From 5fd9956f632035ed306eae0177337c223487ae5e Mon Sep 17 00:00:00 2001 From: Naohiro Aota Date: Mon, 26 Apr 2021 15:27:32 +0900 Subject: [PATCH] btrfs-progs: zoned: reset zone of freed block group When freeing a chunk, we can/should reset the underlying device zones for the chunk. Introduce btrfs_reset_chunk_zones() and reset the zones. Signed-off-by: Naohiro Aota Signed-off-by: David Sterba --- kernel-shared/extent-tree.c | 9 +++++++++ kernel-shared/zoned.c | 27 +++++++++++++++++++++++++++ kernel-shared/zoned.h | 8 ++++++++ 3 files changed, 44 insertions(+) diff --git a/kernel-shared/extent-tree.c b/kernel-shared/extent-tree.c index 7453bf9f..4ed3c1f3 100644 --- a/kernel-shared/extent-tree.c +++ b/kernel-shared/extent-tree.c @@ -21,6 +21,7 @@ #include #include #include "kerncompat.h" +#include "kernel-lib/list.h" #include "kernel-lib/radix-tree.h" #include "kernel-lib/rbtree.h" #include "kernel-shared/ctree.h" @@ -3013,6 +3014,14 @@ static int free_chunk_dev_extent_items(struct btrfs_trans_handle *trans, struct btrfs_chunk); num_stripes = btrfs_chunk_num_stripes(path->nodes[0], chunk); for (i = 0; i < num_stripes; i++) { + u64 devid = btrfs_stripe_devid_nr(path->nodes[0], chunk, i); + u64 offset = btrfs_stripe_offset_nr(path->nodes[0], chunk, i); + u64 length = btrfs_stripe_length(fs_info, path->nodes[0], chunk); + + ret = btrfs_reset_chunk_zones(fs_info, devid, offset, length); + if (ret < 0) + goto out; + ret = free_dev_extent_item(trans, fs_info, btrfs_stripe_devid_nr(path->nodes[0], chunk, i), btrfs_stripe_offset_nr(path->nodes[0], chunk, i)); diff --git a/kernel-shared/zoned.c b/kernel-shared/zoned.c index 1ec40960..50d24798 100644 --- a/kernel-shared/zoned.c +++ b/kernel-shared/zoned.c @@ -881,6 +881,33 @@ bool btrfs_redirty_extent_buffer_for_zoned(struct btrfs_fs_info *fs_info, return false; } +int btrfs_reset_chunk_zones(struct btrfs_fs_info *fs_info, u64 devid, + u64 offset, u64 length) +{ + struct btrfs_device *device; + + list_for_each_entry(device, &fs_info->fs_devices->devices, dev_list) { + struct btrfs_zoned_device_info *zinfo; + struct blk_zone *reset; + + if (device->devid != devid) + continue; + + zinfo = device->zone_info; + if (!zone_is_sequential(zinfo, offset)) + continue; + + reset = &zinfo->zones[offset / zinfo->zone_size]; + if (btrfs_reset_dev_zone(device->fd, reset)) { + error("zoned: failed to reset zone %llu: %m", + offset / zinfo->zone_size); + return -EIO; + } + } + + return 0; +} + #endif int btrfs_get_dev_zone_info_all_devices(struct btrfs_fs_info *fs_info) diff --git a/kernel-shared/zoned.h b/kernel-shared/zoned.h index bcbdeda2..f8f841aa 100644 --- a/kernel-shared/zoned.h +++ b/kernel-shared/zoned.h @@ -92,6 +92,8 @@ int btrfs_load_block_group_zone_info(struct btrfs_fs_info *fs_info, struct btrfs_block_group *cache); bool btrfs_redirty_extent_buffer_for_zoned(struct btrfs_fs_info *fs_info, u64 start, u64 end); +int btrfs_reset_chunk_zones(struct btrfs_fs_info *fs_info, u64 devid, + u64 offset, u64 length); #else @@ -135,6 +137,12 @@ static inline bool btrfs_redirty_extent_buffer_for_zoned( return false; } +static inline int btrfs_reset_chunk_zones(struct btrfs_fs_info *fs_info, + u64 devid, u64 offset, u64 length) +{ + return 0; +} + #endif /* BTRFS_ZONED */ static inline bool btrfs_dev_is_sequential(struct btrfs_device *device, u64 pos)