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
next prev parent 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