Re: [PATCH 2/5] btrfs: clear dirty blocks after a delalloc failure

From: Filipe Manana

Date: Mon Nov 02 2026 - 14:15:18 EST


On Fri, Oct 30, 2026 at 2:38 PM Josef Bacik <josef@xxxxxxxxxxxxxx> wrote:
>
> If writepage_delalloc() runs the first delalloc ranges of a folio and
> then btrfs_run_delalloc_range() fails, the blocks that already got an
> ordered extent are finished with an error through
> btrfs_mark_ordered_io_finished(), but their dirty bits are left set. The
> next writeback then submits blocks whose ordered extent is gone, or is
> about to be completed a second time.
>
> Fix by clearing the dirty bits and cycling the writeback state for those
> blocks, as submit_write_sector() does for a block it fails to submit.
>
> Fixes: 72dad8e377af ("btrfs: fix double accounting race when btrfs_run_delalloc_range() failed")
> CC: stable@xxxxxxxxxxxxxxx # 6.14+
> Assisted-by: LLM
> Signed-off-by: Josef Bacik <josef@xxxxxxxxxxxxxx>

Reviewed-by: Filipe Manana <fdmanana@xxxxxxxx>

Looks good, thanks.

> ---
> fs/btrfs/extent_io.c | 10 ++++++++++
> 1 file changed, 10 insertions(+)
>
> diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
> index 5ff630630490..3283835ccb5e 100644
> --- a/fs/btrfs/extent_io.c
> +++ b/fs/btrfs/extent_io.c
> @@ -1746,6 +1746,16 @@ static noinline_for_stack int writepage_delalloc(struct btrfs_inode *inode,
> u64 start = page_start + (start_bit << fs_info->sectorsize_bits);
> u32 len = (end_bit - start_bit) << fs_info->sectorsize_bits;
>
> + /*
> + * The blocks are not going to be submitted, so they
> + * must not stay dirty. Otherwise they are written back
> + * later without an ordered extent, or worse, with this
> + * one if it is still around, and invalidating the folio
> + * would account for them again.
> + */
> + btrfs_folio_clear_dirty(fs_info, folio, start, len);
> + btrfs_folio_set_writeback(fs_info, folio, start, len);
> + btrfs_folio_clear_writeback(fs_info, folio, start, len);
> btrfs_mark_ordered_io_finished(inode, start, len, false);
> }
> return ret;
>
> --
> 2.55.0
>
>