浏览代码

knfsd: don't shutdown callbacks until nfsv4 client is freed

If a callback still holds a reference on the client, then it may be
about to perform an rpc call, so it isn't safe to call rpc_shutdown().
(Though rpc_shutdown() does wait for any outstanding rpc's, it can't
know if a new rpc is about to be issued with that client.)

So, wait to shutdown the rpc_client until the reference count on the
client has gone to zero.

Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
J. Bruce Fields 18 年之前
父节点
当前提交
1b1a9b3163
共有 1 个文件被更改,包括 13 次插入14 次删除
  1. 13 14
      fs/nfsd/nfs4state.c

+ 13 - 14
fs/nfsd/nfs4state.c

@@ -358,9 +358,22 @@ alloc_client(struct xdr_netobj name)
 	return clp;
 }
 
+static void
+shutdown_callback_client(struct nfs4_client *clp)
+{
+	struct rpc_clnt *clnt = clp->cl_callback.cb_client;
+
+	/* shutdown rpc client, ending any outstanding recall rpcs */
+	if (clnt) {
+		clp->cl_callback.cb_client = NULL;
+		rpc_shutdown_client(clnt);
+	}
+}
+
 static inline void
 free_client(struct nfs4_client *clp)
 {
+	shutdown_callback_client(clp);
 	if (clp->cl_cred.cr_group_info)
 		put_group_info(clp->cl_cred.cr_group_info);
 	kfree(clp->cl_name.data);
@@ -374,18 +387,6 @@ put_nfs4_client(struct nfs4_client *clp)
 		free_client(clp);
 }
 
-static void
-shutdown_callback_client(struct nfs4_client *clp)
-{
-	struct rpc_clnt *clnt = clp->cl_callback.cb_client;
-
-	/* shutdown rpc client, ending any outstanding recall rpcs */
-	if (clnt) {
-		clp->cl_callback.cb_client = NULL;
-		rpc_shutdown_client(clnt);
-	}
-}
-
 static void
 expire_client(struct nfs4_client *clp)
 {
@@ -396,8 +397,6 @@ expire_client(struct nfs4_client *clp)
 	dprintk("NFSD: expire_client cl_count %d\n",
 	                    atomic_read(&clp->cl_count));
 
-	shutdown_callback_client(clp);
-
 	INIT_LIST_HEAD(&reaplist);
 	spin_lock(&recall_lock);
 	while (!list_empty(&clp->cl_delegations)) {