summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@citi.umich.edu>2007-09-12 08:43:59 -0400
committerJ. Bruce Fields <bfields@citi.umich.edu>2007-10-09 18:31:57 -0400
commit1b1a9b3163a83f52ea2ac333846d4dfd2c4edd90 (patch)
treebfaaa512b4efa08bed800330f654ba9637dd2f58
parent0272e1fd9f4fa8a43357c168e081744f99e67195 (diff)
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>
-rw-r--r--fs/nfsd/nfs4state.c27
1 files changed, 13 insertions, 14 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 48fbdac33c7..e706c696169 100644
--- a/fs/nfsd/nfs4state.c
+++ b/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);
@@ -375,18 +388,6 @@ put_nfs4_client(struct nfs4_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)
{
struct nfs4_stateowner *sop;
@@ -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)) {