Re: [PATCH] ext4: convert inline data to extents when truncate exceeds inline size

From: Deepanshu Kartikey

Date: Mon Mar 09 2026 - 21:51:09 EST


On Sat, Feb 7, 2026 at 10:06 AM Deepanshu Kartikey
<kartikey406@xxxxxxxxx> wrote:
>
> Add a check in ext4_setattr() to convert files from inline data storage
> to extent-based storage when truncate() grows the file size beyond the
> inline capacity. This prevents the filesystem from entering an
> inconsistent state where the inline data flag is set but the file size
> exceeds what can be stored inline.
>
> Without this fix, the following sequence causes a kernel BUG_ON():
>
> 1. Mount filesystem with inode that has inline flag set and small size
> 2. truncate(file, 50MB) - grows size but inline flag remains set
> 3. sendfile() attempts to write data
> 4. ext4_write_inline_data() hits BUG_ON(write_size > inline_capacity)
>
> The crash occurs because ext4_write_inline_data() expects inline storage
> to accommodate the write, but the actual inline capacity (~60 bytes for
> i_block + ~96 bytes for xattrs) is far smaller than the file size and
> write request.
>
> The fix checks if the new size from setattr exceeds the inode's actual
> inline capacity (EXT4_I(inode)->i_inline_size) and converts the file to
> extent-based storage before proceeding with the size change.
>
> This addresses the root cause by ensuring the inline data flag and file
> size remain consistent during truncate operations.
>
> Reported-by: syzbot+7de5fe447862fc37576f@xxxxxxxxxxxxxxxxxxxxxxxxx
> Closes: https://syzkaller.appspot.com/bug?extid=7de5fe447862fc37576f
> Tested-by: syzbot+7de5fe447862fc37576f@xxxxxxxxxxxxxxxxxxxxxxxxx
> Signed-off-by: Deepanshu Kartikey <Kartikey406@xxxxxxxxx>
> ---
> fs/ext4/inode.c | 12 ++++++++++++
> 1 file changed, 12 insertions(+)
>
> diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
> index 0c466ccbed69..c3dc0422ff95 100644
> --- a/fs/ext4/inode.c
> +++ b/fs/ext4/inode.c
> @@ -5901,6 +5901,18 @@ int ext4_setattr(struct mnt_idmap *idmap, struct dentry *dentry,
> if (attr->ia_size == inode->i_size)
> inc_ivers = false;
>
> + /*
> + * If file has inline data but new size exceeds inline capacity,
> + * convert to extent-based storage first to prevent inconsistent
> + * state (inline flag set but size exceeds inline capacity).
> + */
> + if (ext4_has_inline_data(inode) &&
> + attr->ia_size > EXT4_I(inode)->i_inline_size) {
> + error = ext4_convert_inline_data(inode);
> + if (error)
> + goto err_out;
> + }
> +
> if (shrink) {
> if (ext4_should_order_data(inode)) {
> error = ext4_begin_ordered_truncate(inode,
> --
> 2.43.0
>


Hi Ted, Andreas, and ext4 maintainers,

I submitted this patch on February 7th to fix a kernel BUG_ON in
ext4_write_inline_data() reported by syzbot:

https://syzkaller.appspot.com/bug?extid=7de5fe447862fc37576f

The patch adds inline->extent conversion in ext4_setattr() when truncate()
grows a file beyond inline capacity, preventing the filesystem from entering
an inconsistent state where the inline flag is set but size exceeds capacity.

I wanted to follow up to see if there are any comments or feedback on the
approach.

Original patch:
https://lore.kernel.org/all/20260207043607.1175976-1-kartikey406@xxxxxxxxx/T/

Thanks,
Deepanshu Kartikey