Re: [PATCH 5/5] btrfs: Switch seed device to list api

Nikolay Borisov
2020-07-24T07:37:01Z

On 15.07.20 г. 13:48 ч., Nikolay Borisov wrote:
> While this patch touches a bunch of files the conversion is
> straighforward. Instead of using the implicit linked list anchored at
> btrfs_fs_devices::seed the code is switched to using
> list_for_each_entry. Previous patches in the series already factored out
> code that processed both main and seed devices so in those cases
> the factored out functions are called on the main fs_devices and then
> on every seed dev inside list_for_each_entry.
>
> Using list api also allows to simplify deletion from the seed dev list
> performed in btrfs_rm_device and btrfs_rm_dev_replace_free_srcdev by
> substituting a while() loop with a simple list_del_init.
>
> Signed-off-by: Nikolay Borisov <nborisov@suse.com>

<snip>

> @@ -6728,8 +6718,8 @@ static struct btrfs_fs_devices *open_seed_devices(struct btrfs_fs_info *fs_info,
> goto out;
> }
>
> - fs_devices->seed = fs_info->fs_devices->seed;
> - fs_info->fs_devices->seed = fs_devices;
> + ASSERT(list_empty(&fs_devices->seed_list));

That assert is useless, since fs_devices at this point are a clone from
clone_fs_devices hence its seed_list cannot be non-empty. Consider this
when removing merging it.

> + list_add_tail(&fs_devices->seed_list, &fs_info->fs_devices->seed_list);
> out:
> return fs_devices;
> }
> @@ -7141,17 +7131,23 @@ int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info)
>
> void btrfs_init_devices_late(struct btrfs_fs_info *fs_info)
> {
> - struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
> + struct btrfs_fs_devices *fs_devices = fs_info->fs_devices, *seed_devs;
> struct btrfs_device *device;
>
> - while (fs_devices) {
> - mutex_lock(&fs_devices->device_list_mutex);
> - list_for_each_entry(device, &fs_devices->devices, dev_list)
> + fs_devices->fs_info = fs_info;
> +
> + mutex_lock(&fs_devices->device_list_mutex);
> + list_for_each_entry(device, &fs_devices->devices, dev_list)
> + device->fs_info = fs_info;
> + mutex_unlock(&fs_devices->device_list_mutex);
> +
> + list_for_each_entry(seed_devs, &fs_devices->seed_list, seed_list) {
> + mutex_lock(&seed_devs->device_list_mutex);
> + list_for_each_entry(device, &seed_devs->devices, dev_list)
> device->fs_info = fs_info;
> - mutex_unlock(&fs_devices->device_list_mutex);
> + mutex_unlock(&seed_devs->device_list_mutex);
>
> - fs_devices->fs_info = fs_info;
> - fs_devices = fs_devices->seed;
> + seed_devs->fs_info = fs_info;
> }
> }
>
> @@ -7527,8 +7523,10 @@ static int verify_one_dev_extent(struct btrfs_fs_info *fs_info,
>
> /* It's possible this device is a dummy for seed device */
> if (dev->disk_total_bytes == 0) {
> - dev = btrfs_find_device(fs_info->fs_devices->seed, devid, NULL,
> - NULL, false);
> + struct btrfs_fs_devices *devs;
> + devs = list_first_entry(&fs_info->fs_devices->seed_list,
> + struct btrfs_fs_devices, seed_list);
> + dev = btrfs_find_device(devs, devid, NULL, NULL, false);
> if (!dev) {
> btrfs_err(fs_info, "failed to find seed devid %llu",
> devid);
> diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
> index fc283fdbcece..709f4aacbd3f 100644
> --- a/fs/btrfs/volumes.h
> +++ b/fs/btrfs/volumes.h
> @@ -246,7 +246,7 @@ struct btrfs_fs_devices {
> */
> struct list_head alloc_list;
>
> - struct btrfs_fs_devices *seed;
> + struct list_head seed_list;
> bool seeding;
>
> int opened;
>