diff options
Diffstat (limited to 'fs/nfs/super.c')
-rw-r--r-- | fs/nfs/super.c | 51 |
1 files changed, 50 insertions, 1 deletions
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index e831bce49766..652d3f7176a9 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c | |||
@@ -54,6 +54,7 @@ | |||
54 | #include <linux/parser.h> | 54 | #include <linux/parser.h> |
55 | #include <linux/nsproxy.h> | 55 | #include <linux/nsproxy.h> |
56 | #include <linux/rcupdate.h> | 56 | #include <linux/rcupdate.h> |
57 | #include <linux/kthread.h> | ||
57 | 58 | ||
58 | #include <asm/uaccess.h> | 59 | #include <asm/uaccess.h> |
59 | 60 | ||
@@ -415,6 +416,54 @@ void nfs_sb_deactive(struct super_block *sb) | |||
415 | } | 416 | } |
416 | EXPORT_SYMBOL_GPL(nfs_sb_deactive); | 417 | EXPORT_SYMBOL_GPL(nfs_sb_deactive); |
417 | 418 | ||
419 | static int nfs_deactivate_super_async_work(void *ptr) | ||
420 | { | ||
421 | struct super_block *sb = ptr; | ||
422 | |||
423 | deactivate_super(sb); | ||
424 | module_put_and_exit(0); | ||
425 | return 0; | ||
426 | } | ||
427 | |||
428 | /* | ||
429 | * same effect as deactivate_super, but will do final unmount in kthread | ||
430 | * context | ||
431 | */ | ||
432 | static void nfs_deactivate_super_async(struct super_block *sb) | ||
433 | { | ||
434 | struct task_struct *task; | ||
435 | char buf[INET6_ADDRSTRLEN + 1]; | ||
436 | struct nfs_server *server = NFS_SB(sb); | ||
437 | struct nfs_client *clp = server->nfs_client; | ||
438 | |||
439 | if (!atomic_add_unless(&sb->s_active, -1, 1)) { | ||
440 | rcu_read_lock(); | ||
441 | snprintf(buf, sizeof(buf), | ||
442 | rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR)); | ||
443 | rcu_read_unlock(); | ||
444 | |||
445 | __module_get(THIS_MODULE); | ||
446 | task = kthread_run(nfs_deactivate_super_async_work, sb, | ||
447 | "%s-deactivate-super", buf); | ||
448 | if (IS_ERR(task)) { | ||
449 | pr_err("%s: kthread_run: %ld\n", | ||
450 | __func__, PTR_ERR(task)); | ||
451 | /* make synchronous call and hope for the best */ | ||
452 | deactivate_super(sb); | ||
453 | module_put(THIS_MODULE); | ||
454 | } | ||
455 | } | ||
456 | } | ||
457 | |||
458 | void nfs_sb_deactive_async(struct super_block *sb) | ||
459 | { | ||
460 | struct nfs_server *server = NFS_SB(sb); | ||
461 | |||
462 | if (atomic_dec_and_test(&server->active)) | ||
463 | nfs_deactivate_super_async(sb); | ||
464 | } | ||
465 | EXPORT_SYMBOL_GPL(nfs_sb_deactive_async); | ||
466 | |||
418 | /* | 467 | /* |
419 | * Deliver file system statistics to userspace | 468 | * Deliver file system statistics to userspace |
420 | */ | 469 | */ |
@@ -771,7 +820,7 @@ int nfs_show_devname(struct seq_file *m, struct dentry *root) | |||
771 | int err = 0; | 820 | int err = 0; |
772 | if (!page) | 821 | if (!page) |
773 | return -ENOMEM; | 822 | return -ENOMEM; |
774 | devname = nfs_path(&dummy, root, page, PAGE_SIZE); | 823 | devname = nfs_path(&dummy, root, page, PAGE_SIZE, 0); |
775 | if (IS_ERR(devname)) | 824 | if (IS_ERR(devname)) |
776 | err = PTR_ERR(devname); | 825 | err = PTR_ERR(devname); |
777 | else | 826 | else |