* [PATCH 1/2] ext4: skip extra isize expansion during mount to prevent deadlock
@ 2026-06-23 6:19 Yun Zhou
2026-06-23 6:19 ` [PATCH 2/2] ext4: set EXT4_STATE_NO_EXPAND in ext4_evict_inode Yun Zhou
0 siblings, 1 reply; 3+ messages in thread
From: Yun Zhou @ 2026-06-23 6:19 UTC (permalink / raw)
To: tytso, adilger.kernel, libaokun, jack, ojaswin, ritesh.list,
yi.zhang
Cc: linux-ext4, linux-kernel, yun.zhou
ext4_try_to_expand_extra_isize() is called from __ext4_mark_inode_dirty()
while holding an active jbd2 handle. During mount (!SB_ACTIVE), the
expand path may move xattrs to external blocks and release ea_inodes via
iput(). When !SB_ACTIVE, iput() calls write_inode_now() which acquires
s_writepages_rwsem, creating a circular lock dependency:
s_writepages_rwsem --> jbd2_handle --> xattr_sem --> s_writepages_rwsem
This can be triggered via:
ext4_process_orphan() -> ext4_truncate() -> ext4_mark_inode_dirty()
-> ext4_try_to_expand_extra_isize()
or:
ext4_evict_inode() -> ext4_mark_inode_dirty()
-> ext4_try_to_expand_extra_isize()
Skip expansion when !SB_ACTIVE. This is a minor loss of functionality
(extra isize won't grow for these inodes during mount), which e2fsck
can resolve later if needed.
Reported-by: syzbot+5d19358d7eb30ffb0cc5@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=5d19358d7eb30ffb0cc5
Fixes: c8585c6fcaf2 ("ext4: fix races between changing inode journal mode and ext4_writepages")
Signed-off-by: Yun Zhou <yun.zhou@windriver.com>
Reviewed-by: Jan Kara <jack@suse.cz>
---
fs/ext4/inode.c | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index ce99807c5f5b..a5409324d965 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -6510,6 +6510,16 @@ static int ext4_try_to_expand_extra_isize(struct inode *inode,
if (ext4_test_inode_state(inode, EXT4_STATE_NO_EXPAND))
return -EOVERFLOW;
+ /*
+ * Skip expansion during mount (!SB_ACTIVE). Expanding extra isize
+ * may move xattrs to external blocks and release ea_inodes via iput.
+ * When !SB_ACTIVE, iput triggers write_inode_now() which acquires
+ * s_writepages_rwsem, causing a deadlock with the caller's active
+ * jbd2 handle (lock order: s_writepages_rwsem -> jbd2_handle).
+ */
+ if (unlikely(!(inode->i_sb->s_flags & SB_ACTIVE)))
+ return -EBUSY;
+
/*
* In nojournal mode, we can immediately attempt to expand
* the inode. When journaled, we first need to obtain extra
--
2.43.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH 2/2] ext4: set EXT4_STATE_NO_EXPAND in ext4_evict_inode
2026-06-23 6:19 [PATCH 1/2] ext4: skip extra isize expansion during mount to prevent deadlock Yun Zhou
@ 2026-06-23 6:19 ` Yun Zhou
2026-07-07 6:57 ` Zhou, Yun
0 siblings, 1 reply; 3+ messages in thread
From: Yun Zhou @ 2026-06-23 6:19 UTC (permalink / raw)
To: tytso, adilger.kernel, libaokun, jack, ojaswin, ritesh.list,
yi.zhang
Cc: linux-ext4, linux-kernel, yun.zhou
An inode being evicted will never need its extra isize expanded. Set
EXT4_STATE_NO_EXPAND before ext4_mark_inode_dirty() in ext4_evict_inode()
to make this explicit and prevent any unnecessary work in
ext4_try_to_expand_extra_isize().
This also provides defense-in-depth for the s_writepages_rwsem deadlock
during mount-time orphan cleanup, ensuring the expand path is blocked
for inodes under eviction regardless of how they are reached.
Signed-off-by: Yun Zhou <yun.zhou@windriver.com>
Reviewed-by: Jan Kara <jack@suse.cz>
---
fs/ext4/inode.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index a5409324d965..0d131371ad3d 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -264,6 +264,7 @@ void ext4_evict_inode(struct inode *inode)
if (ext4_inode_is_fast_symlink(inode))
memset(EXT4_I(inode)->i_data, 0, sizeof(EXT4_I(inode)->i_data));
inode->i_size = 0;
+ ext4_set_inode_state(inode, EXT4_STATE_NO_EXPAND);
err = ext4_mark_inode_dirty(handle, inode);
if (err) {
ext4_warning(inode->i_sb,
--
2.43.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH 2/2] ext4: set EXT4_STATE_NO_EXPAND in ext4_evict_inode
2026-06-23 6:19 ` [PATCH 2/2] ext4: set EXT4_STATE_NO_EXPAND in ext4_evict_inode Yun Zhou
@ 2026-07-07 6:57 ` Zhou, Yun
0 siblings, 0 replies; 3+ messages in thread
From: Zhou, Yun @ 2026-07-07 6:57 UTC (permalink / raw)
To: tytso, adilger.kernel, libaokun, jack, ojaswin, ritesh.list,
yi.zhang
Cc: linux-ext4, linux-kernel
Friendly ping
On 6/23/26 14:19, Yun Zhou wrote:
> An inode being evicted will never need its extra isize expanded. Set
> EXT4_STATE_NO_EXPAND before ext4_mark_inode_dirty() in ext4_evict_inode()
> to make this explicit and prevent any unnecessary work in
> ext4_try_to_expand_extra_isize().
>
> This also provides defense-in-depth for the s_writepages_rwsem deadlock
> during mount-time orphan cleanup, ensuring the expand path is blocked
> for inodes under eviction regardless of how they are reached.
>
> Signed-off-by: Yun Zhou <yun.zhou@windriver.com>
> Reviewed-by: Jan Kara <jack@suse.cz>
> ---
> fs/ext4/inode.c | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
> index a5409324d965..0d131371ad3d 100644
> --- a/fs/ext4/inode.c
> +++ b/fs/ext4/inode.c
> @@ -264,6 +264,7 @@ void ext4_evict_inode(struct inode *inode)
> if (ext4_inode_is_fast_symlink(inode))
> memset(EXT4_I(inode)->i_data, 0, sizeof(EXT4_I(inode)->i_data));
> inode->i_size = 0;
> + ext4_set_inode_state(inode, EXT4_STATE_NO_EXPAND);
> err = ext4_mark_inode_dirty(handle, inode);
> if (err) {
> ext4_warning(inode->i_sb,
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-07-07 6:57 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-23 6:19 [PATCH 1/2] ext4: skip extra isize expansion during mount to prevent deadlock Yun Zhou
2026-06-23 6:19 ` [PATCH 2/2] ext4: set EXT4_STATE_NO_EXPAND in ext4_evict_inode Yun Zhou
2026-07-07 6:57 ` Zhou, Yun
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox