Commit 0964a3d3f1aa96468091924f6b0c391a46dc6d0b

Authored by NeilBrown
Committed by Linus Torvalds
1 parent c7b9a45927

[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
... ... @@ -50,7 +50,6 @@
50 50 #define NFSDDBG_FACILITY NFSDDBG_PROC
51 51  
52 52 /* Globals */
53   -char recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
54 53 static struct nameidata rec_dir;
55 54 static int rec_dir_init = 0;
56 55  
... ... @@ -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 /*
... ... @@ -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 /*