diff options
Diffstat (limited to 'fs/nfsd/nfs4state.c')
-rw-r--r-- | fs/nfsd/nfs4state.c | 45 |
1 files changed, 28 insertions, 17 deletions
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index a0a2b535b0e0..8be612abd0d7 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -2069,7 +2069,8 @@ nfsd4_reclaim_complete(struct svc_rqst *rqstp, struct nfsd4_compound_state *csta nfs4_lock_state(); status = nfserr_complete_already; - if (cstate->session->se_client->cl_firststate) + if (test_and_set_bit(NFSD4_CLIENT_RECLAIM_COMPLETE, + &cstate->session->se_client->cl_flags)) goto out; status = nfserr_stale_clientid; @@ -2816,12 +2817,6 @@ static void nfs4_set_claim_prev(struct nfsd4_open *open, bool has_session) { open->op_openowner->oo_flags |= NFS4_OO_CONFIRMED; - /* - * On a 4.1+ client, we don't create a state record for a client - * until it performs RECLAIM_COMPLETE: - */ - if (!has_session) - open->op_openowner->oo_owner.so_client->cl_firststate = 1; } /* Should we give out recallable state?: */ @@ -4462,7 +4457,7 @@ nfs4_has_reclaimed_state(const char *name, bool use_exchange_id) clp = find_confirmed_client_by_str(name, strhashval); if (!clp) return 0; - return clp->cl_firststate; + return test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); } /* @@ -4507,18 +4502,11 @@ nfs4_release_reclaim(void) /* * called from OPEN, CLAIM_PREVIOUS with a new clientid. */ static struct nfs4_client_reclaim * -nfs4_find_reclaim_client(clientid_t *clid) +nfsd4_find_reclaim_client(struct nfs4_client *clp) { unsigned int strhashval; - struct nfs4_client *clp; struct nfs4_client_reclaim *crp = NULL; - - /* find clientid in conf_id_hashtbl */ - clp = find_confirmed_client(clid); - if (clp == NULL) - return NULL; - dprintk("NFSD: nfs4_find_reclaim_client for %.*s with recdir %s\n", clp->cl_name.len, clp->cl_name.data, clp->cl_recdir); @@ -4533,13 +4521,36 @@ nfs4_find_reclaim_client(clientid_t *clid) return NULL; } +static int +nfsd4_client_record_check(struct nfs4_client *clp) +{ + /* did we already find that this client is stable? */ + if (test_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags)) + return 0; + + /* look for it in the reclaim hashtable otherwise */ + if (nfsd4_find_reclaim_client(clp)) { + set_bit(NFSD4_CLIENT_STABLE, &clp->cl_flags); + return 0; + } + + return -ENOENT; +} + /* * Called from OPEN. Look for clientid in reclaim list. */ __be32 nfs4_check_open_reclaim(clientid_t *clid) { - return nfs4_find_reclaim_client(clid) ? nfs_ok : nfserr_reclaim_bad; + struct nfs4_client *clp; + + /* find clientid in conf_id_hashtbl */ + clp = find_confirmed_client(clid); + if (clp == NULL) + return nfserr_reclaim_bad; + + return nfsd4_client_record_check(clp) ? nfserr_reclaim_bad : nfs_ok; } #ifdef CONFIG_NFSD_FAULT_INJECTION |