aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd/nfs4state.c
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2014-07-30 08:27:08 -0400
committerJ. Bruce Fields <bfields@redhat.com>2014-08-01 16:28:22 -0400
commit6b10ad193d391c295146f23cbe8523e48df78999 (patch)
tree003cec2684d4604671e5a8a81551de9a9a12c1fe /fs/nfsd/nfs4state.c
parentd20c11d86d8f821a64eac7d6c8f296f06d935f4f (diff)
nfsd: Protect nfsd4_destroy_clientid using client_lock
...instead of relying on the client_mutex. Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> Signed-off-by: J. Bruce Fields <bfields@redhat.com>
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r--fs/nfsd/nfs4state.c13
1 files changed, 9 insertions, 4 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index 52a4677f6f35..68383b09c7dc 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -2826,22 +2826,23 @@ nfsd4_sequence_done(struct nfsd4_compoundres *resp)
2826__be32 2826__be32
2827nfsd4_destroy_clientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_destroy_clientid *dc) 2827nfsd4_destroy_clientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_destroy_clientid *dc)
2828{ 2828{
2829 struct nfs4_client *conf, *unconf, *clp; 2829 struct nfs4_client *conf, *unconf;
2830 struct nfs4_client *clp = NULL;
2830 __be32 status = 0; 2831 __be32 status = 0;
2831 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); 2832 struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id);
2832 2833
2833 nfs4_lock_state(); 2834 nfs4_lock_state();
2835 spin_lock(&nn->client_lock);
2834 unconf = find_unconfirmed_client(&dc->clientid, true, nn); 2836 unconf = find_unconfirmed_client(&dc->clientid, true, nn);
2835 conf = find_confirmed_client(&dc->clientid, true, nn); 2837 conf = find_confirmed_client(&dc->clientid, true, nn);
2836 WARN_ON_ONCE(conf && unconf); 2838 WARN_ON_ONCE(conf && unconf);
2837 2839
2838 if (conf) { 2840 if (conf) {
2839 clp = conf;
2840
2841 if (client_has_state(conf)) { 2841 if (client_has_state(conf)) {
2842 status = nfserr_clientid_busy; 2842 status = nfserr_clientid_busy;
2843 goto out; 2843 goto out;
2844 } 2844 }
2845 clp = conf;
2845 } else if (unconf) 2846 } else if (unconf)
2846 clp = unconf; 2847 clp = unconf;
2847 else { 2848 else {
@@ -2849,12 +2850,16 @@ nfsd4_destroy_clientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta
2849 goto out; 2850 goto out;
2850 } 2851 }
2851 if (!mach_creds_match(clp, rqstp)) { 2852 if (!mach_creds_match(clp, rqstp)) {
2853 clp = NULL;
2852 status = nfserr_wrong_cred; 2854 status = nfserr_wrong_cred;
2853 goto out; 2855 goto out;
2854 } 2856 }
2855 expire_client(clp); 2857 unhash_client_locked(clp);
2856out: 2858out:
2859 spin_unlock(&nn->client_lock);
2857 nfs4_unlock_state(); 2860 nfs4_unlock_state();
2861 if (clp)
2862 expire_client(clp);
2858 return status; 2863 return status;
2859} 2864}
2860 2865