* FAILED: patch "[PATCH] ext4: fix ABBA deadlock in ext4_rmdir()" failed to apply to 6.6-stable tree
@ 2026-11-07 10:32 Sasha Levin
2026-11-10 14:23 ` [PATCH 6.6.y 1/2] ext4: Move CONFIG_UNICODE defguards into the code flow Sasha Levin
0 siblings, 1 reply; 3+ messages in thread
From: Sasha Levin @ 2026-11-07 10:32 UTC (permalink / raw)
To: senozhatsky, sarthakkukreti, jack, libaokun, yi.zhang, tytso; +Cc: stable
The patch below does not apply to the 6.6-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.6.y
git checkout FETCH_HEAD
git cherry-pick -x 19e16597f9baf1b5719a3a6c710486446f6808fd
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '20261107053253-failed-6.6-19e16597f9ba@kernel.org' --subject-prefix 'PATCH 6.6.y' 'HEAD^..'
Thanks,
Sasha
------------------ original commit in Linus's tree ------------------
From 19e16597f9baf1b5719a3a6c710486446f6808fd Mon Sep 17 00:00:00 2001
From: Sergey Senozhatsky <senozhatsky@chromium.org>
Date: Thu, 27 Aug 2026 21:50:20 +0900
Subject: [PATCH] ext4: fix ABBA deadlock in ext4_rmdir()
We observe the following ABBA deadlock (casefolding enabled):
INFO: task jbd2/dm-13-8:447 blocked for more than 720 seconds.
task:jbd2/dm-13-8 state:D stack:0 pid:447 tgid:447 ppid:2
Call Trace:
<TASK>
__schedule+0xc2c/0xe60
schedule+0x40/0xe0
jbd2_journal_wait_updates+0x8f/0xf0
jbd2_journal_commit_transaction+0x321/0x1850
kjournald2+0xa9/0x230
kthread+0x226/0x2a0
ret_from_fork+0x101/0x1e0
ret_from_fork_asm+0x1a/0x30
INFO: task Thread-10:4161 blocked for more than 720 seconds.
task:Thread-10 state:D stack:0 pid:4161 tgid:3848 ppid:540
Call Trace:
<TASK>
__schedule+0xc2c/0xe60
schedule+0x40/0xe0
wait_transaction_locked+0x8c/0xd0
start_this_handle+0x252/0x870
jbd2__journal_start+0x120/0x280
__ext4_journal_start_sb+0x11a/0x250
ext4_evict_inode+0x208/0x760
iput+0x222/0x5c0
dput+0x293/0x690
____fput+0x145/0x2b0
task_work_run+0x7a/0xb0
exit_to_user_mode_loop+0xc0/0xd0
do_syscall_64+0x14b/0xf10
entry_SYSCALL_64_after_hwframe+0x76/0x7e
NMI backtrace for cpu 0
CPU: 0 UID: 1010216 PID: 4160 Comm: Thread-7
RIP: 0010:d_walk+0x0/0x290
[..]
Call Trace:
<TASK>
shrink_dcache_parent+0xb2/0x100
d_invalidate+0x50/0x110
ext4_rmdir+0x3a2/0x3d0
vfs_rmdir+0x9d/0x1d0
do_rmdir+0xf0/0x330
__x64_sys_unlinkat+0x34/0x50
do_syscall_64+0x61/0xf10
The problem is that ext4_rmdir() calls d_invalidate() before stopping
the jbd2 transaction handle. Because d_invalidate() traverses child
dentries it can encounter dying or in-use dentries. If a concurrent
thread executing __dentry_kill() on a child dentry invokes ext4_evict_inode(),
it requests a new transaction handle via ext4_journal_start(), which
waits for all running handles to close. However, the thread executing
ext4_rmdir() still holds its active transaction handle while looping
in shrink_dcache_parent() waiting for the dying child dentry to complete
eviction.
Stop transaction handle in ext4_rmdir() before calling d_invalidate().
Cc: stable@kernel.org
Fixes: b886ee3e778e ("ext4: Support case-insensitive file name lookups")
Co-developed-by: Sarthak Kukreti <sarthakkukreti@google.com>
Signed-off-by: Sarthak Kukreti <sarthakkukreti@google.com>
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Baokun Li <libaokun@linux.alibaba.com>
Reviewed-by: Zhang Yi <yi.zhang@huawei.com>
Link: https://patch.msgid.link/20260827125158.4030598-1-senozhatsky@chromium.org
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
---
fs/ext4/namei.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index a6386c1d237f1..231a274b814ec 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -3209,19 +3209,20 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
ext4_fc_track_unlink(handle, dentry);
retval = ext4_mark_inode_dirty(handle, dir);
+end_rmdir:
+ brelse(bh);
+ if (handle)
+ ext4_journal_stop(handle);
+
/* VFS negative dentries are incompatible with Encoding and
* Case-insensitiveness. Eventually we'll want avoid
* invalidating the dentries here, alongside with returning the
* negative dentries at ext4_lookup(), when it is better
* supported by the VFS for the CI case.
*/
- if (IS_ENABLED(CONFIG_UNICODE) && IS_CASEFOLDED(dir))
+ if (!retval && IS_ENABLED(CONFIG_UNICODE) && IS_CASEFOLDED(dir))
d_invalidate(dentry);
-end_rmdir:
- brelse(bh);
- if (handle)
- ext4_journal_stop(handle);
return retval;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 6.6.y 1/2] ext4: Move CONFIG_UNICODE defguards into the code flow
2026-11-07 10:32 FAILED: patch "[PATCH] ext4: fix ABBA deadlock in ext4_rmdir()" failed to apply to 6.6-stable tree Sasha Levin
@ 2026-11-10 14:23 ` Sasha Levin
2026-11-10 14:23 ` [PATCH 6.6.y 2/2] ext4: fix ABBA deadlock in ext4_rmdir() Sasha Levin
0 siblings, 1 reply; 3+ messages in thread
From: Sasha Levin @ 2026-11-10 14:23 UTC (permalink / raw)
To: stable
Cc: Gabriel Krisman Bertazi, Eugen Hristev, Eric Biggers,
Gabriel Krisman Bertazi, Christian Brauner, Sasha Levin
From: Gabriel Krisman Bertazi <krisman@collabora.com>
[ Upstream commit d98c822232f8642960a69caedeb7909471127939 ]
Instead of a bunch of ifdefs, make the unicode built checks part of the
code flow where possible, as requested by Torvalds.
Signed-off-by: Gabriel Krisman Bertazi <krisman@collabora.com>
[eugen.hristev@collabora.com: port to 6.10-rc1]
Signed-off-by: Eugen Hristev <eugen.hristev@collabora.com>
Link: https://lore.kernel.org/r/20240606073353.47130-7-eugen.hristev@collabora.com
Reviewed-by: Eric Biggers <ebiggers@google.com>
Reviewed-by: Gabriel Krisman Bertazi <krisman@suse.de>
Signed-off-by: Christian Brauner <brauner@kernel.org>
Stable-dep-of: 19e16597f9ba ("ext4: fix ABBA deadlock in ext4_rmdir()")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/ext4/crypto.c | 10 ++--------
fs/ext4/ext4.h | 33 +++++++++++++++++++++------------
fs/ext4/namei.c | 14 +++++---------
fs/ext4/super.c | 4 +---
4 files changed, 29 insertions(+), 32 deletions(-)
diff --git a/fs/ext4/crypto.c b/fs/ext4/crypto.c
index 8497f6125a8eb..c52971f62e525 100644
--- a/fs/ext4/crypto.c
+++ b/fs/ext4/crypto.c
@@ -31,11 +31,10 @@ int ext4_fname_setup_filename(struct inode *dir, const struct qstr *iname,
ext4_fname_from_fscrypt_name(fname, &name);
-#if IS_ENABLED(CONFIG_UNICODE)
err = ext4_fname_setup_ci_filename(dir, iname, fname);
if (err)
ext4_fname_free_filename(fname);
-#endif
+
return err;
}
@@ -51,11 +50,9 @@ int ext4_fname_prepare_lookup(struct inode *dir, struct dentry *dentry,
ext4_fname_from_fscrypt_name(fname, &name);
-#if IS_ENABLED(CONFIG_UNICODE)
err = ext4_fname_setup_ci_filename(dir, &dentry->d_name, fname);
if (err)
ext4_fname_free_filename(fname);
-#endif
return err;
}
@@ -70,10 +67,7 @@ void ext4_fname_free_filename(struct ext4_filename *fname)
fname->usr_fname = NULL;
fname->disk_name.name = NULL;
-#if IS_ENABLED(CONFIG_UNICODE)
- kfree(fname->cf_name.name);
- fname->cf_name.name = NULL;
-#endif
+ ext4_fname_free_ci_filename(fname);
}
static bool uuid_is_zero(__u8 u[16])
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 5a9a05d62f549..c3200c942d676 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -2747,8 +2747,25 @@ ext4_fsblk_t ext4_inode_to_goal_block(struct inode *);
#if IS_ENABLED(CONFIG_UNICODE)
extern int ext4_fname_setup_ci_filename(struct inode *dir,
- const struct qstr *iname,
- struct ext4_filename *fname);
+ const struct qstr *iname,
+ struct ext4_filename *fname);
+
+static inline void ext4_fname_free_ci_filename(struct ext4_filename *fname)
+{
+ kfree(fname->cf_name.name);
+ fname->cf_name.name = NULL;
+}
+#else
+static inline int ext4_fname_setup_ci_filename(struct inode *dir,
+ const struct qstr *iname,
+ struct ext4_filename *fname)
+{
+ return 0;
+}
+
+static inline void ext4_fname_free_ci_filename(struct ext4_filename *fname)
+{
+}
#endif
/* ext4 encryption related stuff goes here crypto.c */
@@ -2771,16 +2788,11 @@ static inline int ext4_fname_setup_filename(struct inode *dir,
int lookup,
struct ext4_filename *fname)
{
- int err = 0;
fname->usr_fname = iname;
fname->disk_name.name = (unsigned char *) iname->name;
fname->disk_name.len = iname->len;
-#if IS_ENABLED(CONFIG_UNICODE)
- err = ext4_fname_setup_ci_filename(dir, iname, fname);
-#endif
-
- return err;
+ return ext4_fname_setup_ci_filename(dir, iname, fname);
}
static inline int ext4_fname_prepare_lookup(struct inode *dir,
@@ -2792,10 +2804,7 @@ static inline int ext4_fname_prepare_lookup(struct inode *dir,
static inline void ext4_fname_free_filename(struct ext4_filename *fname)
{
-#if IS_ENABLED(CONFIG_UNICODE)
- kfree(fname->cf_name.name);
- fname->cf_name.name = NULL;
-#endif
+ ext4_fname_free_ci_filename(fname);
}
static inline int ext4_ioctl_get_encryption_pwsalt(struct file *filp,
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 1e72aa6f207ed..c77a18ce76bc7 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -1875,8 +1875,7 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
}
}
-#if IS_ENABLED(CONFIG_UNICODE)
- if (!inode && IS_CASEFOLDED(dir)) {
+ if (IS_ENABLED(CONFIG_UNICODE) && !inode && IS_CASEFOLDED(dir)) {
/* Eventually we want to call d_add_ci(dentry, NULL)
* for negative dentries in the encoding case as
* well. For now, prevent the negative dentry
@@ -1884,7 +1883,7 @@ static struct dentry *ext4_lookup(struct inode *dir, struct dentry *dentry, unsi
*/
return NULL;
}
-#endif
+
return d_splice_alias(inode, dentry);
}
@@ -3260,16 +3259,14 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
ext4_fc_track_unlink(handle, dentry);
retval = ext4_mark_inode_dirty(handle, dir);
-#if IS_ENABLED(CONFIG_UNICODE)
/* VFS negative dentries are incompatible with Encoding and
* Case-insensitiveness. Eventually we'll want avoid
* invalidating the dentries here, alongside with returning the
* negative dentries at ext4_lookup(), when it is better
* supported by the VFS for the CI case.
*/
- if (IS_CASEFOLDED(dir))
+ if (IS_ENABLED(CONFIG_UNICODE) && IS_CASEFOLDED(dir))
d_invalidate(dentry);
-#endif
end_rmdir:
brelse(bh);
@@ -3371,16 +3368,15 @@ static int ext4_unlink(struct inode *dir, struct dentry *dentry)
goto out_trace;
retval = __ext4_unlink(dir, &dentry->d_name, d_inode(dentry), dentry);
-#if IS_ENABLED(CONFIG_UNICODE)
+
/* VFS negative dentries are incompatible with Encoding and
* Case-insensitiveness. Eventually we'll want avoid
* invalidating the dentries here, alongside with returning the
* negative dentries at ext4_lookup(), when it is better
* supported by the VFS for the CI case.
*/
- if (IS_CASEFOLDED(dir))
+ if (IS_ENABLED(CONFIG_UNICODE) && IS_CASEFOLDED(dir))
d_invalidate(dentry);
-#endif
out_trace:
trace_ext4_unlink_exit(dentry, retval);
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index 9be69402c704e..f91f36c39651c 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -3630,14 +3630,12 @@ int ext4_feature_set_ok(struct super_block *sb, int readonly)
return 0;
}
-#if !IS_ENABLED(CONFIG_UNICODE)
- if (ext4_has_feature_casefold(sb)) {
+ if (!IS_ENABLED(CONFIG_UNICODE) && ext4_has_feature_casefold(sb)) {
ext4_msg(sb, KERN_ERR,
"Filesystem with casefold feature cannot be "
"mounted without CONFIG_UNICODE");
return 0;
}
-#endif
if (readonly)
return 1;
--
2.53.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 6.6.y 2/2] ext4: fix ABBA deadlock in ext4_rmdir()
2026-11-10 14:23 ` [PATCH 6.6.y 1/2] ext4: Move CONFIG_UNICODE defguards into the code flow Sasha Levin
@ 2026-11-10 14:23 ` Sasha Levin
0 siblings, 0 replies; 3+ messages in thread
From: Sasha Levin @ 2026-11-10 14:23 UTC (permalink / raw)
To: stable
Cc: Sergey Senozhatsky, stable, Sarthak Kukreti, Jan Kara, Baokun Li,
Zhang Yi, Theodore Ts'o, Sasha Levin
From: Sergey Senozhatsky <senozhatsky@chromium.org>
[ Upstream commit 19e16597f9baf1b5719a3a6c710486446f6808fd ]
We observe the following ABBA deadlock (casefolding enabled):
INFO: task jbd2/dm-13-8:447 blocked for more than 720 seconds.
task:jbd2/dm-13-8 state:D stack:0 pid:447 tgid:447 ppid:2
Call Trace:
<TASK>
__schedule+0xc2c/0xe60
schedule+0x40/0xe0
jbd2_journal_wait_updates+0x8f/0xf0
jbd2_journal_commit_transaction+0x321/0x1850
kjournald2+0xa9/0x230
kthread+0x226/0x2a0
ret_from_fork+0x101/0x1e0
ret_from_fork_asm+0x1a/0x30
INFO: task Thread-10:4161 blocked for more than 720 seconds.
task:Thread-10 state:D stack:0 pid:4161 tgid:3848 ppid:540
Call Trace:
<TASK>
__schedule+0xc2c/0xe60
schedule+0x40/0xe0
wait_transaction_locked+0x8c/0xd0
start_this_handle+0x252/0x870
jbd2__journal_start+0x120/0x280
__ext4_journal_start_sb+0x11a/0x250
ext4_evict_inode+0x208/0x760
iput+0x222/0x5c0
dput+0x293/0x690
____fput+0x145/0x2b0
task_work_run+0x7a/0xb0
exit_to_user_mode_loop+0xc0/0xd0
do_syscall_64+0x14b/0xf10
entry_SYSCALL_64_after_hwframe+0x76/0x7e
NMI backtrace for cpu 0
CPU: 0 UID: 1010216 PID: 4160 Comm: Thread-7
RIP: 0010:d_walk+0x0/0x290
[..]
Call Trace:
<TASK>
shrink_dcache_parent+0xb2/0x100
d_invalidate+0x50/0x110
ext4_rmdir+0x3a2/0x3d0
vfs_rmdir+0x9d/0x1d0
do_rmdir+0xf0/0x330
__x64_sys_unlinkat+0x34/0x50
do_syscall_64+0x61/0xf10
The problem is that ext4_rmdir() calls d_invalidate() before stopping
the jbd2 transaction handle. Because d_invalidate() traverses child
dentries it can encounter dying or in-use dentries. If a concurrent
thread executing __dentry_kill() on a child dentry invokes ext4_evict_inode(),
it requests a new transaction handle via ext4_journal_start(), which
waits for all running handles to close. However, the thread executing
ext4_rmdir() still holds its active transaction handle while looping
in shrink_dcache_parent() waiting for the dying child dentry to complete
eviction.
Stop transaction handle in ext4_rmdir() before calling d_invalidate().
Cc: stable@kernel.org
Fixes: b886ee3e778e ("ext4: Support case-insensitive file name lookups")
Co-developed-by: Sarthak Kukreti <sarthakkukreti@google.com>
Signed-off-by: Sarthak Kukreti <sarthakkukreti@google.com>
Signed-off-by: Sergey Senozhatsky <senozhatsky@chromium.org>
Reviewed-by: Jan Kara <jack@suse.cz>
Reviewed-by: Baokun Li <libaokun@linux.alibaba.com>
Reviewed-by: Zhang Yi <yi.zhang@huawei.com>
Link: https://patch.msgid.link/20260827125158.4030598-1-senozhatsky@chromium.org
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/ext4/namei.c | 11 ++++++-----
1 file changed, 6 insertions(+), 5 deletions(-)
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index c77a18ce76bc7..b30ddb3750fd4 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -3259,19 +3259,20 @@ static int ext4_rmdir(struct inode *dir, struct dentry *dentry)
ext4_fc_track_unlink(handle, dentry);
retval = ext4_mark_inode_dirty(handle, dir);
+end_rmdir:
+ brelse(bh);
+ if (handle)
+ ext4_journal_stop(handle);
+
/* VFS negative dentries are incompatible with Encoding and
* Case-insensitiveness. Eventually we'll want avoid
* invalidating the dentries here, alongside with returning the
* negative dentries at ext4_lookup(), when it is better
* supported by the VFS for the CI case.
*/
- if (IS_ENABLED(CONFIG_UNICODE) && IS_CASEFOLDED(dir))
+ if (!retval && IS_ENABLED(CONFIG_UNICODE) && IS_CASEFOLDED(dir))
d_invalidate(dentry);
-end_rmdir:
- brelse(bh);
- if (handle)
- ext4_journal_stop(handle);
return retval;
}
--
2.53.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-11-10 14:23 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-11-07 10:32 FAILED: patch "[PATCH] ext4: fix ABBA deadlock in ext4_rmdir()" failed to apply to 6.6-stable tree Sasha Levin
2026-11-10 14:23 ` [PATCH 6.6.y 1/2] ext4: Move CONFIG_UNICODE defguards into the code flow Sasha Levin
2026-11-10 14:23 ` [PATCH 6.6.y 2/2] ext4: fix ABBA deadlock in ext4_rmdir() Sasha Levin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox