btrfs: zoned: defer loading zone info after opening trees
This is a preparation patch to implement zone emulation on a regular device. To emulate a zoned filesystem on a regular (non-zoned) device, we need to decide an emulated zone size. Instead of making it a 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 loading the file system trees so that we don't know the size of a device extent at this point. Thus we can't slice a regular device to conventional zones. This patch introduces btrfs_get_dev_zone_info_all_devices to load the zone info for all the devices. And, it places this function in open_ctree() after loading the trees. Reviewed-by: Anand Jain <anand.jain@oracle.com> Reviewed-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: Naohiro Aota <naohiro.aota@wdc.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
c3b0e880bb
commit
7365104236
|
@ -3333,6 +3333,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 a zoned filesystem 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,
|
||||
"zoned: 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
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -143,6 +143,31 @@ 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;
|
||||
|
||||
/* fs_info->zone_size might not set yet. Use the incomapt flag here. */
|
||||
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;
|
||||
|
|
|
@ -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,11 @@ 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;
|
||||
|
|
Loading…
Reference in New Issue