diff options
| -rw-r--r-- | fs/nfs/inode.c | 5 | ||||
| -rw-r--r-- | fs/nfs/internal.h | 1 | ||||
| -rw-r--r-- | fs/nfs/nfs4proc.c | 2 | ||||
| -rw-r--r-- | fs/nfs/super.c | 49 | ||||
| -rw-r--r-- | fs/nfs/unlink.c | 2 |
5 files changed, 56 insertions, 3 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 5c7325c5c5e6..6fa01aea2488 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c | |||
| @@ -685,7 +685,10 @@ static void __put_nfs_open_context(struct nfs_open_context *ctx, int is_sync) | |||
| 685 | if (ctx->cred != NULL) | 685 | if (ctx->cred != NULL) |
| 686 | put_rpccred(ctx->cred); | 686 | put_rpccred(ctx->cred); |
| 687 | dput(ctx->dentry); | 687 | dput(ctx->dentry); |
| 688 | nfs_sb_deactive(sb); | 688 | if (is_sync) |
| 689 | nfs_sb_deactive(sb); | ||
| 690 | else | ||
| 691 | nfs_sb_deactive_async(sb); | ||
| 689 | kfree(ctx->mdsthreshold); | 692 | kfree(ctx->mdsthreshold); |
| 690 | kfree(ctx); | 693 | kfree(ctx); |
| 691 | } | 694 | } |
diff --git a/fs/nfs/internal.h b/fs/nfs/internal.h index a54fe51c1dfb..05521cadac2e 100644 --- a/fs/nfs/internal.h +++ b/fs/nfs/internal.h | |||
| @@ -351,6 +351,7 @@ extern int __init register_nfs_fs(void); | |||
| 351 | extern void __exit unregister_nfs_fs(void); | 351 | extern void __exit unregister_nfs_fs(void); |
| 352 | extern void nfs_sb_active(struct super_block *sb); | 352 | extern void nfs_sb_active(struct super_block *sb); |
| 353 | extern void nfs_sb_deactive(struct super_block *sb); | 353 | extern void nfs_sb_deactive(struct super_block *sb); |
| 354 | extern void nfs_sb_deactive_async(struct super_block *sb); | ||
| 354 | 355 | ||
| 355 | /* namespace.c */ | 356 | /* namespace.c */ |
| 356 | #define NFS_PATH_CANONICAL 1 | 357 | #define NFS_PATH_CANONICAL 1 |
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index 1465364501ba..8cfbac1a8d5e 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c | |||
| @@ -2197,7 +2197,7 @@ static void nfs4_free_closedata(void *data) | |||
| 2197 | nfs4_put_open_state(calldata->state); | 2197 | nfs4_put_open_state(calldata->state); |
| 2198 | nfs_free_seqid(calldata->arg.seqid); | 2198 | nfs_free_seqid(calldata->arg.seqid); |
| 2199 | nfs4_put_state_owner(sp); | 2199 | nfs4_put_state_owner(sp); |
| 2200 | nfs_sb_deactive(sb); | 2200 | nfs_sb_deactive_async(sb); |
| 2201 | kfree(calldata); | 2201 | kfree(calldata); |
| 2202 | } | 2202 | } |
| 2203 | 2203 | ||
diff --git a/fs/nfs/super.c b/fs/nfs/super.c index 13c2a5be4765..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 | */ |
diff --git a/fs/nfs/unlink.c b/fs/nfs/unlink.c index 13cea637eff8..3f79c77153b8 100644 --- a/fs/nfs/unlink.c +++ b/fs/nfs/unlink.c | |||
| @@ -95,7 +95,7 @@ static void nfs_async_unlink_release(void *calldata) | |||
| 95 | 95 | ||
| 96 | nfs_dec_sillycount(data->dir); | 96 | nfs_dec_sillycount(data->dir); |
| 97 | nfs_free_unlinkdata(data); | 97 | nfs_free_unlinkdata(data); |
| 98 | nfs_sb_deactive(sb); | 98 | nfs_sb_deactive_async(sb); |
| 99 | } | 99 | } |
| 100 | 100 | ||
| 101 | static void nfs_unlink_prepare(struct rpc_task *task, void *calldata) | 101 | static void nfs_unlink_prepare(struct rpc_task *task, void *calldata) |
