Good morning, Dai! > On Feb 23, 2022, at 1:16 PM, Dai Ngo <dai.ngo@xxxxxxxxxx> wrote: > > Update find_clp_in_name_tree: > . skip client with CLIENT_EXPIRED flag; discarded courtesy client. > . if courtesy client was found then clear CLIENT_COURTESY and > set CLIENT_RECONNECTED so callers can take appropriate action. > > Update find_confirmed_client_by_name to discard the courtesy > client; set CLIENT_EXPIRED. > > Update nfsd4_setclientid to expire the confirmed courtesy client > to prevent multiple confirmed clients with the same name on the > the conf_id_hashtbl list. > > Signed-off-by: Dai Ngo <dai.ngo@xxxxxxxxxx> > --- > fs/nfsd/nfs4state.c | 45 ++++++++++++++++++++++++++++++++++++++++++--- > 1 file changed, 42 insertions(+), 3 deletions(-) > > diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c > index 1ffe7bafe90b..4990553180f8 100644 > --- a/fs/nfsd/nfs4state.c > +++ b/fs/nfsd/nfs4state.c > @@ -2834,8 +2834,21 @@ find_clp_in_name_tree(struct xdr_netobj *name, struct rb_root *root) > node = node->rb_left; > else if (cmp < 0) > node = node->rb_right; > - else > + else { > + clear_bit(NFSD4_CLIENT_RECONNECTED, &clp->cl_flags); > + /* sync with thread resolving lock/deleg conflict */ > + spin_lock(&clp->cl_cs_lock); > + if (test_bit(NFSD4_CLIENT_EXPIRED, &clp->cl_flags)) { > + spin_unlock(&clp->cl_cs_lock); > + return NULL; > + } > + if (test_bit(NFSD4_CLIENT_COURTESY, &clp->cl_flags)) { > + clear_bit(NFSD4_CLIENT_COURTESY, &clp->cl_flags); > + set_bit(NFSD4_CLIENT_RECONNECTED, &clp->cl_flags); > + } This should be written if (test_and_clear_bit(NFSD4_CLIENT_COURTESY, &clp->cl_flags)) set_bit(NFSD4_CLIENT_RECONNECTED, &clp->cl_flags); > + spin_unlock(&clp->cl_cs_lock); > return clp; > + } And since this is the same logic that is used in 6/10 and 7/10, please refactor this into a separate function and call it from the find_yada_ functions as we discussed previously. Thanks! > } > return NULL; > } > @@ -2888,6 +2901,14 @@ find_client_in_id_table(struct list_head *tbl, clientid_t *clid, bool sessions) > return NULL; > } > > +static void > +nfsd4_discard_courtesy_clnt(struct nfs4_client *clp) > +{ > + spin_lock(&clp->cl_cs_lock); > + set_bit(NFSD4_CLIENT_EXPIRED, &clp->cl_flags); > + spin_unlock(&clp->cl_cs_lock); > +} > + > static struct nfs4_client * > find_confirmed_client(clientid_t *clid, bool sessions, struct nfsd_net *nn) > { > @@ -2914,8 +2935,15 @@ static bool clp_used_exchangeid(struct nfs4_client *clp) > static struct nfs4_client * > find_confirmed_client_by_name(struct xdr_netobj *name, struct nfsd_net *nn) > { > + struct nfs4_client *clp; > + > lockdep_assert_held(&nn->client_lock); > - return find_clp_in_name_tree(name, &nn->conf_name_tree); > + clp = find_clp_in_name_tree(name, &nn->conf_name_tree); > + if (clp && test_bit(NFSD4_CLIENT_RECONNECTED, &clp->cl_flags)) { > + nfsd4_discard_courtesy_clnt(clp); > + clp = NULL; > + } > + return clp; > } > > static struct nfs4_client * > @@ -4032,12 +4060,19 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, > struct nfs4_client *unconf = NULL; > __be32 status; > struct nfsd_net *nn = net_generic(SVC_NET(rqstp), nfsd_net_id); > + struct nfs4_client *cclient = NULL; > > new = create_client(clname, rqstp, &clverifier); > if (new == NULL) > return nfserr_jukebox; > spin_lock(&nn->client_lock); > - conf = find_confirmed_client_by_name(&clname, nn); > + /* find confirmed client by name */ > + conf = find_clp_in_name_tree(&clname, &nn->conf_name_tree); > + if (conf && test_bit(NFSD4_CLIENT_RECONNECTED, &conf->cl_flags)) { > + cclient = conf; > + conf = NULL; > + } > + > if (conf && client_has_state(conf)) { > status = nfserr_clid_inuse; > if (clp_used_exchangeid(conf)) > @@ -4068,7 +4103,11 @@ nfsd4_setclientid(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, > new = NULL; > status = nfs_ok; > out: > + if (cclient) > + unhash_client_locked(cclient); > spin_unlock(&nn->client_lock); > + if (cclient) > + expire_client(cclient); > if (new) > free_client(new); > if (unconf) { > -- > 2.9.5 > -- Chuck Lever