diff options
author | J. Bruce Fields <bfields@citi.umich.edu> | 2007-09-12 12:43:59 (GMT) |
---|---|---|
committer | J. Bruce Fields <bfields@citi.umich.edu> | 2007-10-09 22:31:57 (GMT) |
commit | 1b1a9b3163a83f52ea2ac333846d4dfd2c4edd90 (patch) | |
tree | bfaaa512b4efa08bed800330f654ba9637dd2f58 /fs/nfsd/nfs4state.c | |
parent | 0272e1fd9f4fa8a43357c168e081744f99e67195 (diff) | |
download | linux-1b1a9b3163a83f52ea2ac333846d4dfd2c4edd90.tar.xz |
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>
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r-- | fs/nfsd/nfs4state.c | 27 |
1 files changed, 13 insertions, 14 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 48fbdac..e706c69 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)) { |