From: Yun Zhou <yun.zhou@windriver.com>
To: <tytso@mit.edu>, <adilger.kernel@dilger.ca>,
<libaokun@linux.alibaba.com>, <jack@suse.cz>,
<ojaswin@linux.ibm.com>, <ritesh.list@gmail.com>,
<yi.zhang@huawei.com>
Cc: <linux-ext4@vger.kernel.org>, <linux-kernel@vger.kernel.org>,
<yun.zhou@windriver.com>
Subject: [PATCH v2] ext4: fix deadlock in ext4_evict_ea_inode() vs cache_find()
Date: Mon, 29 Jun 2026 14:27:33 +0800 [thread overview]
Message-ID: <20260629062733.1788981-1-yun.zhou@windriver.com> (raw)
ext4_evict_ea_inode() calls mb_cache_entry_wait_unused() to wait for
the EA inode's mb_cache entry refcount to drop before deleting it.
This can deadlock against ext4_xattr_inode_cache_find() which holds
an mb_cache entry reference while calling ext4_iget():
Thread A (evicting EA inode X):
ext4_evict_ea_inode -> mb_cache_entry_wait_unused [waits for refcnt]
Thread B (setxattr looking for dedup):
ext4_xattr_inode_cache_find -> mb_cache_entry_find [holds refcnt]
-> ext4_iget(X) -> __wait_on_freeing_inode [waits on I_FREEING]
Thread A's eviction sets I_FREEING and then waits for the mb_cache
refcount to drop. Thread B holds that refcount and waits for
I_FREEING to clear -- circular dependency.
Fix by making ext4_evict_ea_inode() non-blocking: try to delete the
entry once, and if it's currently in use, clear MBE_REUSABLE_B and
release it. Clearing the reusable bit prevents future cache lookups
from finding this entry (mb_cache_entry_find skips non-reusable
entries), avoiding stale hits that could trigger spurious filesystem
errors when the inode number is later reused for a non-EA inode.
Fixes: 458aee4a6e5b ("ext4: remove EA inode entry from mbcache on inode eviction")
Reported-by: syzbot+fd5533bcd0f7343bb8ca@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=fd5533bcd0f7343bb8ca
Signed-off-by: Yun Zhou <yun.zhou@windriver.com>
---
v2:
- Clear MBE_REUSABLE_B on the in-use entry instead of just leaving it
stale. This prevents future cache lookups from finding the entry,
avoiding spurious ext4_error_inode() if the inode number is later
reallocated to a non-EA inode. [1]
[1] https://sashiko.dev/#/patchset/20260629052732.1442618-1-yun.zhou@windriver.com?part=1
fs/ext4/xattr.c | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/fs/ext4/xattr.c b/fs/ext4/xattr.c
index 85ad2561474b..3588fe933d5e 100644
--- a/fs/ext4/xattr.c
+++ b/fs/ext4/xattr.c
@@ -471,10 +471,17 @@ void ext4_evict_ea_inode(struct inode *inode)
if (!EA_INODE_CACHE(inode))
return;
- /* Wait for entry to get unused so that we can remove it */
- while ((oe = mb_cache_entry_delete_or_get(EA_INODE_CACHE(inode),
- ext4_xattr_inode_get_hash(inode), inode->i_ino))) {
- mb_cache_entry_wait_unused(oe);
+ /*
+ * Try to delete the cache entry. If it's currently in use by
+ * another thread (e.g. ext4_xattr_inode_cache_find), mark it
+ * non-reusable so future lookups won't find it. Waiting here
+ * would deadlock if the other thread's iget is blocked on this
+ * inode's I_FREEING.
+ */
+ oe = mb_cache_entry_delete_or_get(EA_INODE_CACHE(inode),
+ ext4_xattr_inode_get_hash(inode), inode->i_ino);
+ if (oe) {
+ clear_bit(MBE_REUSABLE_B, &oe->e_flags);
mb_cache_entry_put(EA_INODE_CACHE(inode), oe);
}
}
--
2.43.0
reply other threads:[~2026-06-29 6:33 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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=20260629062733.1788981-1-yun.zhou@windriver.com \
--to=yun.zhou@windriver.com \
--cc=adilger.kernel@dilger.ca \
--cc=jack@suse.cz \
--cc=libaokun@linux.alibaba.com \
--cc=linux-ext4@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=ojaswin@linux.ibm.com \
--cc=ritesh.list@gmail.com \
--cc=tytso@mit.edu \
--cc=yi.zhang@huawei.com \
/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