Update find_client_in_id_table to: . skip client with CLIENT_EXPIRED; discarded courtesy client . if courtesy client was found then clear CLIENT_COURTESY and set CLIENT_RECONNECTED flag so callers can take appropriate action. Update find_confirmed_client to discard courtesy client. Update lookup_clientid to call find_client_in_id_table directly. Update set_client to create client record for courtesy client. Update find_cpntf_state to discard courtesy client. Signed-off-by: Dai Ngo <dai.ngo@xxxxxxxxxx> --- fs/nfsd/nfs4state.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index 34a59c6f446c..4a5276696afe 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -2921,6 +2921,8 @@ find_client_in_id_table(struct list_head *tbl, clientid_t *clid, bool sessions) if (same_clid(&clp->cl_clientid, clid)) { if ((bool)clp->cl_minorversion != sessions) return NULL; + if (nfs4_is_courtesy_client_expired(clp)) + continue; renew_client_locked(clp); return clp; } @@ -2932,9 +2934,15 @@ static struct nfs4_client * find_confirmed_client(clientid_t *clid, bool sessions, struct nfsd_net *nn) { struct list_head *tbl = nn->conf_id_hashtbl; + struct nfs4_client *clp; lockdep_assert_held(&nn->client_lock); - return find_client_in_id_table(tbl, clid, sessions); + clp = find_client_in_id_table(tbl, clid, sessions); + if (clp && test_bit(NFSD4_CLIENT_RECONNECTED, &clp->cl_flags)) { + nfsd4_discard_courtesy_clnt(clp); + clp = NULL; + } + return clp; } static struct nfs4_client * @@ -4873,9 +4881,10 @@ static struct nfs4_client *lookup_clientid(clientid_t *clid, bool sessions, struct nfsd_net *nn) { struct nfs4_client *found; + struct list_head *tbl = nn->conf_id_hashtbl; spin_lock(&nn->client_lock); - found = find_confirmed_client(clid, sessions, nn); + found = find_client_in_id_table(tbl, clid, sessions); if (found) atomic_inc(&found->cl_rpc_users); spin_unlock(&nn->client_lock); @@ -4900,6 +4909,8 @@ static __be32 set_client(clientid_t *clid, cstate->clp = lookup_clientid(clid, false, nn); if (!cstate->clp) return nfserr_expired; + if (test_bit(NFSD4_CLIENT_RECONNECTED, &cstate->clp->cl_flags)) + nfsd4_client_record_create(cstate->clp); return nfs_ok; } @@ -6219,6 +6230,13 @@ static __be32 find_cpntf_state(struct nfsd_net *nn, stateid_t *st, found = lookup_clientid(&cps->cp_p_clid, true, nn); if (!found) goto out; + if (test_bit(NFSD4_CLIENT_RECONNECTED, &found->cl_flags)) { + nfsd4_discard_courtesy_clnt(found); + if (atomic_dec_and_lock(&found->cl_rpc_users, + &nn->client_lock)) + spin_unlock(&nn->client_lock); + goto out; + } *stid = find_stateid_by_type(found, &cps->cp_p_stateid, NFS4_DELEG_STID|NFS4_OPEN_STID|NFS4_LOCK_STID); -- 2.9.5