Commit 959b1c04 authored by Nikolay Borisov's avatar Nikolay Borisov Committed by David Sterba

btrfs: close devices without offloading to a temporary list

Since commit 88c14590 ("btrfs: use RCU in btrfs_show_devname for
device list traversal") btrfs_show_devname no longer takes
device_list_mutex. As such the deadlock that 0ccd0528 ("btrfs: fix a
possible umount deadlock") aimed to fix no longer exists, we can free
the devices immediatelly and remove the code that does the pending work.
Signed-off-by: default avatarNikolay Borisov <nborisov@suse.com>
Reviewed-by: default avatarAnand Jain <anand.jain@oracle.com>
[ update changelog ]
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent 621567a2
...@@ -1001,7 +1001,7 @@ static void btrfs_close_bdev(struct btrfs_device *device) ...@@ -1001,7 +1001,7 @@ static void btrfs_close_bdev(struct btrfs_device *device)
blkdev_put(device->bdev, device->mode); blkdev_put(device->bdev, device->mode);
} }
static void btrfs_prepare_close_one_device(struct btrfs_device *device) static void btrfs_close_one_device(struct btrfs_device *device)
{ {
struct btrfs_fs_devices *fs_devices = device->fs_devices; struct btrfs_fs_devices *fs_devices = device->fs_devices;
struct btrfs_device *new_device; struct btrfs_device *new_device;
...@@ -1019,6 +1019,8 @@ static void btrfs_prepare_close_one_device(struct btrfs_device *device) ...@@ -1019,6 +1019,8 @@ static void btrfs_prepare_close_one_device(struct btrfs_device *device)
if (test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state)) if (test_bit(BTRFS_DEV_STATE_MISSING, &device->dev_state))
fs_devices->missing_devices--; fs_devices->missing_devices--;
btrfs_close_bdev(device);
new_device = btrfs_alloc_device(NULL, &device->devid, new_device = btrfs_alloc_device(NULL, &device->devid,
device->uuid); device->uuid);
BUG_ON(IS_ERR(new_device)); /* -ENOMEM */ BUG_ON(IS_ERR(new_device)); /* -ENOMEM */
...@@ -1032,39 +1034,23 @@ static void btrfs_prepare_close_one_device(struct btrfs_device *device) ...@@ -1032,39 +1034,23 @@ static void btrfs_prepare_close_one_device(struct btrfs_device *device)
list_replace_rcu(&device->dev_list, &new_device->dev_list); list_replace_rcu(&device->dev_list, &new_device->dev_list);
new_device->fs_devices = device->fs_devices; new_device->fs_devices = device->fs_devices;
call_rcu(&device->rcu, free_device_rcu);
} }
static int close_fs_devices(struct btrfs_fs_devices *fs_devices) static int close_fs_devices(struct btrfs_fs_devices *fs_devices)
{ {
struct btrfs_device *device, *tmp; struct btrfs_device *device, *tmp;
struct list_head pending_put;
INIT_LIST_HEAD(&pending_put);
if (--fs_devices->opened > 0) if (--fs_devices->opened > 0)
return 0; return 0;
mutex_lock(&fs_devices->device_list_mutex); mutex_lock(&fs_devices->device_list_mutex);
list_for_each_entry_safe(device, tmp, &fs_devices->devices, dev_list) { list_for_each_entry_safe(device, tmp, &fs_devices->devices, dev_list) {
btrfs_prepare_close_one_device(device); btrfs_close_one_device(device);
list_add(&device->dev_list, &pending_put);
} }
mutex_unlock(&fs_devices->device_list_mutex); mutex_unlock(&fs_devices->device_list_mutex);
/*
* btrfs_show_devname() is using the device_list_mutex,
* sometimes call to blkdev_put() leads vfs calling
* into this func. So do put outside of device_list_mutex,
* as of now.
*/
while (!list_empty(&pending_put)) {
device = list_first_entry(&pending_put,
struct btrfs_device, dev_list);
list_del(&device->dev_list);
btrfs_close_bdev(device);
call_rcu(&device->rcu, free_device_rcu);
}
WARN_ON(fs_devices->open_devices); WARN_ON(fs_devices->open_devices);
WARN_ON(fs_devices->rw_devices); WARN_ON(fs_devices->rw_devices);
fs_devices->opened = 0; fs_devices->opened = 0;
......
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