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@vger.kernel.org # 6.14+ Reviewed-by: Qu Wenruo Reviewed-by: Filipe Manana Signed-off-by: Josef Bacik --- 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