From 0964a3d3f1aa96468091924f6b0c391a46dc6d0b Mon Sep 17 00:00:00 2001 From: NeilBrown Date: Thu, 23 Jun 2005 22:04:32 -0700 Subject: [PATCH] [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 Signed-off-by: J. Bruce Fields Signed-off-by: Neil Brown Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/nfsd/nfs4recover.c | 1 - fs/nfsd/nfs4state.c | 37 +++++++++++++++++++++++++++++++++++-- fs/nfsd/nfsctl.c | 23 +++++++++++++++++++++++ include/linux/nfsd/nfsd.h | 2 ++ 4 files changed, 60 insertions(+), 3 deletions(-) diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c index 2805c5245ea..095f1740f3a 100644 --- a/fs/nfsd/nfs4recover.c +++ b/fs/nfsd/nfs4recover.c @@ -50,7 +50,6 @@ #define NFSDDBG_FACILITY NFSDDBG_PROC /* Globals */ -char recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery"; static struct nameidata rec_dir; static int rec_dir_init = 0; diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 6cca358cd65..89e36526d7f 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -48,6 +48,7 @@ #include #include #include +#include #define NFSDDBG_FACILITY NFSDDBG_PROC @@ -71,7 +72,8 @@ static stateid_t onestateid; /* bits all 1 */ static struct nfs4_stateid * find_stateid(stateid_t *stid, int flags); static struct nfs4_delegation * find_delegation_stateid(struct inode *ino, stateid_t *stid); static void release_stateid_lockowners(struct nfs4_stateid *open_stp); -extern char recovery_dirname[]; +static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery"; +static void nfs4_set_recdir(char *recdir); /* Locking: * @@ -3224,8 +3226,10 @@ nfsd4_load_reboot_recovery_data(void) { int status; - nfsd4_init_recdir(recovery_dirname); + nfs4_lock_state(); + nfsd4_init_recdir(user_recovery_dirname); status = nfsd4_recdir_load(); + nfs4_unlock_state(); if (status) printk("NFSD: Failure reading reboot recovery data\n"); } @@ -3329,6 +3333,35 @@ nfs4_state_shutdown(void) nfs4_unlock_state(); } +static void +nfs4_set_recdir(char *recdir) +{ + nfs4_lock_state(); + strcpy(user_recovery_dirname, recdir); + nfs4_unlock_state(); +} + +/* + * Change the NFSv4 recovery directory to recdir. + */ +int +nfs4_reset_recoverydir(char *recdir) +{ + int status; + struct nameidata nd; + + status = path_lookup(recdir, LOOKUP_FOLLOW, &nd); + if (status) + return status; + status = -ENOTDIR; + if (S_ISDIR(nd.dentry->d_inode->i_mode)) { + nfs4_set_recdir(recdir); + status = 0; + } + path_release(&nd); + return status; +} + /* * Called when leasetime is changed. * diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c index 3da43a3ed32..841c562991e 100644 --- a/fs/nfsd/nfsctl.c +++ b/fs/nfsd/nfsctl.c @@ -51,6 +51,7 @@ enum { NFSD_Fh, NFSD_Threads, NFSD_Leasetime, + NFSD_RecoveryDir, }; /* @@ -66,6 +67,7 @@ static ssize_t write_getfs(struct file *file, char *buf, size_t size); static ssize_t write_filehandle(struct file *file, char *buf, size_t size); static ssize_t write_threads(struct file *file, char *buf, size_t size); static ssize_t write_leasetime(struct file *file, char *buf, size_t size); +static ssize_t write_recoverydir(struct file *file, char *buf, size_t size); static ssize_t (*write_op[])(struct file *, char *, size_t) = { [NFSD_Svc] = write_svc, @@ -78,6 +80,7 @@ static ssize_t (*write_op[])(struct file *, char *, size_t) = { [NFSD_Fh] = write_filehandle, [NFSD_Threads] = write_threads, [NFSD_Leasetime] = write_leasetime, + [NFSD_RecoveryDir] = write_recoverydir, }; static ssize_t nfsctl_transaction_write(struct file *file, const char __user *buf, size_t size, loff_t *pos) @@ -349,6 +352,25 @@ static ssize_t write_leasetime(struct file *file, char *buf, size_t size) return strlen(buf); } +static ssize_t write_recoverydir(struct file *file, char *buf, size_t size) +{ + char *mesg = buf; + char *recdir; + int len, status; + + if (size > PATH_MAX || buf[size-1] != '\n') + return -EINVAL; + buf[size-1] = 0; + + recdir = mesg; + len = qword_get(&mesg, recdir, size); + if (len <= 0) + return -EINVAL; + + status = nfs4_reset_recoverydir(recdir); + return strlen(buf); +} + /*----------------------------------------------------------------------------*/ /* * populating the filesystem. @@ -369,6 +391,7 @@ static int nfsd_fill_super(struct super_block * sb, void * data, int silent) [NFSD_Threads] = {"threads", &transaction_ops, S_IWUSR|S_IRUSR}, #ifdef CONFIG_NFSD_V4 [NFSD_Leasetime] = {"nfsv4leasetime", &transaction_ops, S_IWUSR|S_IRUSR}, + [NFSD_RecoveryDir] = {"nfsv4recoverydir", &transaction_ops, S_IWUSR|S_IRUSR}, #endif /* last one */ {""} }; diff --git a/include/linux/nfsd/nfsd.h b/include/linux/nfsd/nfsd.h index 21c6e9d86e4..5791dfd30dd 100644 --- a/include/linux/nfsd/nfsd.h +++ b/include/linux/nfsd/nfsd.h @@ -150,12 +150,14 @@ int nfs4_state_start(void); void nfs4_state_shutdown(void); time_t nfs4_lease_time(void); void nfs4_reset_lease(time_t leasetime); +int nfs4_reset_recoverydir(char *recdir); #else static inline void nfs4_state_init(void){}; static inline int nfs4_state_start(void){return 0;} static inline void nfs4_state_shutdown(void){} static inline time_t nfs4_lease_time(void){return 0;} static inline void nfs4_reset_lease(time_t leasetime){} +static inline int nfs4_reset_recoverydir(char *recdir) {return 0;} #endif /* -- 2.20.1