diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2014-07-30 08:27:08 -0400 |
---|---|---|
committer | J. Bruce Fields <bfields@redhat.com> | 2014-08-01 16:28:22 -0400 |
commit | 6b10ad193d391c295146f23cbe8523e48df78999 (patch) | |
tree | 003cec2684d4604671e5a8a81551de9a9a12c1fe /fs/nfsd/nfs4state.c | |
parent | d20c11d86d8f821a64eac7d6c8f296f06d935f4f (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.c | 13 |
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 |
2827 | nfsd4_destroy_clientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, struct nfsd4_destroy_clientid *dc) | 2827 | nfsd4_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); |
2856 | out: | 2858 | out: |
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 | ||