diff options
author | Anand Jain <anand.jain@oracle.com> | 2018-05-29 12:23:20 +0300 |
---|---|---|
committer | David Sterba <dsterba@suse.com> | 2018-08-06 14:12:47 +0300 |
commit | 7bcb8164ad9435068d9bc3b83b8a002c64d63ff6 (patch) | |
tree | 3f29cdf256f0698815243a8c5c653f3c37a542b4 /fs/btrfs | |
parent | fa6d2ae540a200a17bb7ee769f9df22d411c9404 (diff) | |
download | linux-7bcb8164ad9435068d9bc3b83b8a002c64d63ff6.tar.xz |
btrfs: use device_list_mutex when removing stale devices
btrfs_free_stale_devices() finds a stale (not opened) device matching
path in the fs_uuid list. We are already under uuid_mutex so when we
check for each fs_devices, hold the device_list_mutex too.
Signed-off-by: Anand Jain <anand.jain@oracle.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/btrfs')
-rw-r--r-- | fs/btrfs/volumes.c | 25 |
1 files changed, 15 insertions, 10 deletions
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index f4ce081bbe46..6a8f1e2c116f 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -637,8 +637,11 @@ static void btrfs_free_stale_devices(const char *path, struct btrfs_device *device, *tmp_device; list_for_each_entry_safe(fs_devices, tmp_fs_devices, &fs_uuids, fs_list) { - if (fs_devices->opened) + mutex_lock(&fs_devices->device_list_mutex); + if (fs_devices->opened) { + mutex_unlock(&fs_devices->device_list_mutex); continue; + } list_for_each_entry_safe(device, tmp_device, &fs_devices->devices, dev_list) { @@ -658,16 +661,18 @@ static void btrfs_free_stale_devices(const char *path, continue; /* delete the stale device */ - if (fs_devices->num_devices == 1) { - btrfs_sysfs_remove_fsid(fs_devices); - list_del(&fs_devices->fs_list); - free_fs_devices(fs_devices); + fs_devices->num_devices--; + list_del(&device->dev_list); + btrfs_free_device(device); + + if (fs_devices->num_devices == 0) break; - } else { - fs_devices->num_devices--; - list_del(&device->dev_list); - btrfs_free_device(device); - } + } + mutex_unlock(&fs_devices->device_list_mutex); + if (fs_devices->num_devices == 0) { + btrfs_sysfs_remove_fsid(fs_devices); + list_del(&fs_devices->fs_list); + free_fs_devices(fs_devices); } } } |