mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH RFC] ext4: add i_data_sem protection in ext4_destroy_inline_data_nolock()
@ 2025-11-04  9:33 Alexey Nepomnyashih
  2025-11-17 19:13 ` Theodore Ts'o
  0 siblings, 1 reply; 2+ messages in thread
From: Alexey Nepomnyashih @ 2025-11-04  9:33 UTC (permalink / raw)
  To: Theodore Ts'o
  Cc: Alexey Nepomnyashih, Andreas Dilger, linux-ext4, linux-kernel,
	lvc-project, stable

Fix a race between inline data destruction and block mapping.

The function ext4_destroy_inline_data_nolock() changes the inode data
layout by clearing EXT4_INODE_INLINE_DATA and setting EXT4_INODE_EXTENTS.
At the same time, another thread may execute ext4_map_blocks(), which
tests EXT4_INODE_EXTENTS to decide whether to call ext4_ext_map_blocks()
or ext4_ind_map_blocks().

Without i_data_sem protection, ext4_ind_map_blocks() may receive inode
with EXT4_INODE_EXTENTS flag and triggering assert.

kernel BUG at fs/ext4/indirect.c:546!
EXT4-fs (loop2): unmounting filesystem.
invalid opcode: 0000 [#1] PREEMPT SMP KASAN NOPTI
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.12.0-1 04/01/2014
RIP: 0010:ext4_ind_map_blocks.cold+0x2b/0x5a fs/ext4/indirect.c:546

Call Trace:
 <TASK>
 ext4_map_blocks+0xb9b/0x16f0 fs/ext4/inode.c:681
 _ext4_get_block+0x242/0x590 fs/ext4/inode.c:822
 ext4_block_write_begin+0x48b/0x12c0 fs/ext4/inode.c:1124
 ext4_write_begin+0x598/0xef0 fs/ext4/inode.c:1255
 ext4_da_write_begin+0x21e/0x9c0 fs/ext4/inode.c:3000
 generic_perform_write+0x259/0x5d0 mm/filemap.c:3846
 ext4_buffered_write_iter+0x15b/0x470 fs/ext4/file.c:285
 ext4_file_write_iter+0x8e0/0x17f0 fs/ext4/file.c:679
 call_write_iter include/linux/fs.h:2271 [inline]
 do_iter_readv_writev+0x212/0x3c0 fs/read_write.c:735
 do_iter_write+0x186/0x710 fs/read_write.c:861
 vfs_iter_write+0x70/0xa0 fs/read_write.c:902
 iter_file_splice_write+0x73b/0xc90 fs/splice.c:685
 do_splice_from fs/splice.c:763 [inline]
 direct_splice_actor+0x10f/0x170 fs/splice.c:950
 splice_direct_to_actor+0x33a/0xa10 fs/splice.c:896
 do_splice_direct+0x1a9/0x280 fs/splice.c:1002
 do_sendfile+0xb13/0x12c0 fs/read_write.c:1255
 __do_sys_sendfile64 fs/read_write.c:1323 [inline]
 __se_sys_sendfile64 fs/read_write.c:1309 [inline]
 __x64_sys_sendfile64+0x1cf/0x210 fs/read_write.c:1309
 do_syscall_x64 arch/x86/entry/common.c:51 [inline]
 do_syscall_64+0x35/0x80 arch/x86/entry/common.c:81
 entry_SYSCALL_64_after_hwframe+0x6e/0xd8

Fixes: c755e251357a ("ext4: fix deadlock between inline_data and ext4_expand_extra_isize_ea()")
Cc: stable@vger.kernel.org # v4.11+
Signed-off-by: Alexey Nepomnyashih <sdl@nppct.ru>
---
 fs/ext4/inline.c | 7 ++++++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/fs/ext4/inline.c b/fs/ext4/inline.c
index 1b094a4f3866..ef7821f7fd26 100644
--- a/fs/ext4/inline.c
+++ b/fs/ext4/inline.c
@@ -446,9 +446,13 @@ static int ext4_destroy_inline_data_nolock(handle_t *handle,
 	if (!ei->i_inline_off)
 		return 0;
 
+	down_write(&ei->i_data_sem);
+
 	error = ext4_get_inode_loc(inode, &is.iloc);
-	if (error)
+	if (error) {
+		up_write(&ei->i_data_sem);
 		return error;
+	}
 
 	error = ext4_xattr_ibody_find(inode, &i, &is);
 	if (error)
@@ -487,6 +491,7 @@ static int ext4_destroy_inline_data_nolock(handle_t *handle,
 	brelse(is.iloc.bh);
 	if (error == -ENODATA)
 		error = 0;
+	up_write(&ei->i_data_sem);
 	return error;
 }
 
-- 
2.43.0


^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: [PATCH RFC] ext4: add i_data_sem protection in ext4_destroy_inline_data_nolock()
  2025-11-04  9:33 [PATCH RFC] ext4: add i_data_sem protection in ext4_destroy_inline_data_nolock() Alexey Nepomnyashih
@ 2025-11-17 19:13 ` Theodore Ts'o
  0 siblings, 0 replies; 2+ messages in thread
From: Theodore Ts'o @ 2025-11-17 19:13 UTC (permalink / raw)
  To: Alexey Nepomnyashih
  Cc: Theodore Ts'o, Andreas Dilger, linux-ext4, linux-kernel,
	lvc-project, stable


On Tue, 04 Nov 2025 09:33:25 +0000, Alexey Nepomnyashih wrote:
> Fix a race between inline data destruction and block mapping.
> 
> The function ext4_destroy_inline_data_nolock() changes the inode data
> layout by clearing EXT4_INODE_INLINE_DATA and setting EXT4_INODE_EXTENTS.
> At the same time, another thread may execute ext4_map_blocks(), which
> tests EXT4_INODE_EXTENTS to decide whether to call ext4_ext_map_blocks()
> or ext4_ind_map_blocks().
> 
> [...]

Applied, thanks!

[1/1] ext4: add i_data_sem protection in ext4_destroy_inline_data_nolock()
      commit: 103ce01cd045197461d654f62f1a30cabedbcad4

Best regards,
-- 
Theodore Ts'o <tytso@mit.edu>

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2025-11-17 19:14 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2025-11-04  9:33 [PATCH RFC] ext4: add i_data_sem protection in ext4_destroy_inline_data_nolock() Alexey Nepomnyashih
2025-11-17 19:13 ` Theodore Ts'o

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®