From: Mateusz Guzik <mjguzik@gmail.com>
To: brauner@kernel.org
Cc: viro@zeniv.linux.org.uk, jack@suse.cz,
linux-kernel@vger.kernel.org, linux-fsdevel@vger.kernel.org,
Mateusz Guzik <mjguzik@gmail.com>
Subject: [PATCH v5 3/4] fs: handle potential filesystems which use I_DONTCACHE and drop the lock in ->drop_inode
Date: Tue, 31 Mar 2026 18:08:50 +0200 [thread overview]
Message-ID: <20260331160851.3854954-4-mjguzik@gmail.com> (raw)
In-Reply-To: <20260331160851.3854954-1-mjguzik@gmail.com>
f2fs and ntfs play games where they transitioning the refcount 0->1 and release
the inode spinlock, allowing other threads to grab a ref of their own.
They also return 0 in that case, making this problem harmless.
However, should they start using the I_DONTCACHE machinery down the road
while retaining the above, iput_final() will get a race where it can
proceed to teardown an inode with references.
The easiest way out for the time being is to future-proof it by
predicating caching on the count.
Developing better ->drop_inode semantics and sanitizing all users is
left as en exercise for the reader.
Signed-off-by: Mateusz Guzik <mjguzik@gmail.com>
---
fs/inode.c | 27 ++++++++++++++++++---------
1 file changed, 18 insertions(+), 9 deletions(-)
diff --git a/fs/inode.c b/fs/inode.c
index e397a4b56671..013470e6d144 100644
--- a/fs/inode.c
+++ b/fs/inode.c
@@ -1935,20 +1935,29 @@ static void iput_final(struct inode *inode)
else
drop = inode_generic_drop(inode);
- if (!drop &&
- !(inode_state_read(inode) & I_DONTCACHE) &&
- (sb->s_flags & SB_ACTIVE)) {
+ /*
+ * FIXME: there are ->drop_inode hooks playing nasty games releasing the
+ * spinlock and temporarily grabbing refs, in turn opening a possibility
+ * someone else will sneak in and grab a ref while it happens.
+ *
+ * If such a hook returns 0 (== don't drop) it ends being up harmless as long
+ * as the inode is not marked with I_DONTCACHE. Otherwise we are proceeding
+ * with teardown despite references being present.
+ *
+ * Damage-control the problem by including the count in the decision. However,
+ * assert no refs showed up if the hook decided to drop the inode.
+ */
+ if (drop)
+ VFS_BUG_ON_INODE(icount_read(inode) != 0, inode);
+
+ if (unlikely(icount_read(inode) > 0) ||
+ (!drop && !(inode_state_read(inode) & I_DONTCACHE) &&
+ (sb->s_flags & SB_ACTIVE))) {
__inode_lru_list_add(inode, true);
spin_unlock(&inode->i_lock);
return;
}
- /*
- * Re-check ->i_count in case the ->drop_inode() hooks played games.
- * Note we only execute this if the verdict was to drop the inode.
- */
- VFS_BUG_ON_INODE(icount_read(inode) != 0, inode);
-
if (drop) {
inode_state_set(inode, I_FREEING);
} else {
--
2.48.1
next prev parent reply other threads:[~2026-03-31 16:09 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-31 16:08 [PATCH v5 0/4] assorted ->i_count changes + extension of lockless handling Mateusz Guzik
2026-03-31 16:08 ` [PATCH v5 1/4] fs: add icount_read_once() and stop open-coding ->i_count loads Mateusz Guzik
2026-04-01 17:29 ` Jan Kara
2026-03-31 16:08 ` [PATCH v5 2/4] fs: relocate and tidy up ihold() Mateusz Guzik
2026-04-01 17:28 ` Jan Kara
2026-03-31 16:08 ` Mateusz Guzik [this message]
2026-04-01 17:45 ` [PATCH v5 3/4] fs: handle potential filesystems which use I_DONTCACHE and drop the lock in ->drop_inode Jan Kara
2026-04-01 18:50 ` Mateusz Guzik
2026-04-09 13:40 ` Christian Brauner
2026-04-09 14:55 ` Mateusz Guzik
2026-04-10 9:41 ` Christian Brauner
2026-03-31 16:08 ` [PATCH v5 4/4] fs: allow lockless ->i_count bumps as long as it does not transition 0->1 Mateusz Guzik
2026-04-08 17:01 ` Jan Kara
2026-04-18 12:32 ` Mateusz Guzik
2026-04-20 7:56 ` Jan Kara
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=20260331160851.3854954-4-mjguzik@gmail.com \
--to=mjguzik@gmail.com \
--cc=brauner@kernel.org \
--cc=jack@suse.cz \
--cc=linux-fsdevel@vger.kernel.org \
--cc=linux-kernel@vger.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 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.