Linux NFS development
 help / color / mirror / Atom feed
From: NeilBrown <neilb@ownmail.net>
To: Chuck Lever <chuck.lever@oracle.com>, Jeff Layton <jlayton@kernel.org>
Cc: Olga Kornievskaia <okorniev@redhat.com>,
	Dai Ngo <Dai.Ngo@oracle.com>, Tom Talpey <tom@talpey.com>,
	linux-nfs@vger.kernel.org
Subject: [PATCH v6 08/14] nfsd: pass parent_fh explicitly to nfsd4_process_open2()
Date: Sat, 22 Nov 2025 11:47:06 +1100	[thread overview]
Message-ID: <20251122005236.3440177-9-neilb@ownmail.net> (raw)
In-Reply-To: <20251122005236.3440177-1-neilb@ownmail.net>

From: NeilBrown <neil@brown.name>

nfsd4_process_open2() sometimes needs the filehandle of the parent of
the created file.  This is passed to nfs4_set_delegation() to verify
that the parent is unchanged after the delegation is obtained.

Currently nfsd4_process_open2() knows that the parent is
cstate->current_fh but that will change in the next patch.

So with this patch we take a copy of current_fh earlier in the one case
(NFS4_OPEN_CLAIM_NULL) where it is needed and before any lookup happens.

nfs4_open_delegation() currently uses "currentfh" (which is the parent)
to pass to nfs4_delegation_stat().  As nfs4_delegation_stat() only wants
the vfsmount, it can equally well use "fh" which is the filehandle for the
newly created file - it must be on the same filesystem.

Signed-off-by: NeilBrown <neil@brown.name>
---
 fs/nfsd/nfs4proc.c  |  8 ++++++--
 fs/nfsd/nfs4state.c | 25 ++++++++++++-------------
 fs/nfsd/xdr4.h      |  4 +++-
 3 files changed, 21 insertions(+), 16 deletions(-)

diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
index bd7ba5df07a7..0c13c75e4092 100644
--- a/fs/nfsd/nfs4proc.c
+++ b/fs/nfsd/nfs4proc.c
@@ -538,6 +538,7 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 	struct nfsd4_open *open = &u->open;
 	__be32 status;
 	struct svc_fh *resfh = NULL;
+	struct svc_fh parent_fh = {};
 	struct net *net = SVC_NET(rqstp);
 	struct nfsd_net *nn = net_generic(net, nfsd_net_id);
 	bool reclaim = false;
@@ -601,8 +602,10 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 		goto out;
 
 	switch (open->op_claim_type) {
-	case NFS4_OPEN_CLAIM_DELEGATE_CUR:
 	case NFS4_OPEN_CLAIM_NULL:
+		fh_dup2(&parent_fh, &cstate->current_fh);
+		fallthrough;
+	case NFS4_OPEN_CLAIM_DELEGATE_CUR:
 		status = do_open_lookup(rqstp, cstate, open, &resfh);
 		if (status)
 			goto out;
@@ -630,7 +633,8 @@ nfsd4_open(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate,
 		goto out;
 	}
 
-	status = nfsd4_process_open2(rqstp, resfh, open);
+	status = nfsd4_process_open2(rqstp, resfh, &parent_fh, open);
+	fh_put(&parent_fh);
 	if (status && open->op_created)
 		pr_warn("nfsd4_process_open2 failed to open newly-created file: status=%u\n",
 			be32_to_cpu(status));
diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c
index f10c22d02735..3aebe90a12ec 100644
--- a/fs/nfsd/nfs4state.c
+++ b/fs/nfsd/nfs4state.c
@@ -6046,7 +6046,7 @@ static bool nfsd4_want_deleg_timestamps(const struct nfsd4_open *open)
 
 static struct nfs4_delegation *
 nfs4_set_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
-		    struct svc_fh *parent)
+		    struct svc_fh *parent_fh)
 {
 	bool deleg_ts = nfsd4_want_deleg_timestamps(open);
 	struct nfs4_client *clp = stp->st_stid.sc_client;
@@ -6146,8 +6146,8 @@ nfs4_set_delegation(struct nfsd4_open *open, struct nfs4_ol_stateid *stp,
 	if (status)
 		goto out_clnt_odstate;
 
-	if (parent) {
-		status = nfsd4_verify_deleg_dentry(open, fp, parent);
+	if (parent_fh && parent_fh->fh_dentry) {
+		status = nfsd4_verify_deleg_dentry(open, fp, parent_fh);
 		if (status)
 			goto out_unlock;
 	}
@@ -6288,13 +6288,12 @@ nfsd4_add_rdaccess_to_wrdeleg(struct svc_rqst *rqstp, struct nfsd4_open *open,
  */
 static void
 nfs4_open_delegation(struct svc_rqst *rqstp, struct nfsd4_open *open,
-		     struct nfs4_ol_stateid *stp, struct svc_fh *currentfh,
+		     struct nfs4_ol_stateid *stp, struct svc_fh *parent_fh,
 		     struct svc_fh *fh)
 {
 	struct nfs4_openowner *oo = openowner(stp->st_stateowner);
 	bool deleg_ts = nfsd4_want_deleg_timestamps(open);
 	struct nfs4_client *clp = stp->st_stid.sc_client;
-	struct svc_fh *parent = NULL;
 	struct nfs4_delegation *dp;
 	struct kstat stat;
 	int status = 0;
@@ -6308,8 +6307,6 @@ nfs4_open_delegation(struct svc_rqst *rqstp, struct nfsd4_open *open,
 				open->op_recall = true;
 			break;
 		case NFS4_OPEN_CLAIM_NULL:
-			parent = currentfh;
-			fallthrough;
 		case NFS4_OPEN_CLAIM_FH:
 			/*
 			 * Let's not give out any delegations till everyone's
@@ -6327,7 +6324,7 @@ nfs4_open_delegation(struct svc_rqst *rqstp, struct nfsd4_open *open,
 		default:
 			goto out_no_deleg;
 	}
-	dp = nfs4_set_delegation(open, stp, parent);
+	dp = nfs4_set_delegation(open, stp, parent_fh);
 	if (IS_ERR(dp))
 		goto out_no_deleg;
 
@@ -6337,7 +6334,7 @@ nfs4_open_delegation(struct svc_rqst *rqstp, struct nfsd4_open *open,
 		struct file *f = dp->dl_stid.sc_file->fi_deleg_file->nf_file;
 
 		if (!nfsd4_add_rdaccess_to_wrdeleg(rqstp, open, fh, stp) ||
-				!nfs4_delegation_stat(dp, currentfh, &stat)) {
+				!nfs4_delegation_stat(dp, fh, &stat)) {
 			nfs4_put_stid(&dp->dl_stid);
 			destroy_delegation(dp);
 			goto out_no_deleg;
@@ -6354,7 +6351,7 @@ nfs4_open_delegation(struct svc_rqst *rqstp, struct nfsd4_open *open,
 		spin_unlock(&f->f_lock);
 		trace_nfsd_deleg_write(&dp->dl_stid.sc_stateid);
 	} else {
-		open->op_delegate_type = deleg_ts && nfs4_delegation_stat(dp, currentfh, &stat) ?
+		open->op_delegate_type = deleg_ts && nfs4_delegation_stat(dp, fh, &stat) ?
 					 OPEN_DELEGATE_READ_ATTRS_DELEG : OPEN_DELEGATE_READ;
 		dp->dl_atime = stat.atime;
 		trace_nfsd_deleg_read(&dp->dl_stid.sc_stateid);
@@ -6403,6 +6400,7 @@ static bool open_xor_delegation(struct nfsd4_open *open)
  * nfsd4_process_open2 - finish open processing
  * @rqstp: the RPC transaction being executed
  * @current_fh: NFSv4 COMPOUND's current filehandle
+ * @parent_fh: filehandle of parent when CLAIM_NULL
  * @open: OPEN arguments
  *
  * If successful, (1) truncate the file if open->op_truncate was
@@ -6412,7 +6410,9 @@ static bool open_xor_delegation(struct nfsd4_open *open)
  * network byte order is returned.
  */
 __be32
-nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfsd4_open *open)
+nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh,
+		    struct svc_fh *parent_fh,
+		    struct nfsd4_open *open)
 {
 	struct nfsd4_compoundres *resp = rqstp->rq_resp;
 	struct nfs4_client *cl = open->op_openowner->oo_owner.so_client;
@@ -6509,8 +6509,7 @@ nfsd4_process_open2(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nf
 	* Attempt to hand out a delegation. No error return, because the
 	* OPEN succeeds even if we fail.
 	*/
-	nfs4_open_delegation(rqstp, open, stp,
-		&resp->cstate.current_fh, current_fh);
+	nfs4_open_delegation(rqstp, open, stp, parent_fh, current_fh);
 
 	/*
 	 * If there is an existing open stateid, it must be updated and
diff --git a/fs/nfsd/xdr4.h b/fs/nfsd/xdr4.h
index b5ec2cdd61a0..ea61e1a4c263 100644
--- a/fs/nfsd/xdr4.h
+++ b/fs/nfsd/xdr4.h
@@ -974,7 +974,9 @@ __be32 nfsd4_reclaim_complete(struct svc_rqst *, struct nfsd4_compound_state *,
 extern __be32 nfsd4_process_open1(struct nfsd4_compound_state *,
 		struct nfsd4_open *open, struct nfsd_net *nn);
 extern __be32 nfsd4_process_open2(struct svc_rqst *rqstp,
-		struct svc_fh *current_fh, struct nfsd4_open *open);
+				  struct svc_fh *current_fh,
+				  struct svc_fh *parent_fh,
+				  struct nfsd4_open *open);
 extern void nfsd4_cstate_clear_replay(struct nfsd4_compound_state *cstate);
 extern void nfsd4_cleanup_open_state(struct nfsd4_compound_state *cstate,
 		struct nfsd4_open *open);
-- 
2.50.0.107.gf914562f5916.dirty


  parent reply	other threads:[~2025-11-22  0:53 UTC|newest]

Thread overview: 20+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-11-22  0:46 [PATCH v7 00/14] nfsd: assorted cleanups involving v4 special stateids NeilBrown
2025-11-22  0:46 ` [PATCH v6 01/14] nfsd: rename ALLOWED_WITHOUT_FH to ALLOWED_WITHOUT_LOCAL_FH and revise use NeilBrown
2025-11-22 20:40   ` Chuck Lever
2025-11-22  0:47 ` [PATCH v6 02/14] nfsd: discard NFSD4_FH_FOREIGN NeilBrown
2025-11-22  0:47 ` [PATCH v6 03/14] nfsd: simplify foreign-filehandle handling to better match RFC-7862 NeilBrown
2025-11-22  0:47 ` [PATCH v6 04/14] nfsd: allow unrecognisable filehandle for foreign servers in COPY NeilBrown
2025-11-22 21:16   ` Chuck Lever
2025-11-23 16:43     ` Chuck Lever
2025-11-27  0:55       ` NeilBrown
2026-01-23 17:03         ` Chuck Lever
2025-11-22  0:47 ` [PATCH v6 05/14] nfsd: report correct error for attempt to use foreign filehandle NeilBrown
2025-11-22  0:47 ` [PATCH v6 06/14] nfsd: drop explicit tests for special stateids which would be invalid NeilBrown
2025-11-22  0:47 ` [PATCH v6 07/14] nfsd: revise names of special stateid, and predicate functions NeilBrown
2025-11-22  0:47 ` NeilBrown [this message]
2025-11-22  0:47 ` [PATCH v6 09/14] nfsd: revert nfsd4: delay setting current_fh in open NeilBrown
2025-11-22  0:47 ` [PATCH v6 10/14] nfsd: simplify clearing of current-state-id NeilBrown
2025-11-22  0:47 ` [PATCH v6 11/14] nfsd: simplify use of the current stateid NeilBrown
2025-11-22  0:47 ` [PATCH v6 12/14] nfsd: simplify saving " NeilBrown
2025-11-22  0:47 ` [PATCH v6 13/14] nfsd: discard current_stateid.h NeilBrown
2025-11-22  0:47 ` [PATCH v6 14/14] nfsd: conditionally clear seqid when current_stateid is used NeilBrown

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20251122005236.3440177-9-neilb@ownmail.net \
    --to=neilb@ownmail.net \
    --cc=Dai.Ngo@oracle.com \
    --cc=chuck.lever@oracle.com \
    --cc=jlayton@kernel.org \
    --cc=linux-nfs@vger.kernel.org \
    --cc=neil@brown.name \
    --cc=okorniev@redhat.com \
    --cc=tom@talpey.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox