]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
btrfs: zoned: reset meta_write_pointer on zone reset
authorJohannes Thumshirn <johannes.thumshirn@wdc.com>
Fri, 3 Jul 2026 05:54:45 +0000 (07:54 +0200)
committerDavid Sterba <dsterba@suse.com>
Tue, 21 Jul 2026 04:40:07 +0000 (06:40 +0200)
btrfs_reset_unused_block_groups() resets a block group's zone and sets
alloc_offset back to 0 so the space can be reused, but it leaves
meta_write_pointer pointing at the previous end of the zone.

Once the block group is reactivated and reused for metadata, newly
allocated tree blocks live before that stale write pointer.
btrfs_check_meta_write_pointer() then sees them behind the write pointer,
so they can never be written out in sequential order: the dirty extent
buffers are stranded and pin their btree_inode folios until unmount.

Reset meta_write_pointer back to the start of the block group for
metadata and system block groups.

Fixes: 453a73c3069a ("btrfs: zoned: reclaim unused zone by zone resetting")
Reviewed-by: Naohiro Aota <naohiro.aota@wdc.com>
Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/zoned.c

index 44a13ed6b8b2493e0cf09879346d70bfef239580..0706c0788cb29e878367f7056109051d23315f23 100644 (file)
@@ -3189,6 +3189,17 @@ int btrfs_reset_unused_block_groups(struct btrfs_space_info *space_info, u64 num
                reclaimed = bg->alloc_offset;
                bg->zone_unusable = bg->length - bg->zone_capacity;
                bg->alloc_offset = 0;
+               /*
+                * The zone was just reset to empty, so alloc_offset went back to
+                * the start of the zone. For metadata/system block groups the
+                * write pointer must follow it back to the start of the zone;
+                * otherwise it stays stale at the previous (finished) zone end,
+                * and metadata written into the reused zone would sit behind the
+                * write pointer, could never be written out in sequential order,
+                * and would be stranded (pinning its folio) until unmount.
+                */
+               if (bg->flags & (BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_SYSTEM))
+                       bg->meta_write_pointer = bg->start;
                /*
                 * This holds because we currently reset fully used then freed
                 * block group.