diff options
| author | Chuck Lever <chuck.lever@oracle.com> | 2026-04-19 14:53:05 -0400 |
|---|---|---|
| committer | Chuck Lever <chuck.lever@oracle.com> | 2026-05-28 11:31:26 -0400 |
| commit | 6433e35f3632fe6dbf18ad62c9a704f8996471a1 (patch) | |
| tree | 363f27fef57c0b0b37deb8cbb5b997641844267c /fs | |
| parent | 8326af5cde512f0bcf43b670b5042bb405b4bccd (diff) | |
| download | linux-next-history-6433e35f3632fe6dbf18ad62c9a704f8996471a1.tar.gz | |
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>
Diffstat (limited to 'fs')
| -rw-r--r-- | fs/nfsd/nfs4layouts.c | 2 | ||||
| -rw-r--r-- | fs/nfsd/nfs4state.c | 42 | ||||
| -rw-r--r-- | fs/nfsd/state.h | 1 |
3 files changed, 42 insertions, 3 deletions
diff --git a/fs/nfsd/nfs4layouts.c b/fs/nfsd/nfs4layouts.c index c3543d4567024..c550b83f44323 100644 --- a/fs/nfsd/nfs4layouts.c +++ b/fs/nfsd/nfs4layouts.c @@ -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); diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index d96994627ba83..475d2b36ecd17 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -1168,6 +1168,7 @@ out_dec: 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 @@ retry: 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) diff --git a/fs/nfsd/state.h b/fs/nfsd/state.h index c5ccea64c2817..43bd965077e1d 100644 --- a/fs/nfsd/state.h +++ b/fs/nfsd/state.h @@ -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 *); }; |
