aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/nfsd/netns.h2
-rw-r--r--fs/nfsd/nfs4recover.c70
2 files changed, 37 insertions, 35 deletions
diff --git a/fs/nfsd/netns.h b/fs/nfsd/netns.h
index 08d5fa1ce82a..130563210c68 100644
--- a/fs/nfsd/netns.h
+++ b/fs/nfsd/netns.h
@@ -84,6 +84,8 @@ struct nfsd_net {
84 84
85 /* client_lock protects the client lru list and session hash table */ 85 /* client_lock protects the client lru list and session hash table */
86 spinlock_t client_lock; 86 spinlock_t client_lock;
87
88 struct file *rec_file;
87}; 89};
88 90
89extern int nfsd_net_id; 91extern int nfsd_net_id;
diff --git a/fs/nfsd/nfs4recover.c b/fs/nfsd/nfs4recover.c
index 651d5134e74c..3e76d281bba8 100644
--- a/fs/nfsd/nfs4recover.c
+++ b/fs/nfsd/nfs4recover.c
@@ -62,7 +62,6 @@ struct nfsd4_client_tracking_ops {
62}; 62};
63 63
64/* Globals */ 64/* Globals */
65static struct file *rec_file;
66static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery"; 65static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery";
67static struct nfsd4_client_tracking_ops *client_tracking_ops; 66static struct nfsd4_client_tracking_ops *client_tracking_ops;
68static bool in_grace; 67static bool in_grace;
@@ -182,7 +181,7 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
182 181
183 if (test_and_set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 182 if (test_and_set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
184 return; 183 return;
185 if (!rec_file) 184 if (!nn->rec_file)
186 return; 185 return;
187 186
188 status = nfs4_make_rec_clidname(dname, &clp->cl_name); 187 status = nfs4_make_rec_clidname(dname, &clp->cl_name);
@@ -193,11 +192,11 @@ nfsd4_create_clid_dir(struct nfs4_client *clp)
193 if (status < 0) 192 if (status < 0)
194 return; 193 return;
195 194
196 status = mnt_want_write_file(rec_file); 195 status = mnt_want_write_file(nn->rec_file);
197 if (status) 196 if (status)
198 return; 197 return;
199 198
200 dir = rec_file->f_path.dentry; 199 dir = nn->rec_file->f_path.dentry;
201 /* lock the parent */ 200 /* lock the parent */
202 mutex_lock(&dir->d_inode->i_mutex); 201 mutex_lock(&dir->d_inode->i_mutex);
203 202
@@ -227,14 +226,14 @@ out_unlock:
227 if (crp) 226 if (crp)
228 crp->cr_clp = clp; 227 crp->cr_clp = clp;
229 } 228 }
230 vfs_fsync(rec_file, 0); 229 vfs_fsync(nn->rec_file, 0);
231 } else { 230 } else {
232 printk(KERN_ERR "NFSD: failed to write recovery record" 231 printk(KERN_ERR "NFSD: failed to write recovery record"
233 " (err %d); please check that %s exists" 232 " (err %d); please check that %s exists"
234 " and is writeable", status, 233 " and is writeable", status,
235 user_recovery_dirname); 234 user_recovery_dirname);
236 } 235 }
237 mnt_drop_write_file(rec_file); 236 mnt_drop_write_file(nn->rec_file);
238 nfs4_reset_creds(original_cred); 237 nfs4_reset_creds(original_cred);
239} 238}
240 239
@@ -267,7 +266,7 @@ static int
267nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn) 266nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn)
268{ 267{
269 const struct cred *original_cred; 268 const struct cred *original_cred;
270 struct dentry *dir = rec_file->f_path.dentry; 269 struct dentry *dir = nn->rec_file->f_path.dentry;
271 LIST_HEAD(names); 270 LIST_HEAD(names);
272 int status; 271 int status;
273 272
@@ -275,13 +274,13 @@ nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn)
275 if (status < 0) 274 if (status < 0)
276 return status; 275 return status;
277 276
278 status = vfs_llseek(rec_file, 0, SEEK_SET); 277 status = vfs_llseek(nn->rec_file, 0, SEEK_SET);
279 if (status < 0) { 278 if (status < 0) {
280 nfs4_reset_creds(original_cred); 279 nfs4_reset_creds(original_cred);
281 return status; 280 return status;
282 } 281 }
283 282
284 status = vfs_readdir(rec_file, nfsd4_build_namelist, &names); 283 status = vfs_readdir(nn->rec_file, nfsd4_build_namelist, &names);
285 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); 284 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
286 while (!list_empty(&names)) { 285 while (!list_empty(&names)) {
287 struct name_list *entry; 286 struct name_list *entry;
@@ -305,14 +304,14 @@ nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn)
305} 304}
306 305
307static int 306static int
308nfsd4_unlink_clid_dir(char *name, int namlen) 307nfsd4_unlink_clid_dir(char *name, int namlen, struct nfsd_net *nn)
309{ 308{
310 struct dentry *dir, *dentry; 309 struct dentry *dir, *dentry;
311 int status; 310 int status;
312 311
313 dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name); 312 dprintk("NFSD: nfsd4_unlink_clid_dir. name %.*s\n", namlen, name);
314 313
315 dir = rec_file->f_path.dentry; 314 dir = nn->rec_file->f_path.dentry;
316 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT); 315 mutex_lock_nested(&dir->d_inode->i_mutex, I_MUTEX_PARENT);
317 dentry = lookup_one_len(name, dir, namlen); 316 dentry = lookup_one_len(name, dir, namlen);
318 if (IS_ERR(dentry)) { 317 if (IS_ERR(dentry)) {
@@ -339,14 +338,14 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp)
339 int status; 338 int status;
340 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id); 339 struct nfsd_net *nn = net_generic(clp->net, nfsd_net_id);
341 340
342 if (!rec_file || !test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) 341 if (!nn->rec_file || !test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags))
343 return; 342 return;
344 343
345 status = nfs4_make_rec_clidname(dname, &clp->cl_name); 344 status = nfs4_make_rec_clidname(dname, &clp->cl_name);
346 if (status) 345 if (status)
347 return legacy_recdir_name_error(status); 346 return legacy_recdir_name_error(status);
348 347
349 status = mnt_want_write_file(rec_file); 348 status = mnt_want_write_file(nn->rec_file);
350 if (status) 349 if (status)
351 goto out; 350 goto out;
352 clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); 351 clear_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags);
@@ -355,10 +354,10 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp)
355 if (status < 0) 354 if (status < 0)
356 goto out_drop_write; 355 goto out_drop_write;
357 356
358 status = nfsd4_unlink_clid_dir(dname, HEXDIR_LEN-1); 357 status = nfsd4_unlink_clid_dir(dname, HEXDIR_LEN-1, nn);
359 nfs4_reset_creds(original_cred); 358 nfs4_reset_creds(original_cred);
360 if (status == 0) { 359 if (status == 0) {
361 vfs_fsync(rec_file, 0); 360 vfs_fsync(nn->rec_file, 0);
362 if (in_grace) { 361 if (in_grace) {
363 /* remove reclaim record */ 362 /* remove reclaim record */
364 crp = nfsd4_find_reclaim_client(dname, nn); 363 crp = nfsd4_find_reclaim_client(dname, nn);
@@ -367,7 +366,7 @@ nfsd4_remove_clid_dir(struct nfs4_client *clp)
367 } 366 }
368 } 367 }
369out_drop_write: 368out_drop_write:
370 mnt_drop_write_file(rec_file); 369 mnt_drop_write_file(nn->rec_file);
371out: 370out:
372 if (status) 371 if (status)
373 printk("NFSD: Failed to remove expired client state directory" 372 printk("NFSD: Failed to remove expired client state directory"
@@ -396,20 +395,20 @@ nfsd4_recdir_purge_old(struct nfsd_net *nn, time_t boot_time)
396 int status; 395 int status;
397 396
398 in_grace = false; 397 in_grace = false;
399 if (!rec_file) 398 if (!nn->rec_file)
400 return; 399 return;
401 status = mnt_want_write_file(rec_file); 400 status = mnt_want_write_file(nn->rec_file);
402 if (status) 401 if (status)
403 goto out; 402 goto out;
404 status = nfsd4_list_rec_dir(purge_old, nn); 403 status = nfsd4_list_rec_dir(purge_old, nn);
405 if (status == 0) 404 if (status == 0)
406 vfs_fsync(rec_file, 0); 405 vfs_fsync(nn->rec_file, 0);
407 mnt_drop_write_file(rec_file); 406 mnt_drop_write_file(nn->rec_file);
408out: 407out:
409 nfs4_release_reclaim(nn); 408 nfs4_release_reclaim(nn);
410 if (status) 409 if (status)
411 printk("nfsd4: failed to purge old clients from recovery" 410 printk("nfsd4: failed to purge old clients from recovery"
412 " directory %s\n", rec_file->f_path.dentry->d_name.name); 411 " directory %s\n", nn->rec_file->f_path.dentry->d_name.name);
413} 412}
414 413
415static int 414static int
@@ -430,13 +429,13 @@ nfsd4_recdir_load(struct net *net) {
430 int status; 429 int status;
431 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 430 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
432 431
433 if (!rec_file) 432 if (!nn->rec_file)
434 return 0; 433 return 0;
435 434
436 status = nfsd4_list_rec_dir(load_recdir, nn); 435 status = nfsd4_list_rec_dir(load_recdir, nn);
437 if (status) 436 if (status)
438 printk("nfsd4: failed loading clients from recovery" 437 printk("nfsd4: failed loading clients from recovery"
439 " directory %s\n", rec_file->f_path.dentry->d_name.name); 438 " directory %s\n", nn->rec_file->f_path.dentry->d_name.name);
440 return status; 439 return status;
441} 440}
442 441
@@ -445,15 +444,16 @@ nfsd4_recdir_load(struct net *net) {
445 */ 444 */
446 445
447static int 446static int
448nfsd4_init_recdir(void) 447nfsd4_init_recdir(struct net *net)
449{ 448{
449 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
450 const struct cred *original_cred; 450 const struct cred *original_cred;
451 int status; 451 int status;
452 452
453 printk("NFSD: Using %s as the NFSv4 state recovery directory\n", 453 printk("NFSD: Using %s as the NFSv4 state recovery directory\n",
454 user_recovery_dirname); 454 user_recovery_dirname);
455 455
456 BUG_ON(rec_file); 456 BUG_ON(nn->rec_file);
457 457
458 status = nfs4_save_creds(&original_cred); 458 status = nfs4_save_creds(&original_cred);
459 if (status < 0) { 459 if (status < 0) {
@@ -463,12 +463,12 @@ nfsd4_init_recdir(void)
463 return status; 463 return status;
464 } 464 }
465 465
466 rec_file = filp_open(user_recovery_dirname, O_RDONLY | O_DIRECTORY, 0); 466 nn->rec_file = filp_open(user_recovery_dirname, O_RDONLY | O_DIRECTORY, 0);
467 if (IS_ERR(rec_file)) { 467 if (IS_ERR(nn->rec_file)) {
468 printk("NFSD: unable to find recovery directory %s\n", 468 printk("NFSD: unable to find recovery directory %s\n",
469 user_recovery_dirname); 469 user_recovery_dirname);
470 status = PTR_ERR(rec_file); 470 status = PTR_ERR(nn->rec_file);
471 rec_file = NULL; 471 nn->rec_file = NULL;
472 } 472 }
473 473
474 nfs4_reset_creds(original_cred); 474 nfs4_reset_creds(original_cred);
@@ -509,7 +509,7 @@ nfsd4_load_reboot_recovery_data(struct net *net)
509{ 509{
510 int status; 510 int status;
511 511
512 status = nfsd4_init_recdir(); 512 status = nfsd4_init_recdir(net);
513 if (!status) 513 if (!status)
514 status = nfsd4_recdir_load(net); 514 status = nfsd4_recdir_load(net);
515 if (status) 515 if (status)
@@ -544,12 +544,12 @@ err:
544} 544}
545 545
546static void 546static void
547nfsd4_shutdown_recdir(void) 547nfsd4_shutdown_recdir(struct nfsd_net *nn)
548{ 548{
549 if (!rec_file) 549 if (!nn->rec_file)
550 return; 550 return;
551 fput(rec_file); 551 fput(nn->rec_file);
552 rec_file = NULL; 552 nn->rec_file = NULL;
553} 553}
554 554
555static void 555static void
@@ -558,7 +558,7 @@ nfsd4_legacy_tracking_exit(struct net *net)
558 struct nfsd_net *nn = net_generic(net, nfsd_net_id); 558 struct nfsd_net *nn = net_generic(net, nfsd_net_id);
559 559
560 nfs4_release_reclaim(nn); 560 nfs4_release_reclaim(nn);
561 nfsd4_shutdown_recdir(); 561 nfsd4_shutdown_recdir(nn);
562 nfs4_legacy_state_shutdown(net); 562 nfs4_legacy_state_shutdown(net);
563} 563}
564 564