4.18-stable review patch. If anyone has any objections, please let me know.
------------------
From: Anand Jain anand.jain@oracle.com
[ Upstream commit 7bcb8164ad9435068d9bc3b83b8a002c64d63ff6 ]
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 Signed-off-by: Sasha Levin alexander.levin@microsoft.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/btrfs/volumes.c | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-)
--- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -640,8 +640,11 @@ static void btrfs_free_stale_devices(con 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) { @@ -661,16 +664,18 @@ static void btrfs_free_stale_devices(con 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); } } }