Message ID | 20200715104850.19071-6-nborisov@suse.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | Convert seed devices to proper list API | expand |
Hi Nikolay, Thank you for the patch! Yet something to improve: [auto build test ERROR on kdave/for-next] [also build test ERROR on next-20200715] [cannot apply to v5.8-rc5] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Nikolay-Borisov/Convert-seed-devices-to-proper-list-API/20200715-185102 base: https://git.kernel.org/pub/scm/linux/kernel/git/kdave/linux.git for-next config: x86_64-rhel-7.6-kselftests (attached as .config) compiler: gcc-9 (Debian 9.3.0-14) 9.3.0 reproduce (this is a W=1 build): # save the attached .config to linux build tree make W=1 ARCH=x86_64 If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All error/warnings (new ones prefixed by >>): In file included from fs/btrfs/volumes.c:17: fs/btrfs/ctree.h:2271:8: warning: type qualifiers ignored on function return type [-Wignored-qualifiers] 2271 | size_t __const btrfs_get_num_csums(void); | ^~~~~~~ In file included from fs/btrfs/volumes.c:28: fs/btrfs/sysfs.h:16:1: warning: type qualifiers ignored on function return type [-Wignored-qualifiers] 16 | const char * const btrfs_feature_set_name(enum btrfs_feature_set set); | ^~~~~ fs/btrfs/volumes.c:1030:6: warning: no previous prototype for '__btrfs_free_extra_devids' [-Wmissing-prototypes] 1030 | void __btrfs_free_extra_devids(struct btrfs_fs_devices *fs_devices, int step, | ^~~~~~~~~~~~~~~~~~~~~~~~~ fs/btrfs/volumes.c: In function 'btrfs_rm_dev_replace_free_srcdev': >> fs/btrfs/volumes.c:2219:28: warning: variable 'tmp_fs_devices' set but not used [-Wunused-but-set-variable] 2219 | struct btrfs_fs_devices *tmp_fs_devices; | ^~~~~~~~~~~~~~ -- In file included from fs/btrfs/delayed-inode.h:17, from fs/btrfs/super.c:30: fs/btrfs/ctree.h:2271:8: warning: type qualifiers ignored on function return type [-Wignored-qualifiers] 2271 | size_t __const btrfs_get_num_csums(void); | ^~~~~~~ In file included from fs/btrfs/super.c:46: fs/btrfs/sysfs.h:16:1: warning: type qualifiers ignored on function return type [-Wignored-qualifiers] 16 | const char * const btrfs_feature_set_name(enum btrfs_feature_set set); | ^~~~~ fs/btrfs/super.c: In function 'btrfs_show_devname': >> fs/btrfs/super.c:2404:28: error: 'struct btrfs_fs_devices' has no member named 'seed' 2404 | cur_devices = cur_devices->seed; | ^~ vim +2404 fs/btrfs/super.c 9e7cc91a6d18a4 Wang Xiaoguang 2016-08-01 2377 9c5085c147989d Josef Bacik 2012-06-05 2378 static int btrfs_show_devname(struct seq_file *m, struct dentry *root) 9c5085c147989d Josef Bacik 2012-06-05 2379 { 9c5085c147989d Josef Bacik 2012-06-05 2380 struct btrfs_fs_info *fs_info = btrfs_sb(root->d_sb); 9c5085c147989d Josef Bacik 2012-06-05 2381 struct btrfs_fs_devices *cur_devices; 9c5085c147989d Josef Bacik 2012-06-05 2382 struct btrfs_device *dev, *first_dev = NULL; 9c5085c147989d Josef Bacik 2012-06-05 2383 struct list_head *head; 9c5085c147989d Josef Bacik 2012-06-05 2384 88c14590cdd6f3 David Sterba 2018-03-16 2385 /* 88c14590cdd6f3 David Sterba 2018-03-16 2386 * Lightweight locking of the devices. We should not need 88c14590cdd6f3 David Sterba 2018-03-16 2387 * device_list_mutex here as we only read the device data and the list 88c14590cdd6f3 David Sterba 2018-03-16 2388 * is protected by RCU. Even if a device is deleted during the list 88c14590cdd6f3 David Sterba 2018-03-16 2389 * traversals, we'll get valid data, the freeing callback will wait at 52042d8e82ff50 Andrea Gelmini 2018-11-28 2390 * least until the rcu_read_unlock. 88c14590cdd6f3 David Sterba 2018-03-16 2391 */ 88c14590cdd6f3 David Sterba 2018-03-16 2392 rcu_read_lock(); 9c5085c147989d Josef Bacik 2012-06-05 2393 cur_devices = fs_info->fs_devices; 9c5085c147989d Josef Bacik 2012-06-05 2394 while (cur_devices) { 9c5085c147989d Josef Bacik 2012-06-05 2395 head = &cur_devices->devices; 88c14590cdd6f3 David Sterba 2018-03-16 2396 list_for_each_entry_rcu(dev, head, dev_list) { e6e674bd4d54fe Anand Jain 2017-12-04 2397 if (test_bit(BTRFS_DEV_STATE_MISSING, &dev->dev_state)) aa9ddcd4b55571 Josef Bacik 2012-08-02 2398 continue; 0aeb8a6e67cdde Anand Jain 2014-06-30 2399 if (!dev->name) 0aeb8a6e67cdde Anand Jain 2014-06-30 2400 continue; 9c5085c147989d Josef Bacik 2012-06-05 2401 if (!first_dev || dev->devid < first_dev->devid) 9c5085c147989d Josef Bacik 2012-06-05 2402 first_dev = dev; 9c5085c147989d Josef Bacik 2012-06-05 2403 } 9c5085c147989d Josef Bacik 2012-06-05 @2404 cur_devices = cur_devices->seed; 9c5085c147989d Josef Bacik 2012-06-05 2405 } 9c5085c147989d Josef Bacik 2012-06-05 2406 672d599041c862 Misono Tomohiro 2018-08-02 2407 if (first_dev) 672d599041c862 Misono Tomohiro 2018-08-02 2408 seq_escape(m, rcu_str_deref(first_dev->name), " \t\n\\"); 672d599041c862 Misono Tomohiro 2018-08-02 2409 else 9c5085c147989d Josef Bacik 2012-06-05 2410 WARN_ON(1); 88c14590cdd6f3 David Sterba 2018-03-16 2411 rcu_read_unlock(); 9c5085c147989d Josef Bacik 2012-06-05 2412 return 0; 9c5085c147989d Josef Bacik 2012-06-05 2413 } 9c5085c147989d Josef Bacik 2012-06-05 2414 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
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; >
The seed of the current sprout should rather be at the head instead of at the bottom. > @@ -2397,7 +2381,7 @@ static int btrfs_prepare_sprout(struct btrfs_fs_info *fs_info) > fs_devices->open_devices = 0; > fs_devices->missing_devices = 0; > fs_devices->rotating = false; > - fs_devices->seed = seed_devices; > + list_add_tail(&seed_devices->seed_list, &fs_devices->seed_list); It should be list_add_head. > > generate_random_uuid(fs_devices->fsid); > memcpy(fs_devices->metadata_uuid, fs_devices->fsid, BTRFS_FSID_SIZE); > @@ -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)); > + list_add_tail(&fs_devices->seed_list, &fs_info->fs_devices->seed_list); It should be list_add_head. > out: > return fs_devices; > } Thanks, Anand
On 2.09.20 г. 18:58 ч., Anand Jain wrote: > > > The seed of the current sprout should rather be at the head instead of > at the bottom. > > >> @@ -2397,7 +2381,7 @@ static int btrfs_prepare_sprout(struct >> btrfs_fs_info *fs_info) >> fs_devices->open_devices = 0; >> fs_devices->missing_devices = 0; >> fs_devices->rotating = false; >> - fs_devices->seed = seed_devices; >> + list_add_tail(&seed_devices->seed_list, &fs_devices->seed_list); > > It should be list_add_head. Generally yes, but in this case I don't think it makes any functional differences so even adding at the tail is fine. > >> generate_random_uuid(fs_devices->fsid); >> memcpy(fs_devices->metadata_uuid, fs_devices->fsid, >> BTRFS_FSID_SIZE); > > > > >> @@ -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)); >> + list_add_tail(&fs_devices->seed_list, >> &fs_info->fs_devices->seed_list); > > It should be list_add_head. > >> out: >> return fs_devices; >> } > > > Thanks, Anand >
On 3/9/20 5:03 pm, Nikolay Borisov wrote: > > > On 2.09.20 г. 18:58 ч., Anand Jain wrote: >> >> >> The seed of the current sprout should rather be at the head instead of >> at the bottom. >> >> >>> @@ -2397,7 +2381,7 @@ static int btrfs_prepare_sprout(struct >>> btrfs_fs_info *fs_info) >>> fs_devices->open_devices = 0; >>> fs_devices->missing_devices = 0; >>> fs_devices->rotating = false; >>> - fs_devices->seed = seed_devices; >>> + list_add_tail(&seed_devices->seed_list, &fs_devices->seed_list); >> >> It should be list_add_head. > > Generally yes, but in this case I don't think it makes any functional > differences so even adding at the tail is fine. > Hm No. Adding to the head matches to the order of dependency. As it was in the while loop. Thanks, Anand >> >>> generate_random_uuid(fs_devices->fsid); >>> memcpy(fs_devices->metadata_uuid, fs_devices->fsid, >>> BTRFS_FSID_SIZE); >> >> >> >> >>> @@ -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)); >>> + list_add_tail(&fs_devices->seed_list, >>> &fs_info->fs_devices->seed_list); >> >> It should be list_add_head. >> >>> out: >>> return fs_devices; >>> } >> >> >> Thanks, Anand >>
On Thu, Sep 03, 2020 at 05:33:26PM +0800, Anand Jain wrote: > > > On 3/9/20 5:03 pm, Nikolay Borisov wrote: > > > > > > On 2.09.20 г. 18:58 ч., Anand Jain wrote: > >> > >> > >> The seed of the current sprout should rather be at the head instead of > >> at the bottom. > >> > >> > >>> @@ -2397,7 +2381,7 @@ static int btrfs_prepare_sprout(struct > >>> btrfs_fs_info *fs_info) > >>> fs_devices->open_devices = 0; > >>> fs_devices->missing_devices = 0; > >>> fs_devices->rotating = false; > >>> - fs_devices->seed = seed_devices; > >>> + list_add_tail(&seed_devices->seed_list, &fs_devices->seed_list); > >> > >> It should be list_add_head. > > > > Generally yes, but in this case I don't think it makes any functional > > differences so even adding at the tail is fine. > > > > Hm No. Adding to the head matches to the order of dependency. As it > was in the while loop. Following the same order sounds like a better idea to me. If there's really no differece and we want to add the entry to the tail, then it would be another patch with proper reasoning. I'll update it to do list_head.
diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 2fb0b43bc1c5..8767d47f6e29 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -545,33 +545,30 @@ static int csum_dirty_buffer(struct btrfs_fs_info *fs_info, struct page *page) static int check_tree_block_fsid(struct extent_buffer *eb) { struct btrfs_fs_info *fs_info = eb->fs_info; - struct btrfs_fs_devices *fs_devices = fs_info->fs_devices; + struct btrfs_fs_devices *fs_devices = fs_info->fs_devices, *seed_devs; u8 fsid[BTRFS_FSID_SIZE]; - int ret = 1; + u8 *metadata_uuid; read_extent_buffer(eb, fsid, offsetof(struct btrfs_header, fsid), BTRFS_FSID_SIZE); - while (fs_devices) { - u8 *metadata_uuid; + /* + * Checking the incompat flag is only valid for the current + * fs. For seed devices it's forbidden to have their uuid + * changed so reading ->fsid in this case is fine + */ + if (btrfs_fs_incompat(fs_info, METADATA_UUID)) + metadata_uuid = fs_devices->metadata_uuid; + else + metadata_uuid = fs_devices->fsid; - /* - * Checking the incompat flag is only valid for the current - * fs. For seed devices it's forbidden to have their uuid - * changed so reading ->fsid in this case is fine - */ - if (fs_devices == fs_info->fs_devices && - btrfs_fs_incompat(fs_info, METADATA_UUID)) - metadata_uuid = fs_devices->metadata_uuid; - else - metadata_uuid = fs_devices->fsid; + if (!memcmp(fsid, metadata_uuid, BTRFS_FSID_SIZE)) + return 0; - if (!memcmp(fsid, metadata_uuid, BTRFS_FSID_SIZE)) { - ret = 0; - break; - } - fs_devices = fs_devices->seed; - } - return ret; + list_for_each_entry(seed_devs, &fs_devices->seed_list, seed_list) + if (!memcmp(fsid, seed_devs->fsid, BTRFS_FSID_SIZE)) + return 0; + + return 1; } static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio, diff --git a/fs/btrfs/reada.c b/fs/btrfs/reada.c index aa9d24ed56d7..ac5b07ded0fe 100644 --- a/fs/btrfs/reada.c +++ b/fs/btrfs/reada.c @@ -792,16 +792,13 @@ static int __reada_start_for_fsdevs(struct btrfs_fs_devices *fs_devices) static void __reada_start_machine(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; int i; u64 enqueued = 0; -again: enqueued += __reada_start_for_fsdevs(fs_devices); - if (fs_devices->seed) { - fs_devices = fs_devices->seed; - goto again; - } + list_for_each_entry(seed_devs, &fs_devices->seed_list, seed_list) + enqueued += __reada_start_for_fsdevs(seed_devs); if (enqueued == 0) return; diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index a0cdd027e99c..7fce7a220a76 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -350,6 +350,7 @@ static struct btrfs_fs_devices *alloc_fs_devices(const u8 *fsid, INIT_LIST_HEAD(&fs_devs->devices); INIT_LIST_HEAD(&fs_devs->alloc_list); INIT_LIST_HEAD(&fs_devs->fs_list); + INIT_LIST_HEAD(&fs_devs->seed_list); if (fsid) memcpy(fs_devs->fsid, fsid, BTRFS_FSID_SIZE); @@ -1087,14 +1088,13 @@ void __btrfs_free_extra_devids(struct btrfs_fs_devices *fs_devices, int step, void btrfs_free_extra_devids(struct btrfs_fs_devices *fs_devices, int step) { struct btrfs_device *latest_dev = NULL; + struct btrfs_fs_devices *seed_dev; mutex_lock(&uuid_mutex); -again: __btrfs_free_extra_devids(fs_devices, step, &latest_dev); - if (fs_devices->seed) { - fs_devices = fs_devices->seed; - goto again; - } + + list_for_each_entry(seed_dev, &fs_devices->seed_list, seed_list) + __btrfs_free_extra_devids(seed_dev, step, &latest_dev); fs_devices->latest_bdev = latest_dev->bdev; @@ -1168,20 +1168,18 @@ static void close_fs_devices(struct btrfs_fs_devices *fs_devices) void btrfs_close_devices(struct btrfs_fs_devices *fs_devices) { - struct btrfs_fs_devices *seed_devices = NULL; + LIST_HEAD(list); + struct btrfs_fs_devices *tmp; mutex_lock(&uuid_mutex); close_fs_devices(fs_devices); - if (!fs_devices->opened) { - seed_devices = fs_devices->seed; - fs_devices->seed = NULL; - } + if (!fs_devices->opened) + list_splice_init(&fs_devices->seed_list, &list); mutex_unlock(&uuid_mutex); - while (seed_devices) { - fs_devices = seed_devices; - seed_devices = fs_devices->seed; + list_for_each_entry_safe(fs_devices, tmp, &list, seed_list) { close_fs_devices(fs_devices); + list_del(&fs_devices->seed_list); free_fs_devices(fs_devices); } } @@ -2154,14 +2152,7 @@ int btrfs_rm_device(struct btrfs_fs_info *fs_info, const char *device_path, btrfs_free_device(device); if (cur_devices->open_devices == 0) { - while (fs_devices) { - if (fs_devices->seed == cur_devices) { - fs_devices->seed = cur_devices->seed; - break; - } - fs_devices = fs_devices->seed; - } - cur_devices->seed = NULL; + list_del_init(&cur_devices->seed_list); close_fs_devices(cur_devices); free_fs_devices(cur_devices); } @@ -2236,14 +2227,7 @@ void btrfs_rm_dev_replace_free_srcdev(struct btrfs_device *srcdev) ASSERT(fs_devices->seeding); tmp_fs_devices = fs_info->fs_devices; - while (tmp_fs_devices) { - if (tmp_fs_devices->seed == fs_devices) { - tmp_fs_devices->seed = fs_devices->seed; - break; - } - tmp_fs_devices = tmp_fs_devices->seed; - } - fs_devices->seed = NULL; + list_del_init(&fs_devices->seed_list); close_fs_devices(fs_devices); free_fs_devices(fs_devices); } @@ -2397,7 +2381,7 @@ static int btrfs_prepare_sprout(struct btrfs_fs_info *fs_info) fs_devices->open_devices = 0; fs_devices->missing_devices = 0; fs_devices->rotating = false; - fs_devices->seed = seed_devices; + list_add_tail(&seed_devices->seed_list, &fs_devices->seed_list); generate_random_uuid(fs_devices->fsid); memcpy(fs_devices->metadata_uuid, fs_devices->fsid, BTRFS_FSID_SIZE); @@ -6430,11 +6414,23 @@ struct btrfs_device *btrfs_find_device(struct btrfs_fs_devices *fs_devices, bool seed) { struct btrfs_device *device; + struct btrfs_fs_devices *seed_devs; - while (fs_devices) { + if (!fsid || + !memcmp(fs_devices->metadata_uuid, fsid, BTRFS_FSID_SIZE)) { + list_for_each_entry(device, &fs_devices->devices, + dev_list) { + if (device->devid == devid && + (!uuid || memcmp(device->uuid, uuid, + BTRFS_UUID_SIZE) == 0)) + return device; + } + } + + list_for_each_entry(seed_devs, &fs_devices->seed_list, seed_list) { if (!fsid || - !memcmp(fs_devices->metadata_uuid, fsid, BTRFS_FSID_SIZE)) { - list_for_each_entry(device, &fs_devices->devices, + !memcmp(seed_devs->metadata_uuid, fsid, BTRFS_FSID_SIZE)) { + list_for_each_entry(device, &seed_devs->devices, dev_list) { if (device->devid == devid && (!uuid || memcmp(device->uuid, uuid, @@ -6442,11 +6438,8 @@ struct btrfs_device *btrfs_find_device(struct btrfs_fs_devices *fs_devices, return device; } } - if (seed) - fs_devices = fs_devices->seed; - else - return NULL; } + return NULL; } @@ -6688,13 +6681,10 @@ static struct btrfs_fs_devices *open_seed_devices(struct btrfs_fs_info *fs_info, lockdep_assert_held(&uuid_mutex); ASSERT(fsid); - fs_devices = fs_info->fs_devices->seed; - while (fs_devices) { + list_for_each_entry(fs_devices, &fs_info->fs_devices->seed_list, seed_list) if (!memcmp(fs_devices->fsid, fsid, BTRFS_FSID_SIZE)) return fs_devices; - fs_devices = fs_devices->seed; - } fs_devices = find_fsid(fsid, NULL); if (!fs_devices) { @@ -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)); + 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;
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> --- fs/btrfs/disk-io.c | 39 ++++++++--------- fs/btrfs/reada.c | 9 ++-- fs/btrfs/volumes.c | 102 ++++++++++++++++++++++----------------------- fs/btrfs/volumes.h | 2 +- 4 files changed, 72 insertions(+), 80 deletions(-)