btrfs: fix lock dep warning, move scratch dev out of device_list_mutex and uuid_mutex
[cascardo/linux.git] / fs / btrfs / volumes.c
index 83dfed6..7bd553d 100644 (file)
@@ -2024,10 +2024,9 @@ void btrfs_destroy_dev_replace_tgtdev(struct btrfs_fs_info *fs_info,
 
        btrfs_sysfs_rm_device_link(fs_info->fs_devices, tgtdev);
 
-       if (tgtdev->bdev) {
-               btrfs_scratch_superblocks(tgtdev->bdev, tgtdev->name->str);
+       if (tgtdev->bdev)
                fs_info->fs_devices->open_devices--;
-       }
+
        fs_info->fs_devices->num_devices--;
 
        next_device = list_entry(fs_info->fs_devices->devices.next,
@@ -2038,10 +2037,18 @@ void btrfs_destroy_dev_replace_tgtdev(struct btrfs_fs_info *fs_info,
                fs_info->fs_devices->latest_bdev = next_device->bdev;
        list_del_rcu(&tgtdev->dev_list);
 
-       call_rcu(&tgtdev->rcu, free_device);
-
        mutex_unlock(&fs_info->fs_devices->device_list_mutex);
        mutex_unlock(&uuid_mutex);
+
+       /*
+        * The update_dev_time() with in btrfs_scratch_superblocks()
+        * may lead to a call to btrfs_show_devname() which will try
+        * to hold device_list_mutex. And here this device
+        * is already out of device list, so we don't have to hold
+        * the device_list_mutex lock.
+        */
+       btrfs_scratch_superblocks(tgtdev->bdev, tgtdev->name->str);
+       call_rcu(&tgtdev->rcu, free_device);
 }
 
 static int btrfs_find_device_by_path(struct btrfs_root *root, char *device_path,