diff mbox series

btrfs: zoned: fix zone unusable accounting for freed reserved extent

Message ID 4d5f6524a0c84e98383ea52dcced34544ff4ae42.1728448186.git.naohiro.aota@wdc.com (mailing list archive)
State New, archived
Headers show
Series btrfs: zoned: fix zone unusable accounting for freed reserved extent | expand

Commit Message

Naohiro Aota Oct. 9, 2024, 4:30 a.m. UTC
When btrfs reserves an extent and does not use it (e.g, by an error), it
calls btrfs_free_reserved_extent() to free the reserved extent. In the
process, it calls btrfs_add_free_space() and then it accounts the region
bytes as block_group->zone_unusable.

However, it leaves the space_info->bytes_zone_unusable side not updated. As
a result, ENOSPC can happen while a space_info reservation succeeded. The
reservation is fine because the freed region is not added in
space_info->bytes_zone_unusable, leaving that space as "free". OTOH,
corresponding block group counts it as zone_unusable and its allocation
pointer is not rewound, we cannot allocate an extent from that block group.
That will also negate space_info's async/sync reclaim process, and cause an
ENOSPC error from the extent allocation process.

Fix that by returning the space to space_info->bytes_zone_unusable.
Ideally, since a bio is not submitted for this reserved region, we should
return the space to free space and rewind the allocation pointer. But, it
needs rework on extent allocation handling, so let it work in this way for
now.

Fixes: 169e0da91a21 ("btrfs: zoned: track unusable bytes for zones")
CC: stable@vger.kernel.org # 5.15+
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
---
 fs/btrfs/block-group.c | 2 ++
 1 file changed, 2 insertions(+)

Comments

David Sterba Oct. 11, 2024, 4:59 p.m. UTC | #1
On Wed, Oct 09, 2024 at 01:30:18PM +0900, Naohiro Aota wrote:
> When btrfs reserves an extent and does not use it (e.g, by an error), it
> calls btrfs_free_reserved_extent() to free the reserved extent. In the
> process, it calls btrfs_add_free_space() and then it accounts the region
> bytes as block_group->zone_unusable.
> 
> However, it leaves the space_info->bytes_zone_unusable side not updated. As
> a result, ENOSPC can happen while a space_info reservation succeeded. The
> reservation is fine because the freed region is not added in
> space_info->bytes_zone_unusable, leaving that space as "free". OTOH,
> corresponding block group counts it as zone_unusable and its allocation
> pointer is not rewound, we cannot allocate an extent from that block group.
> That will also negate space_info's async/sync reclaim process, and cause an
> ENOSPC error from the extent allocation process.
> 
> Fix that by returning the space to space_info->bytes_zone_unusable.
> Ideally, since a bio is not submitted for this reserved region, we should
> return the space to free space and rewind the allocation pointer. But, it
> needs rework on extent allocation handling, so let it work in this way for
> now.
> 
> Fixes: 169e0da91a21 ("btrfs: zoned: track unusable bytes for zones")
> CC: stable@vger.kernel.org # 5.15+
> Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>

Reviewed-by: David Sterba <dsterba@suse.com>
Johannes Thumshirn Oct. 14, 2024, 7:44 a.m. UTC | #2
Looks good,
Reviewed-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
diff mbox series

Patch

diff --git a/fs/btrfs/block-group.c b/fs/btrfs/block-group.c
index 5c5539eb82d3..4427c1b835e8 100644
--- a/fs/btrfs/block-group.c
+++ b/fs/btrfs/block-group.c
@@ -3819,6 +3819,8 @@  void btrfs_free_reserved_bytes(struct btrfs_block_group *cache,
 	spin_lock(&cache->lock);
 	if (cache->ro)
 		space_info->bytes_readonly += num_bytes;
+	else if (btrfs_is_zoned(cache->fs_info))
+		space_info->bytes_zone_unusable += num_bytes;
 	cache->reserved -= num_bytes;
 	space_info->bytes_reserved -= num_bytes;
 	space_info->max_extent_size = 0;