aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4recover.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/nfs4recover.c')
-rw-r--r--fs/nfsd/nfs4recover.c53
1 files changed, 41 insertions, 12 deletions
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 29d77f60585b..ed083b9a731b 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -45,6 +45,7 @@
45 45
46/* Globals */ 46/* Globals */
47static struct file *rec_file; 47static struct file *rec_file;
48static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
48 49
49static int 50static int
50nfs4_save_creds(const struct cred **original_creds) 51nfs4_save_creds(const struct cred **original_creds)
@@ -88,7 +89,7 @@ nfs4_make_rec_clidname(char *dname, struct xdr_netobj *clname)
88 struct xdr_netobj cksum; 89 struct xdr_netobj cksum;
89 struct hash_desc desc; 90 struct hash_desc desc;
90 struct scatterlist sg; 91 struct scatterlist sg;
91 __be32 status = nfserr_resource; 92 __be32 status = nfserr_jukebox;
92 93
93 dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n", 94 dprintk("NFSD: nfs4_make_rec_clidname for %.*s\n",
94 clname->len, clname->data); 95 clname->len, clname->data);
@@ -129,6 +130,7 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
129 if (!rec_file || clp->cl_firststate) 130 if (!rec_file || clp->cl_firststate)
130 return 0; 131 return 0;
131 132
133 clp->cl_firststate = 1;
132 status = nfs4_save_creds(&original_cred); 134 status = nfs4_save_creds(&original_cred);
133 if (status < 0) 135 if (status < 0)
134 return status; 136 return status;
@@ -143,10 +145,8 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
143 goto out_unlock; 145 goto out_unlock;
144 } 146 }
145 status = -EEXIST; 147 status = -EEXIST;
146 if (dentry->d_inode) { 148 if (dentry->d_inode)
147 dprintk("NFSD: nfsd4_create_clid_dir: DIRECTORY EXISTS\n");
148 goto out_put; 149 goto out_put;
149 }
150 status = mnt_want_write(rec_file->f_path.mnt); 150 status = mnt_want_write(rec_file->f_path.mnt);
151 if (status) 151 if (status)
152 goto out_put; 152 goto out_put;
@@ -156,12 +156,14 @@ out_put:
156 dput(dentry); 156 dput(dentry);
157out_unlock: 157out_unlock:
158 mutex_unlock(&dir->d_inode->i_mutex); 158 mutex_unlock(&dir->d_inode->i_mutex);
159 if (status == 0) { 159 if (status == 0)
160 clp->cl_firststate = 1;
161 vfs_fsync(rec_file, 0); 160 vfs_fsync(rec_file, 0);
162 } 161 else
162 printk(KERN_ERR "NFSD: failed to write recovery record"
163 " (err %d); please check that %s exists"
164 " and is writeable", status,
165 user_recovery_dirname);
163 nfs4_reset_creds(original_cred); 166 nfs4_reset_creds(original_cred);
164 dprintk("NFSD: nfsd4_create_clid_dir returns %d\n", status);
165 return status; 167 return status;
166} 168}
167 169
@@ -354,13 +356,13 @@ nfsd4_recdir_load(void) {
354 */ 356 */
355 357
356void 358void
357nfsd4_init_recdir(char *rec_dirname) 359nfsd4_init_recdir()
358{ 360{
359 const struct cred *original_cred; 361 const struct cred *original_cred;
360 int status; 362 int status;
361 363
362 printk("NFSD: Using %s as the NFSv4 state recovery directory\n", 364 printk("NFSD: Using %s as the NFSv4 state recovery directory\n",
363 rec_dirname); 365 user_recovery_dirname);
364 366
365 BUG_ON(rec_file); 367 BUG_ON(rec_file);
366 368
@@ -372,10 +374,10 @@ nfsd4_init_recdir(char *rec_dirname)
372 return; 374 return;
373 } 375 }
374 376
375 rec_file = filp_open(rec_dirname, O_RDONLY | O_DIRECTORY, 0); 377 rec_file = filp_open(user_recovery_dirname, O_RDONLY | O_DIRECTORY, 0);
376 if (IS_ERR(rec_file)) { 378 if (IS_ERR(rec_file)) {
377 printk("NFSD: unable to find recovery directory %s\n", 379 printk("NFSD: unable to find recovery directory %s\n",
378 rec_dirname); 380 user_recovery_dirname);
379 rec_file = NULL; 381 rec_file = NULL;
380 } 382 }
381 383
@@ -390,3 +392,30 @@ nfsd4_shutdown_recdir(void)
390 fput(rec_file); 392 fput(rec_file);
391 rec_file = NULL; 393 rec_file = NULL;
392} 394}
395
396/*
397 * Change the NFSv4 recovery directory to recdir.
398 */
399int
400nfs4_reset_recoverydir(char *recdir)
401{
402 int status;
403 struct path path;
404
405 status = kern_path(recdir, LOOKUP_FOLLOW, &path);
406 if (status)
407 return status;
408 status = -ENOTDIR;
409 if (S_ISDIR(path.dentry->d_inode->i_mode)) {
410 strcpy(user_recovery_dirname, recdir);
411 status = 0;
412 }
413 path_put(&path);
414 return status;
415}
416
417char *
418nfs4_recoverydir(void)
419{
420 return user_recovery_dirname;
421}