summaryrefslogtreecommitdiffstats
path: root/fs/nfs/inode.c
diff options
context:
space:
mode:
authorWeston Andros Adamson <dros@netapp.com>2012-10-30 17:01:39 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2012-10-31 16:26:26 -0400
commit324d003b0cd82151adbaecefef57b73f7959a469 (patch)
tree9876567e78d72999d47feaf1fc957b3615a18c31 /fs/nfs/inode.c
parent97a54868262da1629a3e65121e65b8e8c4419d9f (diff)
NFS: add nfs_sb_deactive_async to avoid deadlock
Use nfs_sb_deactive_async instead of nfs_sb_deactive when in a workqueue context. This avoids a deadlock where rpc_shutdown_client loops forever in a workqueue kworker context, trying to kill all RPC tasks associated with the client, while one or more of these tasks have already been assigned to the same kworker (and will never run rpc_exit_task). This approach is needed because RPC tasks that have already been assigned to a kworker by queue_work cannot be canceled, as explained in the comment for workqueue.c:insert_wq_barrier. Signed-off-by: Weston Andros Adamson <dros@netapp.com> [Trond: add module_get/put.] Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/inode.c')
-rw-r--r--fs/nfs/inode.c5
1 files changed, 4 insertions, 1 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 5c7325c5c5e..6fa01aea248 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)
if (ctx->cred != NULL)
put_rpccred(ctx->cred);
dput(ctx->dentry);
- nfs_sb_deactive(sb);
+ if (is_sync)
+ nfs_sb_deactive(sb);
+ else
+ nfs_sb_deactive_async(sb);
kfree(ctx->mdsthreshold);
kfree(ctx);
}