Linux NFS development
 help / color / mirror / Atom feed
From: "Chuck Lever" <cel@kernel.org>
To: NeilBrown <neil@brown.name>
Cc: "Olga Kornievskaia" <okorniev@redhat.com>,
	"Dai Ngo" <Dai.Ngo@oracle.com>, "Tom Talpey" <tom@talpey.com>,
	linux-nfs@vger.kernel.org, "Jeff Layton" <jlayton@kernel.org>
Subject: Re: [PATCH v5 18/18] nfsd: use do_lookup_open() for non-creating open requests too.
Date: Mon, 24 Aug 2026 18:48:19 -0400	[thread overview]
Message-ID: <91af721c-a6a9-4f34-adb0-8d5982a87efa@app.fastmail.com> (raw)
In-Reply-To: <178760852225.3510150.8856836572675365165@noble.neil.brown.name>



On Mon, Aug 24, 2026, at 5:55 PM, NeilBrown wrote:
> On Tue, 18 Aug 2026, NeilBrown wrote:
>> On Tue, 18 Aug 2026, Chuck Lever wrote:
>> > 
>> > On Wed, Aug 12, 2026, at 1:12 PM, Jeff Layton wrote:
>> > > On Fri, 2026-07-17 at 19:28 +1000, NeilBrown wrote:
>> > >> From: NeilBrown <neil@brown.name>
>> > >> 
>> > >> Now that we have do_lookup_open() for creating open requests, we can use
>> > >> it for non-creating too as do_lookup_open() is already able to do that.
>> > >> 
>> > >> This prepares for switching to vfs_lookup_open() once the VFS provides
>> > >> that.  This will ensure consistent code and fs-interaction with VFS open().
>> > >> 
>> > >> The resulting simplification allows fh_fill_pre_attrs_unlocked() to be
>> > >> moved into nfsd4_open_file() (renamed from nfsd4_create_file()) so it is
>> > >> closer to fh_full_post_attrs and fh_fill_post_noop calls.
>> > >> 
>> > >> As ->op_create_mode isn't defined when op_create is zero, we need a
>> > >> local create_mode which is -1 (illegal value) when op_create is zero.
>> > >> 
>> > >> The non-create path now doesn't use nfsd_lookup().  As mount-point
>> > >> crossing including nfsd_check_access() is already included for existing
>> > >> names, this does not lose us anything.
>> > >> 
>> > >> We now only call mnt_want_write() is there is a flag which indicates we
>> > >> might want write access - previously O_CREAT was always set.
>> > >> 
>> > >> Signed-off-by: NeilBrown <neil@brown.name>
>> > >> ---
>> > >>  fs/nfsd/nfs4proc.c | 113 ++++++++++++++++++++++-----------------------
>> > >>  1 file changed, 56 insertions(+), 57 deletions(-)
>> > >> 
>> > >> diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
>> > >> index b7fdc75c4b81..11d0411dec08 100644
>> > >> --- a/fs/nfsd/nfs4proc.c
>> > >> +++ b/fs/nfsd/nfs4proc.c
>> > >> @@ -204,9 +204,10 @@ static struct file *do_lookup_open(struct path *parent,
>> > >>  	struct file *filp = NULL;
>> > >>  	struct path path;
>> > >>  	struct dentry *child;
>> > >> -	int want_write_err = 0;
>> > >> +	int want_write_err = -ENOENT;
>> > >>  
>> > >> -	want_write_err = mnt_want_write(parent->mnt);
>> > >> +	if (oflags & (O_CREAT|O_RDONLY|O_RDWR|O_TRUNC))
>> > >> +		want_write_err = mnt_want_write(parent->mnt);
>> > >>  
>> > >>  	child = start_creating(&nop_mnt_idmap, parent->dentry, name);
>> > >>  	if (IS_ERR(child)) {
>> > >> @@ -242,29 +243,30 @@ static struct file *do_lookup_open(struct path *parent,
>> > >>  }
>> > >>  
>> > >>  /*
>> > >> - * Implement NFSv4's unchecked, guarded, and exclusive create
>> > >> - * semantics for regular files. Open state for this new file is
>> > >> - * subsequently fabricated in nfsd4_process_open2().
>> > >> - *
>> > >> + * Implement NFSv4's open semantics for regular files.
>> > >> + * Both create (unchecked, guarded, and exclusive) and non-create.
>> > >> + * Open state for this new file is subsequently fabricated in
>> > >> + * nfsd4_process_open2().
>> > >>   * Upon return, caller must release @fhp and @resfhp.
>> > >>   */
>> > >>  static __be32
>> > >> -nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
>> > >> -		  struct svc_fh *resfhp, struct nfsd4_open *open)
>> > >> +nfsd4_open_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
>> > >> +		struct svc_fh *resfhp, struct nfsd4_open *open)
>> > >>  {
>> > >>  	struct iattr *iap = &open->op_iattr;
>> > >>  	struct nfsd_attrs attrs = {
>> > >>  		.na_iattr	= iap,
>> > >>  		.na_seclabel	= &open->op_label,
>> > >>  	};
>> > >> -	int oflags = O_CREAT | O_LARGEFILE;
>> > >> +	int oflags = O_LARGEFILE;
>> > >>  	struct dentry *child = ERR_PTR(-EINVAL);
>> > >>  	struct path parent = {
>> > >>  		.mnt = fhp->fh_export->ex_path.mnt,
>> > >>  		.dentry = fhp->fh_dentry,
>> > >>  	};
>> > >>  	__u32 v_mtime, v_atime;
>> > >> -	__be32 status, create_status;
>> > >> +	int createmode = -1;
>> > >> +	__be32 status, create_status = 0;
>> > >>  	int want_write_err;
>> > >>  
>> > >>  	if (name_is_dot_dotdot(open->op_fname, open->op_fnamelen))
>> > >> @@ -276,6 +278,10 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
>> > >>  	if (status != nfs_ok)
>> > >>  		return status;
>> > >>  
>> > >> +	status = fh_fill_pre_attrs_unlocked(fhp);
>> > >> +	if (status)
>> > >> +		return status;
>> > >> +
>> > >>  	if (open->op_createmode == NFS4_CREATE_UNCHECKED) {
>> > >>  		/*
>> > >>  		 * If name is already in dcache we need to check for mountpoints
>> > >> @@ -305,11 +311,15 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
>> > >>  	if (!IS_POSIXACL(d_inode(parent.dentry)))
>> > >>  		iap->ia_mode &= ~current_umask();
>> > >>  
>> > >> +	if (open->op_create) {
>> > >> +		createmode = open->op_createmode;
>> > >> +		oflags |= O_CREAT;
>> > >> +	}
>> > >>  	/*
>> > >>  	 * For the EXCLUSIVE modes we do our own uniqueness tests
>> > >>  	 * so don't want O_EXCL.
>> > >>  	 */
>> > >> -	if (open->op_createmode == NFS4_CREATE_GUARDED)
>> > >> +	if (createmode == NFS4_CREATE_GUARDED)
>> > >>  		oflags |= O_EXCL;
>> > >>  
>> > >>  	switch (open->op_share_access & NFS4_SHARE_ACCESS_BOTH) {
>> > >> @@ -344,7 +354,7 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
>> > >>  
>> > >>  	v_mtime = 0;
>> > >>  	v_atime = 0;
>> > >> -	if (nfsd4_create_is_exclusive(open->op_createmode)) {
>> > >> +	if (nfsd4_create_is_exclusive(createmode)) {
>> > >>  		u32 *verifier = (u32 *)open->op_verf.data;
>> > >>  
>> > >>  		/*
>> > >> @@ -366,11 +376,11 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
>> > >>  		iap->ia_atime.tv_nsec = 0;
>> > >>  	}
>> > >>  
>> > >> -	create_status = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE);
>> > >> -	if (create_status)
>> > >> -		/* Might still succeed if no create is needed */
>> > >> -		oflags &= ~O_CREAT;
>> > >> -
>> > >> +	if (oflags & O_CREAT) {
>> > >> +		create_status = fh_verify(rqstp, fhp, S_IFDIR, NFSD_MAY_CREATE);
>> > >> +		if (create_status)
>> > >> +			oflags &= ~O_CREAT;
>> > >> +	}
>> > >>  	open->op_filp = do_lookup_open(&parent,
>> > >>  				       &QSTR_LEN(open->op_fname,
>> > >>  						 open->op_fnamelen),
>> > >> @@ -392,14 +402,15 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
>> > >>  		goto out;
>> > >>  
>> > >>  	if (!open->op_created &&
>> > >> -	    nfsd4_create_is_exclusive(open->op_createmode) &&
>> > >> +	    nfsd4_create_is_exclusive(createmode) &&
>> > >>  	    inode_get_mtime_sec(d_inode(child)) == v_mtime &&
>> > >>  	    inode_get_atime_sec(d_inode(child)) == v_atime &&
>> > >>  	    d_inode(child)->i_size == 0)
>> > >>  		open->op_created = true;
>> > >>  
>> > >>  	if (!open->op_created) {
>> > >> -		if (open->op_createmode == NFS4_CREATE_UNCHECKED) {
>> > >> +		if (open->op_create == NFS4_OPEN_NOCREATE ||
>> > >> +		    createmode == NFS4_CREATE_UNCHECKED) {
>> > >>  			/* NFSv4 protocol requires change attributes
>> > >>  			 * even though no change happened.
>> > >>  			 */
>> > >> @@ -494,46 +505,34 @@ do_open_lookup(struct svc_rqst *rqstp, struct nfsd4_compound_state *cstate, stru
>> > >>  	fh_init(*resfh, NFS4_FHSIZE);
>> > >>  	open->op_truncate = false;
>> > >>  
>> > >> -	status = fh_fill_pre_attrs_unlocked(current_fh);
>> > >> -	if (status)
>> > >> -		goto out;
>> > >> -	if (open->op_create) {
>> > >> -		/* FIXME: check session persistence and pnfs flags.
>> > >> -		 * The nfsv4.1 spec requires the following semantics:
>> > >> -		 *
>> > >> -		 * Persistent   | pNFS   | Server REQUIRED | Client Allowed
>> > >> -		 * Reply Cache  | server |                 |
>> > >> -		 * -------------+--------+-----------------+--------------------
>> > >> -		 * no           | no     | EXCLUSIVE4_1    | EXCLUSIVE4_1
>> > >> -		 *              |        |                 | (SHOULD)
>> > >> -		 *              |        | and EXCLUSIVE4  | or EXCLUSIVE4
>> > >> -		 *              |        |                 | (SHOULD NOT)
>> > >> -		 * no           | yes    | EXCLUSIVE4_1    | EXCLUSIVE4_1
>> > >> -		 * yes          | no     | GUARDED4        | GUARDED4
>> > >> -		 * yes          | yes    | GUARDED4        | GUARDED4
>> > >> -		 */
>> > >> +	/* FIXME: check session persistence and pnfs flags.
>> > >> +	 * The nfsv4.1 spec requires the following semantics:
>> > >> +	 *
>> > >> +	 * Persistent   | pNFS   | Server REQUIRED | Client Allowed
>> > >> +	 * Reply Cache  | server |                 |
>> > >> +	 * -------------+--------+-----------------+--------------------
>> > >> +	 * no           | no     | EXCLUSIVE4_1    | EXCLUSIVE4_1
>> > >> +	 *              |        |                 | (SHOULD)
>> > >> +	 *              |        | and EXCLUSIVE4  | or EXCLUSIVE4
>> > >> +	 *              |        |                 | (SHOULD NOT)
>> > >> +	 * no           | yes    | EXCLUSIVE4_1    | EXCLUSIVE4_1
>> > >> +	 * yes          | no     | GUARDED4        | GUARDED4
>> > >> +	 * yes          | yes    | GUARDED4        | GUARDED4
>> > >> +	 */
>> > >>  
>> > >> -		current->fs->umask = open->op_umask;
>> > >> -		status = nfsd4_create_file(rqstp, current_fh, *resfh, open);
>> > >> -		current->fs->umask = 0;
>> > >> +	current->fs->umask = open->op_umask;
>> > >> +	status = nfsd4_open_file(rqstp, current_fh, *resfh, open);
>> > >> +	current->fs->umask = 0;
>> > >>  
>> > >> -		/*
>> > >> -		 * Following rfc 3530 14.2.16, and rfc 5661 18.16.4
>> > >> -		 * use the returned bitmask to indicate which attributes
>> > >> -		 * we used to store the verifier:
>> > >> -		 */
>> > >> -		if (nfsd4_create_is_exclusive(open->op_createmode) && status == 0)
>> > >> -			open->op_bmval[1] |= (FATTR4_WORD1_TIME_ACCESS |
>> > >> -						FATTR4_WORD1_TIME_MODIFY);
>> > >> -	} else {
>> > >> -		status = nfsd_lookup(rqstp, current_fh,
>> > >> -				     open->op_fname, open->op_fnamelen, *resfh);
>> > >> -		/*
>> > >> -		 * NFSv4 protocol requires change attributes even though
>> > >> -		 * no change happened.
>> > >> -		 */
>> > >> -		fh_fill_post_noop(current_fh);
>> > >> -	}
>> > >> +	/*
>> > >> +	 * Following rfc 3530 14.2.16, and rfc 5661 18.16.4
>> > >> +	 * use the returned bitmask to indicate which attributes
>> > >> +	 * we used to store the verifier:
>> > >> +	 */
>> > >> +	if (open->op_create &&
>> > >> +	    nfsd4_create_is_exclusive(open->op_createmode) && status == 0)
>> > >> +		open->op_bmval[1] |= (FATTR4_WORD1_TIME_ACCESS |
>> > >> +				      FATTR4_WORD1_TIME_MODIFY);
>> > >>  	if (status)
>> > >>  		goto out;
>> > >>  	status = nfserrno(nfsd_check_obj_isreg((*resfh)->fh_dentry));
>> > >
>> > > This patch is making the pynfs DELEG8 test fail. It seems like this
>> > > patch breaks the behavior where the server sends back NFS4ERR_DELAY on
>> > > an OPEN while waiting for a DELEGRETURN. The server just doesn't send a
>> > > reply until the delegation times out with it.
>> > 
>> > Neil, I need a response from you. How soon do you intend to address this
>> > issue? Can this patch be dropped safely from the series, or do I need to
>> > drop the whole series?
>> > 
>> 
>> Hi,
>>  sorry for not getting to this sooner.
>>  I can see the problem.  To fix it we need to somehow get logic similar
>>  to nfsd_open_break_lease() into the vfs_lookup_open() path.  I think
>>  that'll be possible though not trivial.
>> 
>>  It is safe to drop just that patch for now.  I don't need it for the
>>  locking work that I am doing.  I think it is still good to have and I
>>  will try to rehabilitate it, but not in a hurry.
>> 
>>  I'm confident the rest of the series is not implicated in this problem
>>  so there is no need to drop the whole series.
>
> Hi Chuck,
>  I notice this series wasn't in your recent pull request and they seem
>  to have disappeared from your tree.

I see them in nfsd-testing, where they’ve been since August 10.


>  What do you understand the status of these patches to be?
>  I was hoping they would land this merge window.

Jeff and I discussed this, and we’d like these to get another month
or two in linux-next because they modify common paths. When v7.3-rc1
opens, they will be at the first patches in nfsd-next for v7.4.


-- 
Chuck Lever

  reply	other threads:[~2026-08-24 22:48 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-17  9:27 [PATCH v5 00/18] nfsd: refactor nfs4_create_file() NeilBrown
2026-07-17  9:27 ` [PATCH v5 01/18] nfsd: honour client-provided attributes for NFS4_CREATE_EXCLUSIVE4_1 NeilBrown
2026-07-17  9:27 ` [PATCH v5 02/18] nfsd: move check_nfsd_access() call into nfsd_cross_mnt() NeilBrown
2026-07-17  9:27 ` [PATCH v5 03/18] nfsd: correctly handle CREATE of mounted-on files NeilBrown
2026-07-17  9:27 ` [PATCH v5 04/18] nfsd: replace fh_fill_both_attrs() with fh_fill_post_noop() NeilBrown
2026-07-17  9:27 ` [PATCH v5 05/18] nfsd: move fh_want_write() after preamble in nfsd4_create_file() NeilBrown
2026-07-17  9:27 ` [PATCH v5 06/18] nfsd: move more nfs-specific code into preamble of nfsd4_create_file() NeilBrown
2026-07-17  9:27 ` [PATCH v5 07/18] nfsd: remove subtlety from nfsd4_create_file() NeilBrown
2026-07-17  9:27 ` [PATCH v5 08/18] nfsd: in nfsd4_create_file() let VFS report if file was created NeilBrown
2026-07-17  9:27 ` [PATCH v5 09/18] nfsd: nfsd4_create_file(): Move NFSD_MAY_CREATE check earlier NeilBrown
2026-07-17  9:27 ` [PATCH v5 10/18] nfsd: fh_want_write) failure need not be immediately fatal for nfsd4_create_file() NeilBrown
2026-07-17  9:27 ` [PATCH v5 11/18] nfsd: (almost) always open file in nfsd4_create_file() NeilBrown
2026-07-17  9:28 ` [PATCH v5 12/18] nfsd: reduce range of directory lock " NeilBrown
2026-07-17  9:28 ` [PATCH v5 13/18] nfsd: open-code nfsd4_vfs_create() into nfsd4_create_file() NeilBrown
2026-07-17  9:28 ` [PATCH v5 14/18] nfsd: move some code out of the d_really_is_negative() branch in nfsd4_create_file() NeilBrown
2026-07-17  9:28 ` [PATCH v5 15/18] nfsd: reduce want-write range " NeilBrown
2026-07-17  9:28 ` [PATCH v5 16/18] nfsd: move v0 checking out of nfsd_check_obj_isreg() NeilBrown
2026-07-17  9:28 ` [PATCH v5 17/18] nfsd: separate out VFS-specific code from nfsd4_create_file() NeilBrown
2026-07-17  9:28 ` [PATCH v5 18/18] nfsd: use do_lookup_open() for non-creating open requests too NeilBrown
2026-08-12 17:12   ` Jeff Layton
2026-08-17 17:02     ` Chuck Lever
2026-08-17 21:53       ` NeilBrown
2026-08-24 21:55         ` NeilBrown
2026-08-24 22:48           ` Chuck Lever [this message]
2026-08-24 23:02             ` NeilBrown
2026-07-17 11:29 ` [PATCH v5 00/18] nfsd: refactor nfs4_create_file() Jeff Layton
2026-07-17 13:30 ` Chuck Lever

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=91af721c-a6a9-4f34-adb0-8d5982a87efa@app.fastmail.com \
    --to=cel@kernel.org \
    --cc=Dai.Ngo@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