NFSD: Track svc_export in nfs4_stid

Add an sc_export field to struct nfs4_stid so that each stateid
records the export under which it was acquired.  The export
reference is taken via exp_get() at stateid creation and released
via exp_put() in nfs4_put_stid().

Open stateids record the export from current_fh->fh_export.
Lock stateids and delegations inherit the export from their
parent open stateid. Layout stateids inherit from their
parent stateid. Directory delegations record the export from
cstate->current_fh.

A subsequent commit uses sc_export to scope state revocation to a
specific export, avoiding the need to walk inode dentry aliases at
revocation time.

Reviewed-by: Jeff Layton <jlayton@kernel.org>
Tested-by: Dai Ngo <dai.ngo@oracle.com>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
This commit is contained in:
Chuck Lever 2026-04-19 14:53:05 -04:00 committed by Chuck Lever
parent 8fc2748835
commit ba0cde5dc8
3 changed files with 42 additions and 3 deletions

View File

@ -234,6 +234,8 @@ nfsd4_alloc_layout_stateid(struct nfsd4_compound_state *cstate,
get_nfs4_file(fp);
stp->sc_file = fp;
if (parent->sc_export)
stp->sc_export = exp_get(parent->sc_export);
ls = layoutstateid(stp);
INIT_LIST_HEAD(&ls->ls_perclnt);

View File

@ -1168,6 +1168,7 @@ alloc_init_deleg(struct nfs4_client *clp, struct nfs4_file *fp,
void
nfs4_put_stid(struct nfs4_stid *s)
{
struct svc_export *exp = s->sc_export;
struct nfs4_file *fp = s->sc_file;
struct nfs4_client *clp = s->sc_client;
@ -1183,6 +1184,8 @@ nfs4_put_stid(struct nfs4_stid *s)
nfs4_free_cpntf_statelist(clp->net, s);
spin_unlock(&clp->cl_lock);
s->sc_free(s);
if (exp)
exp_put(exp);
if (fp)
put_nfs4_file(fp);
}
@ -1763,6 +1766,25 @@ static struct nfs4_stid *find_one_sb_stid(struct nfs4_client *clp,
return stid;
}
/*
* Release the export reference an admin-revoked stateid holds,
* so the svc_export (and its vfsmount) is not pinned until the
* client issues FREE_STATEID. sc_export is no longer consulted
* once SC_STATUS_ADMIN_REVOKED is set.
*/
static void drop_stid_export(struct nfs4_client *clp,
struct nfs4_stid *stid)
{
struct svc_export *exp;
spin_lock(&clp->cl_lock);
exp = stid->sc_export;
stid->sc_export = NULL;
spin_unlock(&clp->cl_lock);
if (exp)
exp_put(exp);
}
static void revoke_ol_stid(struct nfs4_client *clp,
struct nfs4_ol_stateid *stp)
{
@ -1787,6 +1809,7 @@ static void revoke_ol_stid(struct nfs4_client *clp,
}
}
release_all_access(stp);
drop_stid_export(clp, stid);
} else
spin_unlock(&clp->cl_lock);
}
@ -1820,9 +1843,10 @@ static void revoke_one_stid(struct nfsd_net *nn, struct nfs4_client *clp,
if (!unhash_delegation_locked(dp, SC_STATUS_ADMIN_REVOKED))
dp = NULL;
spin_unlock(&nn->deleg_lock);
if (dp)
if (dp) {
revoke_delegation(dp);
else
drop_stid_export(clp, stid);
} else
nfs4_put_stid(stid);
break;
case SC_TYPE_LAYOUT:
@ -1833,6 +1857,7 @@ static void revoke_one_stid(struct nfsd_net *nn, struct nfs4_client *clp,
}
spin_unlock(&clp->cl_lock);
nfsd4_close_layout(layoutstateid(stid));
drop_stid_export(clp, stid);
break;
}
}
@ -6172,6 +6197,8 @@ nfs4_set_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
dp = alloc_init_deleg(clp, fp, odstate, dl_type);
if (!dp)
goto out_delegees;
if (stp->st_stid.sc_export)
dp->dl_stid.sc_export = exp_get(stp->st_stid.sc_export);
fl = nfs4_alloc_init_lease(dp);
if (!fl)
@ -6505,8 +6532,11 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
goto out;
}
if (!open->op_stp)
if (!open->op_stp) {
new_stp = true;
stp->st_stid.sc_export =
exp_get(current_fh->fh_export);
}
}
/*
@ -8202,6 +8232,9 @@ init_lock_stateid(struct nfs4_ol_stateid *stp, struct nfs4_lockowner *lo,
stp->st_stateowner = nfs4_get_stateowner(&lo->lo_owner);
get_nfs4_file(fp);
stp->st_stid.sc_file = fp;
if (open_stp->st_stid.sc_export)
stp->st_stid.sc_export =
exp_get(open_stp->st_stid.sc_export);
stp->st_access_bmap = 0;
stp->st_deny_bmap = open_stp->st_deny_bmap;
stp->st_openstp = open_stp;
@ -9532,6 +9565,9 @@ nfsd_get_dir_deleg(struct nfsd4_compound_state *cstate,
dp = alloc_init_deleg(clp, fp, NULL, NFS4_OPEN_DELEGATE_READ);
if (!dp)
goto out_delegees;
if (cstate->current_fh.fh_export)
dp->dl_stid.sc_export =
exp_get(cstate->current_fh.fh_export);
fl = nfs4_alloc_init_lease(dp);
if (!fl)

View File

@ -145,6 +145,7 @@ struct nfs4_stid {
spinlock_t sc_lock;
struct nfs4_client *sc_client;
struct nfs4_file *sc_file;
struct svc_export *sc_export;
void (*sc_free)(struct nfs4_stid *);
};