mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Jonathan Flynn <jonathan.flynn@hammerspace.com>
To: NeilBrown <neil@brown.name>, Trond Myklebust <trondmy@kernel.org>,
	Anna Schumaker <anna@kernel.org>
Cc: Alexander Viro <viro@zeniv.linux.org.uk>,
	Christian Brauner <brauner@kernel.org>,
	Jeff Layton <jlayton@kernel.org>, Chuck Lever <cel@kernel.org>,
	Jan Kara <jack@suse.cz>,
	linux-nfs@vger.kernel.org, linux-fsdevel@vger.kernel.org,
	linux-kernel@vger.kernel.org
Subject: [PATCH 0/3] nfs: fix the silly-delete hand-off that 2/9 makes reachable
Date: Thu, 29 Oct 2026 12:09:47 -0600	[thread overview]
Message-ID: <20261029180950.387072-1-jonathan.flynn@hammerspace.com> (raw)
In-Reply-To: <20261028041023.3738553-3-neilb@ownmail.net>

Hi Neil,

Your "nfs: fix nfs_call_unlink()" computes the silly name's hash before
d_alloc_parallel(), so nfs_call_unlink() can now find another cached
entry for that name and hand it the pending silly-delete.  With it
applied, that happens: an entry made by a fresh lookup of the silly
name, after the original entry was invalidated, receives the delete
when the file is closed.  Three problems in the hand-off become
reachable with it, and these patches fix them:

  1/3  the hand-off can overwrite NFS_FSDATA_BLOCKED on an entry whose
       REMOVE or RENAME is in flight (Sashiko's review of 2/9 reports
       this too);
  2/3  the other order: nfs_rename() tests its target before it takes
       ->d_lock, so a hand-off landing in between is kfree()d by
       block_revalidate(), leaving DCACHE_NFSFS_RENAMED set with no
       data and a NULL dereference at the final dput(); a hand-off
       that the VFS's unlocked test missed also trips the WARN_ON()s
       in nfs_unlink() and nfs_rename().  nfs_rename() now tests under
       ->d_lock, and both return -EBUSY, as may_delete_dentry() does;
  3/3  nfs_call_unlink() holds rmdir_sem for read across its lookup and
       across the dput() of the alias, and either can kill a dentry
       carrying a silly-delete, which re-enters nfs_call_unlink() with
       rmdir_sem still held: that deadlocks against a waiting rmdir()
       (Sashiko's review of 2/9 reports the alias case).  It now takes
       rmdir_sem only for the REMOVE it sends, which also closes an
       older route to the same re-entry that does not need 2/9:
       NFSv4's delegation return in ->unlink_setup().

They have to go wherever 2/9 goes, and its Fixes: tag will take it to
stable.  Fold them into 2/9 if you prefer, as you did with the d_seq fix
in 1/9.

One window is not covered, and you may prefer to close it another way.
After nfs_unlink() or nfs_rename() clears the mark, and before the
VFS's d_delete() or nfs_rename()'s d_move(), a hand-off can still land
on the entry.  For an unlink, that costs only a second REMOVE, which
finds nothing.  For a rename onto the silly name, the target is left
owing a REMOVE of a name that now belongs to the renamed file.  That
REMOVE is normally dropped, because nfs_call_unlink() then finds the
renamed file's own entry and its file handle differs; but if that entry
has left the dcache by the time the target's last reference goes, the
REMOVE is sent and deletes the renamed file.  Closing the rename case
would take the hand-off refusing an alias that is no longer hashed, and
nfs_rename() dropping, under ->d_lock and after d_move(), a
silly-delete that landed after its mark cleared.  I have a draft of
that, and can test and send it if you want it.

Tested with your v4 and these patches on a 7.3-based kernel, over
NFSv4.2 to a pNFS metadata server that is not knfsd.  The hand-off
happens as described above.  With 3/3, the nested nfs_call_unlink()
that follows it starts with rmdir_sem not held, where without 3/3 it
ran with rmdir_sem held for read, and the REMOVE is sent once.  The
removal race tests of my RFC, posted in reply to your 0/9, passed on
this kernel, as did a PROVE_LOCKING and KASAN build running them,
though lockdep does not see rmdir_sem's read hold, which is taken with
down_read_non_owner().  No test here hits the races that 1/3 and 2/3
close, or the deadlock itself, so for those the fixes rest on the code.

The series applies to 83f32c773255 in Linus's tree with your v4, and
fs/ compiles without warnings at each patch.

Tools: these patches, their changelogs and this letter were written
with Claude Code, using Anthropic's Claude Opus 5 and Claude Opus 5.5
models, at my direction.  It found the problems fixed by 1/3 and 2/3,
and two of the three routes in 3/3, reading the code with and without
Sashiko's review prompts; Sashiko's own review of 2/9 reported the
problem in 1/3 as well, and the route through the alias in 3/3.

Thanks,
Jonathan

Jonathan Flynn (3):
  nfs: do not transfer a sillydelete onto a blocked dentry
  nfs: answer a handed-off silly-delete on a removal target with -EBUSY
  nfs: take rmdir_sem for a silly-delete only when its REMOVE is sent

 fs/nfs/dir.c    | 32 ++++++++++++++++++++++++++------
 fs/nfs/unlink.c | 39 ++++++++++++++++++++++++++++++++-------
 2 files changed, 58 insertions(+), 13 deletions(-)


base-commit: 83f32c773255720a661aa45d83e36278135f23f5
prerequisite-patch-id: 3405b4d6ab8b0bf24ba63a898083d617deec4f24
prerequisite-patch-id: 096657d6d80d7ca533ccb574d2af65611ede4af2
prerequisite-patch-id: 1a2319c14739918aef86116647fea28ae85ad4df
prerequisite-patch-id: 725cb18c3936d50141ef27dafc159bf50b64a5bd
prerequisite-patch-id: b39cdd352b97e2cd247311fd5db620dbff227bd7
prerequisite-patch-id: f9f3f0e945cadf96113d4ac9ab8f7b0c207af4e5
prerequisite-patch-id: 4c09a15390bb556d79bea1ee733f52a58bec80ef
prerequisite-patch-id: 7c026717a97b2c86a169539822f5d14650f68f8a
prerequisite-patch-id: a702d54495d0f3d7f88b82411d884dcf5aacf9a0
-- 
2.43.0


  reply	other threads:[~2026-10-29 18:09 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   ` Jonathan Flynn [this message]
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   ` [PATCH RFC 04/12] nfs: concurrent O_CREAT in one NFSv4 directory Jonathan Flynn
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=20261029180950.387072-1-jonathan.flynn@hammerspace.com \
    --to=jonathan.flynn@hammerspace.com \
    --cc=anna@kernel.org \
    --cc=brauner@kernel.org \
    --cc=cel@kernel.org \
    --cc=jack@suse.cz \
    --cc=jlayton@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®