diff mbox series

[v14,03/42] btrfs: defer loading zone info after opening trees

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

Commit Message

Naohiro Aota Jan. 26, 2021, 2:24 a.m. UTC
This is preparation patch to implement zone emulation on a regular device.

To emulate zoned mode on a regular (non-zoned) device, we need to decide an
emulating zone size. Instead of making it compile-time static value, we'll
make it configurable at mkfs time. Since we have one zone == one device
extent restriction, we can determine the emulated zone size from the size
of a device extent. We can extend btrfs_get_dev_zone_info() to show a
regular device filled with conventional zones once the zone size is
decided.

The current call site of btrfs_get_dev_zone_info() during the mount process
is earlier than reading the trees, so we can't slice a regular device to
conventional zones. This patch defers the loading of zone info to
open_ctree() to load the emulated zone size from a device extent.

Reviewed-by: Josef Bacik <josef@toxicpanda.com>
Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>
---
 fs/btrfs/disk-io.c | 13 +++++++++++++
 fs/btrfs/volumes.c |  4 ----
 fs/btrfs/zoned.c   | 24 ++++++++++++++++++++++++
 fs/btrfs/zoned.h   |  7 +++++++
 4 files changed, 44 insertions(+), 4 deletions(-)

Comments

Anand Jain Jan. 30, 2021, 10:09 p.m. UTC | #1
On 1/26/2021 10:24 AM, Naohiro Aota wrote:
> This is preparation patch to implement zone emulation on a regular device.
> 
> To emulate zoned mode on a regular (non-zoned) device, we need to decide an
> emulating zone size. Instead of making it compile-time static value, we'll
> make it configurable at mkfs time. Since we have one zone == one device
> extent restriction, we can determine the emulated zone size from the size
> of a device extent. We can extend btrfs_get_dev_zone_info() to show a
> regular device filled with conventional zones once the zone size is
> decided.
> 
> The current call site of btrfs_get_dev_zone_info() during the mount process
> is earlier than reading the trees, so we can't slice a regular device to
> conventional zones. This patch defers the loading of zone info to
> open_ctree() to load the emulated zone size from a device extent.
> 
> Reviewed-by: Josef Bacik <josef@toxicpanda.com>
> Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com>


Patches are already in for-next. My apologies for the delay in review 
here and in the following patches how many ever I could.

Reviewed-by: Anand Jain <anand.jain@oracle.com>

Thanks.

> ---
>   fs/btrfs/disk-io.c | 13 +++++++++++++
>   fs/btrfs/volumes.c |  4 ----
>   fs/btrfs/zoned.c   | 24 ++++++++++++++++++++++++
>   fs/btrfs/zoned.h   |  7 +++++++
>   4 files changed, 44 insertions(+), 4 deletions(-)
> 
> diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
> index 5473bed6a7e8..39cbe10a81b6 100644
> --- a/fs/btrfs/disk-io.c
> +++ b/fs/btrfs/disk-io.c
> @@ -3257,6 +3257,19 @@ int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
>   	if (ret)
>   		goto fail_tree_roots;
>   
> +	/*
> +	 * Get zone type information of zoned block devices. This will also
> +	 * handle emulation of the zoned mode for btrfs if a regular device has
> +	 * the zoned incompat feature flag set.
> +	 */
> +	ret = btrfs_get_dev_zone_info_all_devices(fs_info);
> +	if (ret) {
> +		btrfs_err(fs_info,
> +			  "failed to read device zone info: %d",
> +			  ret);
> +		goto fail_block_groups;
> +	}
> +
>   	/*
>   	 * If we have a uuid root and we're not being told to rescan we need to
>   	 * check the generation here so we can set the
> diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
> index badb972919eb..bb3f341f6a22 100644
> --- a/fs/btrfs/volumes.c
> +++ b/fs/btrfs/volumes.c
> @@ -669,10 +669,6 @@ static int btrfs_open_one_device(struct btrfs_fs_devices *fs_devices,
>   	clear_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &device->dev_state);
>   	device->mode = flags;
>   
> -	ret = btrfs_get_dev_zone_info(device);
> -	if (ret != 0)
> -		goto error_free_page;
> -
>   	fs_devices->open_devices++;
>   	if (test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state) &&
>   	    device->devid != BTRFS_DEV_REPLACE_DEVID) {
> diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c
> index c38846659019..bcabdb2c97f1 100644
> --- a/fs/btrfs/zoned.c
> +++ b/fs/btrfs/zoned.c
> @@ -143,6 +143,30 @@ static int btrfs_get_dev_zones(struct btrfs_device *device, u64 pos,
>   	return 0;
>   }
>   
> +int btrfs_get_dev_zone_info_all_devices(struct btrfs_fs_info *fs_info)
> +{
> +	struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
> +	struct btrfs_device *device;
> +	int ret = 0;
> +
> +	if (!btrfs_fs_incompat(fs_info, ZONED))
> +		return 0;
> +
> +	mutex_lock(&fs_devices->device_list_mutex);
> +	list_for_each_entry(device, &fs_devices->devices, dev_list) {
> +		/* We can skip reading of zone info for missing devices */
> +		if (!device->bdev)
> +			continue;
> +
> +		ret = btrfs_get_dev_zone_info(device);
> +		if (ret)
> +			break;
> +	}
> +	mutex_unlock(&fs_devices->device_list_mutex);
> +
> +	return ret;
> +}
> +
>   int btrfs_get_dev_zone_info(struct btrfs_device *device)
>   {
>   	struct btrfs_zoned_device_info *zone_info = NULL;
> diff --git a/fs/btrfs/zoned.h b/fs/btrfs/zoned.h
> index 8abe2f83272b..5e0e7de84a82 100644
> --- a/fs/btrfs/zoned.h
> +++ b/fs/btrfs/zoned.h
> @@ -25,6 +25,7 @@ struct btrfs_zoned_device_info {
>   #ifdef CONFIG_BLK_DEV_ZONED
>   int btrfs_get_dev_zone(struct btrfs_device *device, u64 pos,
>   		       struct blk_zone *zone);
> +int btrfs_get_dev_zone_info_all_devices(struct btrfs_fs_info *fs_info);
>   int btrfs_get_dev_zone_info(struct btrfs_device *device);
>   void btrfs_destroy_dev_zone_info(struct btrfs_device *device);
>   int btrfs_check_zoned_mode(struct btrfs_fs_info *fs_info);
> @@ -42,6 +43,12 @@ static inline int btrfs_get_dev_zone(struct btrfs_device *device, u64 pos,
>   	return 0;
>   }
>   
> +static inline int btrfs_get_dev_zone_info_all_devices(
> +	struct btrfs_fs_info *fs_info)
> +{
> +	return 0;
> +}
> +
>   static inline int btrfs_get_dev_zone_info(struct btrfs_device *device)
>   {
>   	return 0;
>
diff mbox series

Patch

diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c
index 5473bed6a7e8..39cbe10a81b6 100644
--- a/fs/btrfs/disk-io.c
+++ b/fs/btrfs/disk-io.c
@@ -3257,6 +3257,19 @@  int __cold open_ctree(struct super_block *sb, struct btrfs_fs_devices *fs_device
 	if (ret)
 		goto fail_tree_roots;
 
+	/*
+	 * Get zone type information of zoned block devices. This will also
+	 * handle emulation of the zoned mode for btrfs if a regular device has
+	 * the zoned incompat feature flag set.
+	 */
+	ret = btrfs_get_dev_zone_info_all_devices(fs_info);
+	if (ret) {
+		btrfs_err(fs_info,
+			  "failed to read device zone info: %d",
+			  ret);
+		goto fail_block_groups;
+	}
+
 	/*
 	 * If we have a uuid root and we're not being told to rescan we need to
 	 * check the generation here so we can set the
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index badb972919eb..bb3f341f6a22 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -669,10 +669,6 @@  static int btrfs_open_one_device(struct btrfs_fs_devices *fs_devices,
 	clear_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &device->dev_state);
 	device->mode = flags;
 
-	ret = btrfs_get_dev_zone_info(device);
-	if (ret != 0)
-		goto error_free_page;
-
 	fs_devices->open_devices++;
 	if (test_bit(BTRFS_DEV_STATE_WRITEABLE, &device->dev_state) &&
 	    device->devid != BTRFS_DEV_REPLACE_DEVID) {
diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c
index c38846659019..bcabdb2c97f1 100644
--- a/fs/btrfs/zoned.c
+++ b/fs/btrfs/zoned.c
@@ -143,6 +143,30 @@  static int btrfs_get_dev_zones(struct btrfs_device *device, u64 pos,
 	return 0;
 }
 
+int btrfs_get_dev_zone_info_all_devices(struct btrfs_fs_info *fs_info)
+{
+	struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
+	struct btrfs_device *device;
+	int ret = 0;
+
+	if (!btrfs_fs_incompat(fs_info, ZONED))
+		return 0;
+
+	mutex_lock(&fs_devices->device_list_mutex);
+	list_for_each_entry(device, &fs_devices->devices, dev_list) {
+		/* We can skip reading of zone info for missing devices */
+		if (!device->bdev)
+			continue;
+
+		ret = btrfs_get_dev_zone_info(device);
+		if (ret)
+			break;
+	}
+	mutex_unlock(&fs_devices->device_list_mutex);
+
+	return ret;
+}
+
 int btrfs_get_dev_zone_info(struct btrfs_device *device)
 {
 	struct btrfs_zoned_device_info *zone_info = NULL;
diff --git a/fs/btrfs/zoned.h b/fs/btrfs/zoned.h
index 8abe2f83272b..5e0e7de84a82 100644
--- a/fs/btrfs/zoned.h
+++ b/fs/btrfs/zoned.h
@@ -25,6 +25,7 @@  struct btrfs_zoned_device_info {
 #ifdef CONFIG_BLK_DEV_ZONED
 int btrfs_get_dev_zone(struct btrfs_device *device, u64 pos,
 		       struct blk_zone *zone);
+int btrfs_get_dev_zone_info_all_devices(struct btrfs_fs_info *fs_info);
 int btrfs_get_dev_zone_info(struct btrfs_device *device);
 void btrfs_destroy_dev_zone_info(struct btrfs_device *device);
 int btrfs_check_zoned_mode(struct btrfs_fs_info *fs_info);
@@ -42,6 +43,12 @@  static inline int btrfs_get_dev_zone(struct btrfs_device *device, u64 pos,
 	return 0;
 }
 
+static inline int btrfs_get_dev_zone_info_all_devices(
+	struct btrfs_fs_info *fs_info)
+{
+	return 0;
+}
+
 static inline int btrfs_get_dev_zone_info(struct btrfs_device *device)
 {
 	return 0;