Linux filesystem development
 help / color / mirror / Atom feed
From: NeilBrown <neilb@ownmail.net>
To: Alexander Viro <viro@zeniv.linux.org.uk>,
	Christian Brauner <brauner@kernel.org>,
	Chuck Lever <cel@kernel.org>, Jeff Layton <jlayton@kernel.org>
Cc: linux-fsdevel@vger.kernel.org, linux-nfs@vger.kernel.org
Subject: [PATCH 5/7] nfsd: switch NFS4 OPEN to use vfs_lookup_open()
Date: Thu, 10 Sep 2026 10:20:51 +1000	[thread overview]
Message-ID: <20260910002934.192979-6-neilb@ownmail.net> (raw)
In-Reply-To: <20260910002934.192979-1-neilb@ownmail.net>

From: NeilBrown <neil@brown.name>

The functionality that was recently gathered into do_lookup_open() is
now available from the vfs as vfs_lookup_open().  So nfsd4_create_file()
can call that, with a few adjustments.

This implementation shares more code with syscall open paths and so uses
some filesystem interfaces slightly more correctly.  It also takes the
responsibility for locking out of nfsd so that planned changes can
happen entirely in VFS code.

We need to pass O_NONBLOCK so that that EWOULDBLOCK errors from
break_lease of try_break_deleg() get passed back.

We need to mask any type out of "mode" else vfs_lookup_open() will warn.

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.

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().
Make both these tests (for non-regular and for regular) the same.

Signed-off-by: NeilBrown <neil@brown.name>
---
 fs/nfsd/nfs4proc.c | 83 ++++++++++++----------------------------------
 1 file changed, 21 insertions(+), 62 deletions(-)

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
@@ -225,8 +225,11 @@ do_open_permission(struct svc_rqst *rqstp, struct svc_fh *current_fh, struct nfs
 
 static int nfsd_check_obj_isreg(struct dentry *child)
 {
-	umode_t mode = d_inode(child)->i_mode;
+	umode_t mode;
 
+	if (!child || !d_inode(child))
+		return -EFTYPE;
+	mode = d_inode(child)->i_mode;
 	if (S_ISREG(mode))
 		return 0;
 	if (S_ISDIR(mode))
@@ -250,52 +253,6 @@ static inline bool nfsd4_create_is_exclusive(int createmode)
 		createmode == NFS4_CREATE_EXCLUSIVE4_1;
 }
 
-static struct file *do_lookup_open(struct path *parent,
-				   struct qstr *name,
-				   unsigned int oflags,
-				   umode_t mode)
-{
-	struct file *filp = NULL;
-	struct path path;
-	struct dentry *child;
-	int want_write_err = 0;
-
-	want_write_err = mnt_want_write(parent->mnt);
-
-	child = start_creating(&nop_mnt_idmap, parent->dentry, name);
-	if (IS_ERR(child)) {
-		filp = ERR_CAST(child);
-		goto out;
-	}
-	path.mnt = parent->mnt;
-	path.dentry = child;
-
-	if (d_really_is_positive(child)) {
-		/*
-		 * open the file so that we consistently have a valid
-		 * op_filp and consequently a valid ->f_path.dentry.
-		 */
-		int err = nfsd_check_obj_isreg(child);
-
-		if (err)
-			filp = ERR_PTR(err);
-		else
-			filp = dentry_open(&path, oflags, current_cred());
-	} else if (!(oflags & O_CREAT)) {
-		filp = ERR_PTR(-ENOENT);
-	} else if (want_write_err) {
-		filp = ERR_PTR(want_write_err);
-	} else {
-		filp = dentry_create(&path, oflags, mode, current_cred());
-		child = path.dentry;
-	}
-	end_creating(child);
-out:
-	if (!want_write_err)
-		mnt_drop_write(parent->mnt);
-	return filp;
-}
-
 /*
  * Implement NFSv4's unchecked, guarded, and exclusive create
  * semantics for regular files. Open state for this new file is
@@ -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;
 	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);
 	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);
 		}
 		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 {
 			/* NFSv4 protocol requires change attributes
 			 * even though no change happened.
 			 */
@@ -477,8 +437,7 @@ nfsd4_create_file(struct svc_rqst *rqstp, struct svc_fh *fhp,
 			open->op_truncate = (d_is_reg(child) &&
 					     (iap->ia_valid & ATTR_SIZE) &&
 					     !iap->ia_size);
-		} else
-			status = nfserr_exist;
+		}
 		goto out;
 	}
 	/* file was created */
-- 
2.50.0.107.gf914562f5916.dirty


  parent reply	other threads:[~2026-09-10  0:30 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 ` NeilBrown [this message]
2026-09-10 15:41   ` [PATCH 5/7] nfsd: switch NFS4 OPEN to use vfs_lookup_open() Chuck Lever
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=20260910002934.192979-6-neilb@ownmail.net \
    --to=neilb@ownmail.net \
    --cc=brauner@kernel.org \
    --cc=cel@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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox