diff mbox series

[16/26] btrfs-progs: zoned: reset zone of freed block group

Message ID 501d22b99fbdf8439fd9726ead439d29b5de8363.1619416549.git.naohiro.aota@wdc.com (mailing list archive)
State New, archived
Headers show
Series btrfs-progs: zoned: zoned block device support | expand

Commit Message

Naohiro Aota April 26, 2021, 6:27 a.m. UTC
When freeing a chunk, we can/should reset the underlying device zones for
the chunk. This commit introduces btrfs_reset_chunk_zones() and reset the
zones.

Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
---
 kernel-shared/extent-tree.c | 10 ++++++++++
 kernel-shared/zoned.c       | 28 ++++++++++++++++++++++++++++
 kernel-shared/zoned.h       |  8 ++++++++
 3 files changed, 46 insertions(+)
diff mbox series

Patch

diff --git a/kernel-shared/extent-tree.c b/kernel-shared/extent-tree.c
index 7453bf9f49b6..e3ffe146606f 100644
--- a/kernel-shared/extent-tree.c
+++ b/kernel-shared/extent-tree.c
@@ -21,6 +21,7 @@ 
 #include <stdint.h>
 #include <math.h>
 #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,15 @@  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 793c524ed66f..22e0245abaf6 100644
--- a/kernel-shared/zoned.c
+++ b/kernel-shared/zoned.c
@@ -886,6 +886,34 @@  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 1ba5a9939a3c..70044acc4d94 100644
--- a/kernel-shared/zoned.h
+++ b/kernel-shared/zoned.h
@@ -89,6 +89,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
 #define sbread(fd, buf, offset) \
 	pread64(fd, buf, BTRFS_SUPER_INFO_SIZE, offset)
@@ -130,6 +132,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)