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 e831bce4976..652d3f7176a 100644 --- a/fs/nfs/super.c +++ b/fs/nfs/super.c @@ -54,6 +54,7 @@  #include <linux/parser.h>  #include <linux/nsproxy.h>  #include <linux/rcupdate.h> +#include <linux/kthread.h>  #include <asm/uaccess.h> @@ -415,6 +416,54 @@ void nfs_sb_deactive(struct super_block *sb)  }  EXPORT_SYMBOL_GPL(nfs_sb_deactive); +static int nfs_deactivate_super_async_work(void *ptr) +{ +	struct super_block *sb = ptr; + +	deactivate_super(sb); +	module_put_and_exit(0); +	return 0; +} + +/* + * same effect as deactivate_super, but will do final unmount in kthread + * context + */ +static void nfs_deactivate_super_async(struct super_block *sb) +{ +	struct task_struct *task; +	char buf[INET6_ADDRSTRLEN + 1]; +	struct nfs_server *server = NFS_SB(sb); +	struct nfs_client *clp = server->nfs_client; + +	if (!atomic_add_unless(&sb->s_active, -1, 1)) { +		rcu_read_lock(); +		snprintf(buf, sizeof(buf), +			rpc_peeraddr2str(clp->cl_rpcclient, RPC_DISPLAY_ADDR)); +		rcu_read_unlock(); + +		__module_get(THIS_MODULE); +		task = kthread_run(nfs_deactivate_super_async_work, sb, +				"%s-deactivate-super", buf); +		if (IS_ERR(task)) { +			pr_err("%s: kthread_run: %ld\n", +				__func__, PTR_ERR(task)); +			/* make synchronous call and hope for the best */ +			deactivate_super(sb); +			module_put(THIS_MODULE); +		} +	} +} + +void nfs_sb_deactive_async(struct super_block *sb) +{ +	struct nfs_server *server = NFS_SB(sb); + +	if (atomic_dec_and_test(&server->active)) +		nfs_deactivate_super_async(sb); +} +EXPORT_SYMBOL_GPL(nfs_sb_deactive_async); +  /*   * Deliver file system statistics to userspace   */ @@ -771,7 +820,7 @@ int nfs_show_devname(struct seq_file *m, struct dentry *root)  	int err = 0;  	if (!page)  		return -ENOMEM; -	devname = nfs_path(&dummy, root, page, PAGE_SIZE); +	devname = nfs_path(&dummy, root, page, PAGE_SIZE, 0);  	if (IS_ERR(devname))  		err = PTR_ERR(devname);  	else  |