Commit 0964a3d3f1aa96468091924f6b0c391a46dc6d0b
Committed by
Linus Torvalds
1 parent
c7b9a45927
Exists in
master
and in
7 other branches
[PATCH] knfsd: nfsd4 reboot dirname fix
Set the recovery directory via /proc/fs/nfsd/nfs4recoverydir. It may be changed any time, but is used only on startup. Signed-off-by: Andy Adamson <andros@citi.umich.edu> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu> Signed-off-by: Neil Brown <neilb@cse.unsw.edu.au> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Showing 4 changed files with 60 additions and 3 deletions Side-by-side Diff
fs/nfsd/nfs4recover.c
fs/nfsd/nfs4state.c
... | ... | @@ -48,6 +48,7 @@ |
48 | 48 | #include <linux/nfs4.h> |
49 | 49 | #include <linux/nfsd/state.h> |
50 | 50 | #include <linux/nfsd/xdr4.h> |
51 | +#include <linux/namei.h> | |
51 | 52 | |
52 | 53 | #define NFSDDBG_FACILITY NFSDDBG_PROC |
53 | 54 | |
... | ... | @@ -71,7 +72,8 @@ |
71 | 72 | static struct nfs4_stateid * find_stateid(stateid_t *stid, int flags); |
72 | 73 | static struct nfs4_delegation * find_delegation_stateid(struct inode *ino, stateid_t *stid); |
73 | 74 | static void release_stateid_lockowners(struct nfs4_stateid *open_stp); |
74 | -extern char recovery_dirname[]; | |
75 | +static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery"; | |
76 | +static void nfs4_set_recdir(char *recdir); | |
75 | 77 | |
76 | 78 | /* Locking: |
77 | 79 | * |
78 | 80 | |
... | ... | @@ -3224,8 +3226,10 @@ |
3224 | 3226 | { |
3225 | 3227 | int status; |
3226 | 3228 | |
3227 | - nfsd4_init_recdir(recovery_dirname); | |
3229 | + nfs4_lock_state(); | |
3230 | + nfsd4_init_recdir(user_recovery_dirname); | |
3228 | 3231 | status = nfsd4_recdir_load(); |
3232 | + nfs4_unlock_state(); | |
3229 | 3233 | if (status) |
3230 | 3234 | printk("NFSD: Failure reading reboot recovery data\n"); |
3231 | 3235 | } |
... | ... | @@ -3327,6 +3331,35 @@ |
3327 | 3331 | __nfs4_state_shutdown(); |
3328 | 3332 | nfsd4_free_slabs(); |
3329 | 3333 | nfs4_unlock_state(); |
3334 | +} | |
3335 | + | |
3336 | +static void | |
3337 | +nfs4_set_recdir(char *recdir) | |
3338 | +{ | |
3339 | + nfs4_lock_state(); | |
3340 | + strcpy(user_recovery_dirname, recdir); | |
3341 | + nfs4_unlock_state(); | |
3342 | +} | |
3343 | + | |
3344 | +/* | |
3345 | + * Change the NFSv4 recovery directory to recdir. | |
3346 | + */ | |
3347 | +int | |
3348 | +nfs4_reset_recoverydir(char *recdir) | |
3349 | +{ | |
3350 | + int status; | |
3351 | + struct nameidata nd; | |
3352 | + | |
3353 | + status = path_lookup(recdir, LOOKUP_FOLLOW, &nd); | |
3354 | + if (status) | |
3355 | + return status; | |
3356 | + status = -ENOTDIR; | |
3357 | + if (S_ISDIR(nd.dentry->d_inode->i_mode)) { | |
3358 | + nfs4_set_recdir(recdir); | |
3359 | + status = 0; | |
3360 | + } | |
3361 | + path_release(&nd); | |
3362 | + return status; | |
3330 | 3363 | } |
3331 | 3364 | |
3332 | 3365 | /* |
fs/nfsd/nfsctl.c
... | ... | @@ -51,6 +51,7 @@ |
51 | 51 | NFSD_Fh, |
52 | 52 | NFSD_Threads, |
53 | 53 | NFSD_Leasetime, |
54 | + NFSD_RecoveryDir, | |
54 | 55 | }; |
55 | 56 | |
56 | 57 | /* |
... | ... | @@ -66,6 +67,7 @@ |
66 | 67 | static ssize_t write_filehandle(struct file *file, char *buf, size_t size); |
67 | 68 | static ssize_t write_threads(struct file *file, char *buf, size_t size); |
68 | 69 | static ssize_t write_leasetime(struct file *file, char *buf, size_t size); |
70 | +static ssize_t write_recoverydir(struct file *file, char *buf, size_t size); | |
69 | 71 | |
70 | 72 | static ssize_t (*write_op[])(struct file *, char *, size_t) = { |
71 | 73 | [NFSD_Svc] = write_svc, |
... | ... | @@ -78,6 +80,7 @@ |
78 | 80 | [NFSD_Fh] = write_filehandle, |
79 | 81 | [NFSD_Threads] = write_threads, |
80 | 82 | [NFSD_Leasetime] = write_leasetime, |
83 | + [NFSD_RecoveryDir] = write_recoverydir, | |
81 | 84 | }; |
82 | 85 | |
83 | 86 | static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos) |
... | ... | @@ -349,6 +352,25 @@ |
349 | 352 | return strlen(buf); |
350 | 353 | } |
351 | 354 | |
355 | +static ssize_t write_recoverydir(struct file *file, char *buf, size_t size) | |
356 | +{ | |
357 | + char *mesg = buf; | |
358 | + char *recdir; | |
359 | + int len, status; | |
360 | + | |
361 | + if (size > PATH_MAX || buf[size-1] != '\n') | |
362 | + return -EINVAL; | |
363 | + buf[size-1] = 0; | |
364 | + | |
365 | + recdir = mesg; | |
366 | + len = qword_get(&mesg, recdir, size); | |
367 | + if (len <= 0) | |
368 | + return -EINVAL; | |
369 | + | |
370 | + status = nfs4_reset_recoverydir(recdir); | |
371 | + return strlen(buf); | |
372 | +} | |
373 | + | |
352 | 374 | /*----------------------------------------------------------------------------*/ |
353 | 375 | /* |
354 | 376 | * populating the filesystem. |
... | ... | @@ -369,6 +391,7 @@ |
369 | 391 | [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR}, |
370 | 392 | #ifdef CONFIG_NFSD_V4 |
371 | 393 | [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR}, |
394 | + [NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR}, | |
372 | 395 | #endif |
373 | 396 | /* last one */ {""} |
374 | 397 | }; |
include/linux/nfsd/nfsd.h
... | ... | @@ -150,12 +150,14 @@ |
150 | 150 | void nfs4_state_shutdown(void); |
151 | 151 | time_t nfs4_lease_time(void); |
152 | 152 | void nfs4_reset_lease(time_t leasetime); |
153 | +int nfs4_reset_recoverydir(char *recdir); | |
153 | 154 | #else |
154 | 155 | static inline void nfs4_state_init(void){}; |
155 | 156 | static inline int nfs4_state_start(void){return 0;} |
156 | 157 | static inline void nfs4_state_shutdown(void){} |
157 | 158 | static inline time_t nfs4_lease_time(void){return 0;} |
158 | 159 | static inline void nfs4_reset_lease(time_t leasetime){} |
160 | +static inline int nfs4_reset_recoverydir(char *recdir) {return 0;} | |
159 | 161 | #endif |
160 | 162 | |
161 | 163 | /* |