From: Jonathan Flynn <jonathan.flynn@hammerspace.com>
To: NeilBrown <neil@brown.name>,
Alexander Viro <viro@zeniv.linux.org.uk>,
Christian Brauner <brauner@kernel.org>,
Trond Myklebust <trondmy@kernel.org>,
Anna Schumaker <anna@kernel.org>
Cc: Jeff Layton <jlayton@kernel.org>, Chuck Lever <cel@kernel.org>,
Jan Kara <jack@suse.cz>, Jonathan Corbet <corbet@lwn.net>,
linux-doc@vger.kernel.org, linux-nfs@vger.kernel.org,
linux-fsdevel@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH RFC 04/12] nfs: concurrent O_CREAT in one NFSv4 directory
Date: Thu, 29 Oct 2026 12:09:49 -0600 [thread overview]
Message-ID: <20261029180957.387138-5-jonathan.flynn@hammerspace.com> (raw)
In-Reply-To: <20261029180957.387138-1-jonathan.flynn@hammerspace.com>
Set IOPF_ATOMIC_OPEN_CREATE_SHARED in nfs4_dir_inode_operations, so
that the VFS takes the parent shared rather than exclusive for an
O_CREAT open in an NFSv4 directory. Creates of different names in one
directory then stop serializing on the parent inode, except on a server
that reports itself case-insensitive or not case-preserving, where
"nfs: tell the VFS when two names can be one entry on the server" has
set SB_I_NAMES_COLLIDE and creates keep the exclusive lock.
This is the only user of "vfs: allow the parent lock to be shared for
O_CREAT", and what it needs from it is the guarantee that the dentry
reaching the atomic-open method for a create is in-lookup. NFSv4 keeps
the dentry the VFS gives it when O_CREAT is set, and publishes the new
inode on that dentry; because it is in-lookup, the dentry is not in the
main hash, so dropping it is a no-op and publishing it is permitted.
The name enters the hash exactly once, and until it does, a concurrent
lookup or create of the same name finds the in-lookup dentry and waits.
NFS does not use the exclusive parent lock to serialize its own
per-directory state, which is what that patch asks an opting-in
filesystem to promise. Both pieces of state a create touches are
already under finer locks: the directory's change attribute and the
cache-validity bookkeeping that moves with it are updated under the
directory's own spinlock, and a dentry's directory verifier is stored
under that dentry's lock. Neither needs the parent lock held
exclusive, or held at all. The verifier is also ordered so that losing
a race can only cost work: a verifier offered against a directory state
it no longer reflects is declined rather than stored, so the failure
direction is an extra revalidation, never a dentry claiming stale
validity.
Lookup and readdir already run with the parent held shared, and
readdir already instantiates dentries there under that lock:
nfs_prime_dcache() takes an in-lookup dentry with d_alloc_trylock(),
skipping a name another thread holds in-lookup, and invalidates and
retries a hashed dentry that no longer matches the listing. A create
joins concurrency NFS already handles.
NeilBrown's "nfs: remove d_drop()/d_alloc_parallel() from
nfs_atomic_open()" states that the method has exclusive access to the
dentry in one of two ways: O_CREAT, where the parent is held exclusive,
or a dentry carrying DCACHE_PAR_LOOKUP. Setting the flag removes the
first of those for open(2), which reaches the method through
lookup_open(); nfsd reaches it through dentry_create(), which still
holds the parent exclusive. "vfs: allow the parent lock to be shared
for O_CREAT" supplies the second in its place: with the parent held
shared for a create, a hashed negative dentry is rejected and the
lookup retried, so an in-lookup dentry is what reaches the method.
NFS's invalidation of a cached negative for LOOKUP_OPEN and that
rejection do not overlap: nfs_neg_need_reval() returns 0 for
LOOKUP_CREATE before it can reach the LOOKUP_OPEN case that invalidates
a cached negative, so the invalidation that covers a plain open never
fires for a create, and the rejection in "vfs: allow the parent lock to
be shared for O_CREAT" never fires for anything else. The opener newly
in company with a shared create is one opening the same name without
O_CREAT, and that is the opener the invalidation covers.
The flag goes on the NFSv4 directory operations only. NFSv2 and NFSv3
reach a different atomic-open path, which has not been analysed or
exercised under a shared parent lock, so it does not get the flag;
adding it later is one line. Referral and automount directories are
unaffected, since they are given different operations vectors.
Every other directory-modifying operation still takes the parent
exclusive; for unlink that changes when "nfs: remove files with the
parent directory locked shared on NFSv4", later in this series, gives
NFSv4 ->unlink_shared().
The measured effect, from a 7.1.13-based kernel carrying an earlier
revision of both patches, is in "vfs: allow the parent lock to be
shared for O_CREAT".
Signed-off-by: Jonathan Flynn <jonathan.flynn@hammerspace.com>
---
fs/nfs/nfs4proc.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index fac8450b65..808bb8f1c1 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -10869,6 +10869,7 @@ static const struct inode_operations nfs4_dir_inode_operations = {
.setattr = nfs_setattr,
.listxattr = nfs4_listxattr,
.fileattr_get = nfs_fileattr_get,
+ .iop_flags = IOPF_ATOMIC_OPEN_CREATE_SHARED,
};
static const struct inode_operations nfs4_file_inode_operations = {
--
2.43.0
next prev parent reply other threads:[~2026-10-29 18:10 UTC|newest]
Thread overview: 31+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-28 4:06 [PATCH v4 0/9] nfs: prepare for locking changes NeilBrown
2026-10-28 4:06 ` [PATCH v4 1/9] nfs: fix open-blocking with d_fsdata NeilBrown
2026-10-28 4:06 ` [PATCH v4 2/9] nfs: fix nfs_call_unlink() NeilBrown
2026-10-29 18:09 ` [PATCH 0/3] nfs: fix the silly-delete hand-off that 2/9 makes reachable Jonathan Flynn
2026-10-29 18:09 ` [PATCH 1/3] nfs: do not transfer a sillydelete onto a blocked dentry Jonathan Flynn
2026-10-29 18:09 ` [PATCH 2/3] nfs: answer a handed-off silly-delete on a removal target with -EBUSY Jonathan Flynn
2026-10-29 18:09 ` [PATCH 3/3] nfs: take rmdir_sem for a silly-delete only when its REMOVE is sent Jonathan Flynn
2026-10-29 21:58 ` [PATCH 0/3] nfs: fix the silly-delete hand-off that 2/9 makes reachable NeilBrown
2026-10-28 4:06 ` [PATCH v4 3/9] nfs: remove d_drop()/d_alloc_parallel() from nfs_atomic_open() NeilBrown
2026-10-28 4:06 ` [PATCH v4 4/9] nfs: use d_splice_alias() in nfs_link() NeilBrown
2026-10-28 4:06 ` [PATCH v4 5/9] nfs: don't d_drop() before d_splice_alias() NeilBrown
2026-10-28 4:06 ` [PATCH v4 6/9] nfs: don't d_drop() before d_splice_alias() in atomic_create NeilBrown
2026-10-28 4:06 ` [PATCH v4 7/9] nfs: Use d_alloc_trylock() in nfs_prime_dcache() NeilBrown
2026-10-28 4:06 ` [PATCH v4 8/9] nfs: use d_alloc_trylock() in silly-rename NeilBrown
2026-10-28 4:06 ` [PATCH v4 9/9] nfs: use d_duplicate() NeilBrown
2026-10-28 17:21 ` [PATCH v4 0/9] nfs: prepare for locking changes Anna Schumaker
2026-10-29 18:09 ` [PATCH RFC 00/12] vfs, nfs: concurrent create and unlink in one directory Jonathan Flynn
2026-10-29 18:09 ` [PATCH RFC 01/12] nfs: update a server's capabilities in one step Jonathan Flynn
2026-10-29 18:09 ` [PATCH RFC 02/12] vfs: allow the parent lock to be shared for O_CREAT Jonathan Flynn
2026-10-29 18:09 ` [PATCH RFC 03/12] nfs: tell the VFS when two names can be one entry on the server Jonathan Flynn
2026-10-29 22:23 ` NeilBrown
2026-10-29 18:09 ` Jonathan Flynn [this message]
2026-10-29 18:09 ` [PATCH RFC 05/12] vfs: factor file removal into a helper, no functional change Jonathan Flynn
2026-10-29 18:09 ` [PATCH RFC 06/12] vfs: let a filesystem remove files with the parent directory locked shared Jonathan Flynn
2026-10-29 18:09 ` [PATCH RFC 07/12] nfs: add a second mark for a removal made with the parent " Jonathan Flynn
2026-10-29 18:09 ` [PATCH RFC 08/12] nfs: keep the dentry of a shared-parent removal hashed Jonathan Flynn
2026-10-29 18:09 ` [PATCH RFC 09/12] nfs: do not cache a name from a listing that a removal overlapped Jonathan Flynn
2026-10-29 18:09 ` [PATCH RFC 10/12] nfs: add the removal method for a parent directory locked shared Jonathan Flynn
2026-10-29 18:09 ` [PATCH RFC 11/12] nfs: look a name up again once its removal has unhashed it Jonathan Flynn
2026-10-29 18:09 ` [PATCH RFC 12/12] nfs: remove files with the parent directory locked shared on NFSv4 Jonathan Flynn
2026-10-29 22:18 ` [PATCH RFC 00/12] vfs, nfs: concurrent create and unlink in one directory 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=20261029180957.387138-5-jonathan.flynn@hammerspace.com \
--to=jonathan.flynn@hammerspace.com \
--cc=anna@kernel.org \
--cc=brauner@kernel.org \
--cc=cel@kernel.org \
--cc=corbet@lwn.net \
--cc=jack@suse.cz \
--cc=jlayton@kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-nfs@vger.kernel.org \
--cc=neil@brown.name \
--cc=trondmy@kernel.org \
--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
all inboxes | Powered by JetHome®