From: Zhang Yi <yizhang089@gmail.com>
To: sashiko-reviews@lists.linux.dev, Zhang Yi <yi.zhang@huaweicloud.com>
Cc: tytso@mit.edu, linux-ext4@vger.kernel.org
Subject: Re: [PATCH v7 14/31] ext4: rework handle credit accounting for unwritten extent conversion
Date: Sat, 10 Oct 2026 10:33:40 +0800 [thread overview]
Message-ID: <b82ca2bb-1026-440d-871f-d092e57a17e5@gmail.com> (raw)
In-Reply-To: <sashiko-outbox-165354@kernel.org>
On 10/9/2026 7:20 PM, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
> - [High] ext4: atomicity violation in fallocate extent conversion
> --
>
> commit 352cf8eb3125c707efc06205d4a61cc670cd67bf
> Author: Zhang Yi <yi.zhang@huawei.com>
>
> ext4: rework handle credit accounting for unwritten extent conversion
>
> This commit updates the unwritten extent conversion process to handle long
> merged ioends. It introduces a check using ext4_journal_ensure_credits to
> extend or restart the transaction if credits run low during the loop.
>
>> diff --git a/fs/ext4/extents.c b/fs/ext4/extents.c
>> index 76038b6c36552..83d040e36b682 100644
>> --- a/fs/ext4/extents.c
>> +++ b/fs/ext4/extents.c
> [ ... ]
>> @@ -5137,27 +5137,36 @@ int ext4_convert_unwritten_extents(handle_t *handle, struct inode *inode,
> [ ... ]
>> while (max_blocks) {
>> - if (credits) {
>> - handle = ext4_journal_start(inode, EXT4_HT_MAP_BLOCKS,
>> - credits);
>> - if (IS_ERR(handle)) {
>> - ret = PTR_ERR(handle);
>> - break;
>> - }
>> - }
>> + /*
>> + * The caller cannot know how many extents the range covers,
>> + * so make sure the transaction can take one more extent,
>> + * extending or restarting it once it is full. The reserved
>> + * handle of the buffer_head writeback path is safe as it has
>> + * enough credits for the conversion, so it is not restarted
>> + * here.
>> + */
>> + ret = ext4_journal_ensure_credits(handle, credits, 0);
>> + if (ret < 0)
>> + break;
>
> [Severity: High]
> Does restarting the caller's transaction here break atomicity requirements
> for fallocate?
>
> ext4_alloc_file_blocks relies on the atomicity of converting unwritten
> extents to written and adding the inode to the orphan list. This prevents
> e2fsck from flagging initialized extents beyond i_disksize as corruption on
> crash.
>
> If the transaction restarts during this conversion loop, the first batch of
> converted extents is committed to the journal before the loop finishes and
> ext4_orphan_add is called in the parent function:
>
> fs/ext4/extents.c:ext4_alloc_file_blocks() {
> ...
> ret = ext4_convert_unwritten_extents(handle, inode, ...);
> ...
> if (new_size && converted) {
> ret2 = ext4_orphan_add(handle, inode);
> ...
> }
>
> If a crash occurs after the transaction restarts but before ext4_orphan_add
> completes, will it leave the disk with initialized extents beyond i_disksize
> and no orphan list entry, triggering filesystem corruption warnings and
> silent truncations in e2fsck?
>
This is a pre-existing issue in ext4_alloc_file_blocks(), which is
extremely hard to trigger in practice, and the failure mode after the
patch will differ somewhat from before.
This can only be triggered by a size-extending FALLOC_FL_WRITE_ZEROES
that runs concurrently with another I/O completion. Since
ext4_alloc_file_blocks() holds i_rwsem, what it requires is that the
extent that the ext4_map_blocks() call at the top of the loop returned
as a single extent gets split before ext4_convert_unwritten_extents()
is called, so that the conversion is spread over more extents than the
extent tree had at map time. That means another unwritten extent
conversion has to land in that window, and the io_end conversion runs
from a workqueue, so it routinely completes only after the data
writeback and after the page cache has been dropped. A direct I/O
completion (ext4_dio_write_end_io()) can do the same. Buffered writes,
truncate and other fallocate calls are excluded by i_rwsem.
Before the patch, in the worst case, this would exhaust the handle
credits and cause a filesystem error. After the patch, since
ext4_journal_ensure_credits() will first try to extend the credits, the
credit exhaustion itself becomes much less likely, and only when the
extension fails, because the transaction is already at
j_max_transaction_buffers, will the transaction be restarted, which then
can trigger the issue Sashiko described.
This issue needs to be fixed separately, perhaps by moving
ext4_orphan_add() in ext4_alloc_file_blocks() before
ext4_convert_unwritten_extents().
Thanks,
Yi.
next prev parent reply other threads:[~2026-10-10 2:33 UTC|newest]
Thread overview: 78+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-09 10:30 [PATCH v7 00/31] ext4: use iomap for regular file's buffered I/O path Zhang Yi
2026-10-09 10:30 ` [PATCH v7 01/31] ext4: simplify size updating in ext4_setattr() Zhang Yi
2026-10-09 10:51 ` sashiko-bot
2026-10-09 10:30 ` [PATCH v7 02/31] ext4: factor out ext4_truncate_[up|down]() Zhang Yi
2026-10-09 10:54 ` sashiko-bot
2026-10-09 10:30 ` [PATCH v7 03/31] ext4: set EXT4_MAP_NEW flag for delayed allocated blocks Zhang Yi
2026-10-09 10:50 ` sashiko-bot
2026-10-09 10:30 ` [PATCH v7 04/31] ext4: recheck extent status tree before block allocation Zhang Yi
2026-10-09 10:54 ` sashiko-bot
2026-10-09 10:30 ` [PATCH v7 05/31] ext4: fix orig_mlen initialization in ext4_map_blocks() Zhang Yi
2026-10-09 10:53 ` sashiko-bot
2026-10-09 10:30 ` [PATCH v7 06/31] ext4: allow ext4_map_blocks() to start its own transaction handle Zhang Yi
2026-10-09 10:58 ` sashiko-bot
2026-10-09 10:30 ` [PATCH v7 07/31] ext4: avoid unnecessary transaction in ext4_map_blocks() for unwritten extents Zhang Yi
2026-10-09 10:53 ` sashiko-bot
2026-10-09 10:30 ` [PATCH v7 08/31] ext4: skip block allocation for holes in the data submission path Zhang Yi
2026-10-09 10:58 ` sashiko-bot
2026-10-10 0:55 ` Zhang Yi
2026-10-09 10:30 ` [PATCH v7 09/31] ext4: add iomap address space operations for buffered I/O Zhang Yi
2026-10-09 10:54 ` sashiko-bot
2026-10-09 10:30 ` [PATCH v7 10/31] ext4: implement buffered read path using iomap Zhang Yi
2026-10-09 11:07 ` sashiko-bot
2026-10-09 10:30 ` [PATCH v7 11/31] ext4: pass out extent seq counter when mapping da blocks Zhang Yi
2026-10-09 10:55 ` sashiko-bot
2026-10-09 10:30 ` [PATCH v7 12/31] ext4: do not use data=ordered mode for inodes using buffered iomap path Zhang Yi
2026-10-09 11:01 ` sashiko-bot
2026-10-09 10:30 ` [PATCH v7 13/31] ext4: implement buffered write path using iomap Zhang Yi
2026-10-09 11:03 ` sashiko-bot
2026-10-09 10:30 ` [PATCH v7 14/31] ext4: rework handle credit accounting for unwritten extent conversion Zhang Yi
2026-10-09 11:20 ` sashiko-bot
2026-10-10 2:33 ` Zhang Yi [this message]
2026-10-09 10:30 ` [PATCH v7 15/31] ext4: implement writeback path using iomap Zhang Yi
2026-10-09 11:13 ` sashiko-bot
2026-10-09 10:30 ` [PATCH v7 16/31] ext4: implement mmap " Zhang Yi
2026-10-09 11:10 ` sashiko-bot
2026-10-09 10:30 ` [PATCH v7 17/31] ext4: implement partial block zero range " Zhang Yi
2026-10-09 11:09 ` sashiko-bot
2026-10-09 10:30 ` [PATCH v7 18/31] ext4: drain writeback before removing extents on the iomap path Zhang Yi
2026-10-09 11:06 ` sashiko-bot
2026-10-09 10:30 ` [PATCH v7 19/31] ext4: add block mapping tracepoints for iomap buffered I/O path Zhang Yi
2026-10-09 11:03 ` sashiko-bot
2026-10-10 3:04 ` Zhang Yi
2026-10-09 10:30 ` [PATCH v7 20/31] ext4: disable online defrag when inode using " Zhang Yi
2026-10-09 11:00 ` sashiko-bot
2026-10-09 10:30 ` [PATCH v7 21/31] ext4: add EXT4_STATE_DISKSIZE_GROW_PENDING state bit and helpers Zhang Yi
2026-10-09 11:04 ` sashiko-bot
2026-10-09 10:30 ` [PATCH v7 22/31] ext4: submit and wait for pending disksize-grow I/O on writeback Zhang Yi
2026-10-09 11:18 ` sashiko-bot
2026-10-10 3:11 ` Zhang Yi
2026-10-09 10:30 ` [PATCH v7 23/31] ext4: advance i_disksize to i_size upon disksize-grow I/O completion Zhang Yi
2026-10-09 11:19 ` sashiko-bot
2026-10-09 10:30 ` [PATCH v7 24/31] ext4: defer i_disksize update while DISKSIZE_GROW_PENDING is set Zhang Yi
2026-10-09 11:21 ` sashiko-bot
2026-10-10 3:35 ` Zhang Yi
2026-10-09 10:30 ` [PATCH v7 25/31] ext4: submit and wait for disksize-grow I/O in fallocate paths Zhang Yi
2026-10-09 11:25 ` sashiko-bot
2026-10-09 10:30 ` [PATCH v7 26/31] ext4: clear DISKSIZE_GROW_PENDING on truncate or error Zhang Yi
2026-10-09 11:16 ` sashiko-bot
2026-10-10 4:59 ` Zhang Yi
2026-10-09 10:30 ` [PATCH v7 27/31] ext4: set DISKSIZE_GROW_PENDING after zeroing unaligned EOF block Zhang Yi
2026-10-09 11:21 ` sashiko-bot
2026-10-10 7:21 ` Zhang Yi
2026-10-10 9:00 ` Ojaswin Mujoo
2026-10-10 9:50 ` Zhang Yi
2026-10-10 13:49 ` Ojaswin Mujoo
2026-10-10 15:54 ` Zhang Yi
2026-10-11 9:30 ` Ojaswin Mujoo
2026-10-09 10:30 ` [PATCH v7 28/31] ext4: add tracepoints for DISKSIZE_GROW_PENDING set, clear, and wait Zhang Yi
2026-10-09 11:13 ` sashiko-bot
2026-10-09 10:38 ` [PATCH v7 29/31] ext4: add tracepoints for EOF block zeroing and disksize-grow I/O Zhang Yi
2026-10-09 11:16 ` sashiko-bot
2026-10-09 10:38 ` [PATCH v7 30/31] ext4: partially enable iomap for the buffered I/O path of regular files Zhang Yi
2026-10-09 11:33 ` sashiko-bot
2026-10-10 8:09 ` Zhang Yi
2026-10-09 10:38 ` [PATCH v7 31/31] ext4: introduce a mount option for iomap buffered I/O path Zhang Yi
2026-10-09 11:17 ` sashiko-bot
2026-10-09 17:54 ` [syzbot ci] Re: ext4: use iomap for regular file's " syzbot ci
2026-10-10 8:44 ` Zhang Yi
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=b82ca2bb-1026-440d-871f-d092e57a17e5@gmail.com \
--to=yizhang089@gmail.com \
--cc=linux-ext4@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=tytso@mit.edu \
--cc=yi.zhang@huaweicloud.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox