diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfsd/netns.h | 2 | ||||
-rw-r--r-- | fs/nfsd/nfs4recover.c | 70 |
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 | ||
89 | extern int nfsd_net_id; | 91 | extern 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 */ |
65 | static struct file *rec_file; | ||
66 | static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery"; | 65 | static char user_recovery_dirname[PATH_MAX] = "/var/lib/nfs/v4recovery"; |
67 | static struct nfsd4_client_tracking_ops *client_tracking_ops; | 66 | static struct nfsd4_client_tracking_ops *client_tracking_ops; |
68 | static bool in_grace; | 67 | static 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 | |||
267 | nfsd4_list_rec_dir(recdir_func *f, struct nfsd_net *nn) | 266 | nfsd4_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 | ||
307 | static int | 306 | static int |
308 | nfsd4_unlink_clid_dir(char *name, int namlen) | 307 | nfsd4_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 | } |
369 | out_drop_write: | 368 | out_drop_write: |
370 | mnt_drop_write_file(rec_file); | 369 | mnt_drop_write_file(nn->rec_file); |
371 | out: | 370 | out: |
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); |
408 | out: | 407 | out: |
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 | ||
415 | static int | 414 | static 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 | ||
447 | static int | 446 | static int |
448 | nfsd4_init_recdir(void) | 447 | nfsd4_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 | ||
546 | static void | 546 | static void |
547 | nfsd4_shutdown_recdir(void) | 547 | nfsd4_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 | ||
555 | static void | 555 | static 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 | ||