Commit 944d3f9f authored by Nikolay Borisov's avatar Nikolay Borisov Committed by David Sterba

btrfs: switch seed device to list api

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.
Reviewed-by: default avatarJosef Bacik <josef@toxicpanda.com>
Reviewed-by: default avatarAnand Jain <anand.jain@oracle.com>
Signed-off-by: default avatarNikolay Borisov <nborisov@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent c4989c2f
...@@ -545,33 +545,30 @@ static int csum_dirty_buffer(struct btrfs_fs_info *fs_info, struct page *page) ...@@ -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) static int check_tree_block_fsid(struct extent_buffer *eb)
{ {
struct btrfs_fs_info *fs_info = eb->fs_info; 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]; u8 fsid[BTRFS_FSID_SIZE];
int ret = 1; u8 *metadata_uuid;
read_extent_buffer(eb, fsid, offsetof(struct btrfs_header, fsid), read_extent_buffer(eb, fsid, offsetof(struct btrfs_header, fsid),
BTRFS_FSID_SIZE); 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;
/* if (!memcmp(fsid, metadata_uuid, BTRFS_FSID_SIZE))
* Checking the incompat flag is only valid for the current return 0;
* 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)) { list_for_each_entry(seed_devs, &fs_devices->seed_list, seed_list)
ret = 0; if (!memcmp(fsid, seed_devs->fsid, BTRFS_FSID_SIZE))
break; return 0;
}
fs_devices = fs_devices->seed; return 1;
}
return ret;
} }
static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio, static int btree_readpage_end_io_hook(struct btrfs_io_bio *io_bio,
......
...@@ -791,16 +791,13 @@ static int reada_start_for_fsdevs(struct btrfs_fs_devices *fs_devices) ...@@ -791,16 +791,13 @@ static int reada_start_for_fsdevs(struct btrfs_fs_devices *fs_devices)
static void __reada_start_machine(struct btrfs_fs_info *fs_info) 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; int i;
u64 enqueued = 0; u64 enqueued = 0;
again:
enqueued += reada_start_for_fsdevs(fs_devices); enqueued += reada_start_for_fsdevs(fs_devices);
if (fs_devices->seed) { list_for_each_entry(seed_devs, &fs_devices->seed_list, seed_list)
fs_devices = fs_devices->seed; enqueued += reada_start_for_fsdevs(seed_devs);
goto again;
}
if (enqueued == 0) if (enqueued == 0)
return; return;
......
...@@ -356,6 +356,7 @@ static struct btrfs_fs_devices *alloc_fs_devices(const u8 *fsid, ...@@ -356,6 +356,7 @@ static struct btrfs_fs_devices *alloc_fs_devices(const u8 *fsid,
INIT_LIST_HEAD(&fs_devs->devices); INIT_LIST_HEAD(&fs_devs->devices);
INIT_LIST_HEAD(&fs_devs->alloc_list); INIT_LIST_HEAD(&fs_devs->alloc_list);
INIT_LIST_HEAD(&fs_devs->fs_list); INIT_LIST_HEAD(&fs_devs->fs_list);
INIT_LIST_HEAD(&fs_devs->seed_list);
if (fsid) if (fsid)
memcpy(fs_devs->fsid, fsid, BTRFS_FSID_SIZE); memcpy(fs_devs->fsid, fsid, BTRFS_FSID_SIZE);
...@@ -1097,14 +1098,13 @@ static void __btrfs_free_extra_devids(struct btrfs_fs_devices *fs_devices, ...@@ -1097,14 +1098,13 @@ static void __btrfs_free_extra_devids(struct btrfs_fs_devices *fs_devices,
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_device *latest_dev = NULL;
struct btrfs_fs_devices *seed_dev;
mutex_lock(&uuid_mutex); mutex_lock(&uuid_mutex);
again:
__btrfs_free_extra_devids(fs_devices, step, &latest_dev); __btrfs_free_extra_devids(fs_devices, step, &latest_dev);
if (fs_devices->seed) {
fs_devices = fs_devices->seed; list_for_each_entry(seed_dev, &fs_devices->seed_list, seed_list)
goto again; __btrfs_free_extra_devids(seed_dev, step, &latest_dev);
}
fs_devices->latest_bdev = latest_dev->bdev; fs_devices->latest_bdev = latest_dev->bdev;
...@@ -1178,20 +1178,18 @@ static void close_fs_devices(struct btrfs_fs_devices *fs_devices) ...@@ -1178,20 +1178,18 @@ static void close_fs_devices(struct btrfs_fs_devices *fs_devices)
void btrfs_close_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); mutex_lock(&uuid_mutex);
close_fs_devices(fs_devices); close_fs_devices(fs_devices);
if (!fs_devices->opened) { if (!fs_devices->opened)
seed_devices = fs_devices->seed; list_splice_init(&fs_devices->seed_list, &list);
fs_devices->seed = NULL;
}
mutex_unlock(&uuid_mutex); mutex_unlock(&uuid_mutex);
while (seed_devices) { list_for_each_entry_safe(fs_devices, tmp, &list, seed_list) {
fs_devices = seed_devices;
seed_devices = fs_devices->seed;
close_fs_devices(fs_devices); close_fs_devices(fs_devices);
list_del(&fs_devices->seed_list);
free_fs_devices(fs_devices); free_fs_devices(fs_devices);
} }
} }
...@@ -2169,14 +2167,7 @@ int btrfs_rm_device(struct btrfs_fs_info *fs_info, const char *device_path, ...@@ -2169,14 +2167,7 @@ int btrfs_rm_device(struct btrfs_fs_info *fs_info, const char *device_path,
btrfs_free_device(device); btrfs_free_device(device);
if (cur_devices->open_devices == 0) { if (cur_devices->open_devices == 0) {
while (fs_devices) { list_del_init(&cur_devices->seed_list);
if (fs_devices->seed == cur_devices) {
fs_devices->seed = cur_devices->seed;
break;
}
fs_devices = fs_devices->seed;
}
cur_devices->seed = NULL;
close_fs_devices(cur_devices); close_fs_devices(cur_devices);
free_fs_devices(cur_devices); free_fs_devices(cur_devices);
} }
...@@ -2236,8 +2227,6 @@ void btrfs_rm_dev_replace_free_srcdev(struct btrfs_device *srcdev) ...@@ -2236,8 +2227,6 @@ void btrfs_rm_dev_replace_free_srcdev(struct btrfs_device *srcdev)
/* if this is no devs we rather delete the fs_devices */ /* if this is no devs we rather delete the fs_devices */
if (!fs_devices->num_devices) { if (!fs_devices->num_devices) {
struct btrfs_fs_devices *tmp_fs_devices;
/* /*
* On a mounted FS, num_devices can't be zero unless it's a * On a mounted FS, num_devices can't be zero unless it's a
* seed. In case of a seed device being replaced, the replace * seed. In case of a seed device being replaced, the replace
...@@ -2246,15 +2235,7 @@ void btrfs_rm_dev_replace_free_srcdev(struct btrfs_device *srcdev) ...@@ -2246,15 +2235,7 @@ void btrfs_rm_dev_replace_free_srcdev(struct btrfs_device *srcdev)
*/ */
ASSERT(fs_devices->seeding); ASSERT(fs_devices->seeding);
tmp_fs_devices = fs_info->fs_devices; list_del_init(&fs_devices->seed_list);
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;
close_fs_devices(fs_devices); close_fs_devices(fs_devices);
free_fs_devices(fs_devices); free_fs_devices(fs_devices);
} }
...@@ -2409,7 +2390,7 @@ static int btrfs_prepare_sprout(struct btrfs_fs_info *fs_info) ...@@ -2409,7 +2390,7 @@ static int btrfs_prepare_sprout(struct btrfs_fs_info *fs_info)
fs_devices->open_devices = 0; fs_devices->open_devices = 0;
fs_devices->missing_devices = 0; fs_devices->missing_devices = 0;
fs_devices->rotating = false; fs_devices->rotating = false;
fs_devices->seed = seed_devices; list_add(&seed_devices->seed_list, &fs_devices->seed_list);
generate_random_uuid(fs_devices->fsid); generate_random_uuid(fs_devices->fsid);
memcpy(fs_devices->metadata_uuid, fs_devices->fsid, BTRFS_FSID_SIZE); memcpy(fs_devices->metadata_uuid, fs_devices->fsid, BTRFS_FSID_SIZE);
...@@ -6465,11 +6446,21 @@ struct btrfs_device *btrfs_find_device(struct btrfs_fs_devices *fs_devices, ...@@ -6465,11 +6446,21 @@ struct btrfs_device *btrfs_find_device(struct btrfs_fs_devices *fs_devices,
bool seed) bool seed)
{ {
struct btrfs_device *device; struct btrfs_device *device;
struct btrfs_fs_devices *seed_devs;
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;
}
}
while (fs_devices) { list_for_each_entry(seed_devs, &fs_devices->seed_list, seed_list) {
if (!fsid || if (!fsid ||
!memcmp(fs_devices->metadata_uuid, fsid, BTRFS_FSID_SIZE)) { !memcmp(seed_devs->metadata_uuid, fsid, BTRFS_FSID_SIZE)) {
list_for_each_entry(device, &fs_devices->devices, list_for_each_entry(device, &seed_devs->devices,
dev_list) { dev_list) {
if (device->devid == devid && if (device->devid == devid &&
(!uuid || memcmp(device->uuid, uuid, (!uuid || memcmp(device->uuid, uuid,
...@@ -6477,11 +6468,8 @@ struct btrfs_device *btrfs_find_device(struct btrfs_fs_devices *fs_devices, ...@@ -6477,11 +6468,8 @@ struct btrfs_device *btrfs_find_device(struct btrfs_fs_devices *fs_devices,
return device; return device;
} }
} }
if (seed)
fs_devices = fs_devices->seed;
else
return NULL;
} }
return NULL; return NULL;
} }
...@@ -6732,13 +6720,10 @@ static struct btrfs_fs_devices *open_seed_devices(struct btrfs_fs_info *fs_info, ...@@ -6732,13 +6720,10 @@ static struct btrfs_fs_devices *open_seed_devices(struct btrfs_fs_info *fs_info,
lockdep_assert_held(&uuid_mutex); lockdep_assert_held(&uuid_mutex);
ASSERT(fsid); ASSERT(fsid);
fs_devices = fs_info->fs_devices->seed; list_for_each_entry(fs_devices, &fs_info->fs_devices->seed_list, seed_list)
while (fs_devices) {
if (!memcmp(fs_devices->fsid, fsid, BTRFS_FSID_SIZE)) if (!memcmp(fs_devices->fsid, fsid, BTRFS_FSID_SIZE))
return fs_devices; return fs_devices;
fs_devices = fs_devices->seed;
}
fs_devices = find_fsid(fsid, NULL); fs_devices = find_fsid(fsid, NULL);
if (!fs_devices) { if (!fs_devices) {
...@@ -6772,8 +6757,7 @@ static struct btrfs_fs_devices *open_seed_devices(struct btrfs_fs_info *fs_info, ...@@ -6772,8 +6757,7 @@ static struct btrfs_fs_devices *open_seed_devices(struct btrfs_fs_info *fs_info,
goto out; goto out;
} }
fs_devices->seed = fs_info->fs_devices->seed; list_add(&fs_devices->seed_list, &fs_info->fs_devices->seed_list);
fs_info->fs_devices->seed = fs_devices;
out: out:
return fs_devices; return fs_devices;
} }
...@@ -7193,17 +7177,23 @@ int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info) ...@@ -7193,17 +7177,23 @@ int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info)
void btrfs_init_devices_late(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; struct btrfs_device *device;
while (fs_devices) { fs_devices->fs_info = fs_info;
mutex_lock(&fs_devices->device_list_mutex);
list_for_each_entry(device, &fs_devices->devices, dev_list) 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; 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; seed_devs->fs_info = fs_info;
fs_devices = fs_devices->seed;
} }
} }
...@@ -7581,8 +7571,11 @@ static int verify_one_dev_extent(struct btrfs_fs_info *fs_info, ...@@ -7581,8 +7571,11 @@ static int verify_one_dev_extent(struct btrfs_fs_info *fs_info,
/* It's possible this device is a dummy for seed device */ /* It's possible this device is a dummy for seed device */
if (dev->disk_total_bytes == 0) { if (dev->disk_total_bytes == 0) {
dev = btrfs_find_device(fs_info->fs_devices->seed, devid, NULL, struct btrfs_fs_devices *devs;
NULL, false);
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) { if (!dev) {
btrfs_err(fs_info, "failed to find seed devid %llu", btrfs_err(fs_info, "failed to find seed devid %llu",
devid); devid);
......
...@@ -246,7 +246,7 @@ struct btrfs_fs_devices { ...@@ -246,7 +246,7 @@ struct btrfs_fs_devices {
*/ */
struct list_head alloc_list; struct list_head alloc_list;
struct btrfs_fs_devices *seed; struct list_head seed_list;
bool seeding; bool seeding;
int opened; int opened;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment