Re: [PATCH] btrfs: zoned: don't submit orphaned extent buffers

Qu Wenruo <[email protected]>
Newsgroups org.kernel.vger.linux-btrfs,org.kernel.vger.stable
Message-ID <[email protected]>

在 2026/7/3 15:24, Johannes Thumshirn 写道:
> On a zoned filesystem btree_writepages() can encounter a dirty metadata
> extent buffer whose block group no longer exists. Submitting a write for
> such a buffer maps it to a stale/removed block-group and leaves the folio
> under writeback forever, hanging later in filemap_fdatawait_range(), for
> example the iput(btree_inode) in close_ctree(), which then hangs unmount.
> 
> This is caused by btrfs_clear_buffer_dirty() not clearing the dirty bit of
> a freed tree block but it sets EXTENT_BUFFER_ZONED_ZEROOUT and keeps the
> buffer dirty so that it is still written out to keep the zone's
> meta_write_pointer advancing sequentially. So a freed metadata block
> legitimately stays dirty until that zero-write completes.
> 
> Dropping these buffers is safe: the block group is empty, so they are
> stale, unreferenced, already-freed blocks. Once the zone is reset their
> zero-write is unneeded. Instead of submitting a such a write, finish the
> writeback immediately.
> 
> Reported-by: Shin'ichiro Kawasaki <[email protected]>
> Fixes: 7db94301a980 ("btrfs: zoned: introduce block group context to btrfs_eb_write_context")
> Cc: [email protected]
> Signed-off-by: Johannes Thumshirn <[email protected]>
> ---
>   fs/btrfs/extent_io.c | 16 ++++++++++++++--
>   1 file changed, 14 insertions(+), 2 deletions(-)
> 
> diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c
> index 0edd532174fa..4a029ae719e9 100644
> --- a/fs/btrfs/extent_io.c
> +++ b/fs/btrfs/extent_io.c
> @@ -2280,7 +2280,8 @@ static void prepare_eb_write(struct extent_buffer *eb)
>   }
>   
>   static noinline_for_stack void write_one_eb(struct extent_buffer *eb,
> -					    struct writeback_control *wbc)
> +					    struct writeback_control *wbc,
> +					    bool submit)
>   {
>   	struct btrfs_fs_info *fs_info = eb->fs_info;
>   	struct btrfs_bio *bbio;
> @@ -2310,6 +2311,12 @@ static noinline_for_stack void write_one_eb(struct extent_buffer *eb,
>   		wbc_account_cgroup_owner(wbc, folio, range_len);
>   		folio_unlock(folio);
>   	}
> +
> +	if (!submit) {
> +		btrfs_bio_end_io(bbio, BLK_STS_OK);
> +		return;
> +	}
> +
>   	/*
>   	 * If the fs is already in error status, do not submit any writeback
>   	 * but immediately finish it.
> @@ -2397,6 +2404,8 @@ int btree_writepages(struct address_space *mapping, struct writeback_control *wb
>   		struct extent_buffer *eb;
>   
>   		while ((eb = eb_batch_next(&batch)) != NULL) {
> +			bool submit = true;
> +
>   			ctx.eb = eb;
>   
>   			ret = btrfs_check_meta_write_pointer(eb->fs_info, &ctx);
> @@ -2411,6 +2420,9 @@ int btree_writepages(struct address_space *mapping, struct writeback_control *wb
>   				continue;
>   			}
>   
> +			if (btrfs_is_zoned(fs_info) && !ctx.zoned_bg)
> +				submit = false;
> +
>   			if (!lock_extent_buffer_for_io(eb, wbc))
>   				continue;
>   
> @@ -2420,7 +2432,7 @@ int btree_writepages(struct address_space *mapping, struct writeback_control *wb
>   				btrfs_schedule_zone_finish_bg(ctx.zoned_bg, eb);
>   				ctx.zoned_bg->meta_write_pointer += eb->len;
>   			}
> -			write_one_eb(eb, wbc);
> +			write_one_eb(eb, wbc, submit);

I understand this is the minimal fix, but I can't help but wondering, 
would it be more instinctual to release all ebs inside a zoned metadata 
bg when freeing the bg?

Thanks,
Qu

>   		}
>   		nr_to_write_done = (wbc->nr_to_write <= 0);
>   		eb_batch_release(&batch);
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.