From: "Chuck Lever" <cel@kernel.org>
To: NeilBrown <neil@brown.name>
Cc: "Alexander Viro" <viro@zeniv.linux.org.uk>,
"Christian Brauner" <brauner@kernel.org>,
"Jeff Layton" <jlayton@kernel.org>,
linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org
Subject: Re: [PATCH 5/7] nfsd: switch NFS4 OPEN to use vfs_lookup_open()
Date: Thu, 10 Sep 2026 11:41:31 -0400 [thread overview]
Message-ID: <e36532d5-e37f-4d71-b83a-c8d19d87811f@slotpi15m67> (raw)
In-Reply-To: <20260910002934.192979-6-neilb@ownmail.net>
> This implementation shares more code with syscall open paths and so uses
> some filesystem interfaces slightly more correctly. It also takes the
Which interfaces? The concrete difference I can see is that lookup_open()
honors ->atomic_open, which do_lookup_open() never called. Naming that
would be clearer than "slightly more correctly".
> We need to pass O_NONBLOCK so that that EWOULDBLOCK errors from
Repeated word: "that that".
> vfs_lookup_open() always returns -EFTYPE if a non-regular-file was
> found, and provides the dentry in parent.dentry. We can use
> nfsd_check_obj_is_reg() to turn this into an error.
>
> As parent.dentry could be NULL, we enhance nfsd_check_obj_is_reg() to
> cope with that.
The function is nfsd_check_obj_isreg(), in both places.
> vfs_lookup_open() will return -EEXIST if required for
> NFS_CREATE_GUARDED4 as O_EXCL is passed in. Other checks for
> and existing object need only test for nfsd4_create_is_exclusive().
s/and existing/an existing/, and the identifier is NFS4_CREATE_GUARDED.
The -EEXIST claim holds only on the path through the tail of
vfs_lookup_open(), where the O_EXCL test runs before the d_is_reg()
test. When lookup_open() itself returns -EFTYPE, vfs_lookup_open()
returns before either test. See below.
> diff --git a/fs/nfsd/nfs4proc.c b/fs/nfsd/nfs4proc.c
> index 3a82af381a8d..0fd5a6411ed3 100644
> --- a/fs/nfsd/nfs4proc.c
> +++ b/fs/nfsd/nfs4proc.c
[ ... ]
> @@ -312,7 +269,7 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
> .na_iattr = iap,
> .na_seclabel = &open->op_label,
> };
> - int oflags = O_CREAT | O_LARGEFILE;
> + int oflags = O_CREAT | O_LARGEFILE | O_NONBLOCK;
Nit: do_dentry_open() strips O_CREAT, O_EXCL and O_TRUNC from f_flags
and leaves O_NONBLOCK in place, so op_filp now carries O_NONBLOCK into
the filecache entry that nfsd_file_acquire_opened() builds from it.
Files opened through __nfsd_open() do not. Is that divergence
intended?
> struct dentry *child = ERR_PTR(-EINVAL);
> struct path parent = {
> .mnt = fhp->fh_export->ex_path.mnt,
> @@ -424,28 +381,29 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
> /* Might still succeed if no create is needed */
> oflags &= ~O_CREAT;
>
> - open->op_filp = do_lookup_open(&parent,
> - &QSTR_LEN(open->op_fname,
> - open->op_fnamelen),
> - oflags,
> - open->op_iattr.ia_mode);
> + dget(parent.dentry);
> + open->op_filp = vfs_lookup_open(&parent,
> + &QSTR_LEN(open->op_fname,
> + open->op_fnamelen),
> + oflags,
> + open->op_iattr.ia_mode & S_IALLUGO);
Nit: after this call "parent.dentry" is the child (or NULL), while a
few lines up IS_POSIXACL(d_inode(parent.dentry)) reads the same
expression as the parent directory. The VFS patch renamed its parameter
to @path for this reason. Would renaming the local here avoid the same
trap?
> if (IS_ERR(open->op_filp)) {
> int hosterr = PTR_ERR(open->op_filp);
>
> - if (open->op_createmode != NFS4_CREATE_UNCHECKED) {
> - switch (hosterr) {
> - case -EISDIR:
> - case -ELOOP:
> - case -EFTYPE:
> + if (hosterr == -EFTYPE) {
> + if (nfsd4_create_is_exclusive(open->op_createmode))
> hosterr = -EEXIST;
> - }
> + else
> + hosterr = nfsd_check_obj_isreg(parent.dentry);
> }
Does this drop the NFS4ERR_EXIST mapping for GUARDED4?
The old test covered GUARDED as well as the two EXCLUSIVE modes.
nfsd4_create_is_exclusive() covers only EXCLUSIVE4 and EXCLUSIVE4_1, so
a GUARDED open that finds a non-regular object now takes the else arm
and returns NFS4ERR_ISDIR, NFS4ERR_WRONG_TYPE, and so on. RFC 8881
section 18.16.3 says a GUARDED4 duplicate is NFS4ERR_EXIST.
Keeping "open->op_createmode != NFS4_CREATE_UNCHECKED" here would
restore the old mapping without depending on the ordering of checks
inside each filesystem's ->atomic_open.
Separately, can this arm return nfs_ok? nfsd_check_obj_isreg() returns
0 for a regular file, and vfs_lookup_open() can leave a regular file in
parent.dentry when the d_lookup() it does after an -EFTYPE races with a
rename (the VFS marks that case with a WARN_ON_ONCE rather than
excluding it). nfserrno(0) is nfs_ok, op_filp is then set to NULL, and
nfsd4_create_file() returns success with resfhp never composed. It only
fails safely today because do_open_lookup() then calls
nfsd_check_obj_isreg() on the NULL fh_dentry. Something like
if (!hosterr)
hosterr = -EFTYPE;
would address that.
> status = nfserrno(hosterr);
> open->op_filp = NULL;
> if (status == nfserr_noent && create_status)
> status = create_status;
> + dput(parent.dentry);
> goto out;
> }
> + dput(parent.dentry);
>
> child = open->op_filp->f_path.dentry;
> open->op_created = open->op_filp->f_mode & FMODE_CREATED;
> @@ -462,7 +420,9 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
> open->op_created = true;
>
> if (!open->op_created) {
> - if (open->op_createmode == NFS4_CREATE_UNCHECKED) {
> + if (nfsd4_create_is_exclusive(open->op_createmode)) {
> + status = nfserr_exist;
> + } else {
Same question here. GUARDED used to get nfserr_exist from this branch
and now gets the "no change happened" arm. It is unreachable for GUARDED
today only because vfs_lookup_open() returns -EEXIST whenever O_EXCL is
set and nothing was created. Should this also stay as
"!= NFS4_CREATE_UNCHECKED" so the protocol rule is enforced here rather
than relying on that ordering?
--
Chuck Lever (Come to NFS bake-a-thon! https://nfsv4bat.org)
next prev parent reply other threads:[~2026-09-10 15:41 UTC|newest]
Thread overview: 12+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-10 0:20 [PATCH 0/7 RFC] fixes for vfs_lookup_open, and integration with nfsd NeilBrown
2026-09-10 0:20 ` [PATCH 1/7] vfs: add some allowed open flags to vfs_lookup_open() NeilBrown
2026-09-10 0:20 ` [PATCH 2/7] vfs: O_NONBLOCK|O_CREAT open shouldn't wait for directory delegation NeilBrown
2026-09-10 0:20 ` [PATCH 3/7] vfs: vfs_lookup_open() should only return -EFTYPE for non-regular files NeilBrown
2026-09-10 0:20 ` [PATCH 4/7] vfs: change vfs_lookup_open() to return found dentry in path.dentry NeilBrown
2026-09-10 0:39 ` NeilBrown
2026-09-10 15:13 ` Chuck Lever
2026-09-10 0:20 ` [PATCH 5/7] nfsd: switch NFS4 OPEN to use vfs_lookup_open() NeilBrown
2026-09-10 15:41 ` Chuck Lever [this message]
2026-09-10 0:20 ` [PATCH 6/7] nfsd: nfsd_check_obj_isreg() to use nfs error codes NeilBrown
2026-09-10 0:20 ` [PATCH 7/7] nfsd: use vfs_lookup_open() for non-creating open requests too NeilBrown
2026-09-10 15:47 ` 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=e36532d5-e37f-4d71-b83a-c8d19d87811f@slotpi15m67 \
--to=cel@kernel.org \
--cc=brauner@kernel.org \
--cc=jlayton@kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=neil@brown.name \
--cc=viro@zeniv.linux.org.uk \
/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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.