Linux EXT4 FS development
 help / color / mirror / Atom feed
* [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