btrfs: match stale devices by dev_t
[sfrench/cifs-2.6.git] / fs / btrfs / volumes.c
index 188e2a61402d032fe9ba2b8779553bd05ce31e2d..b47dd13877666b4272e1add603f2526806c3c42a 100644 (file)
@@ -541,11 +541,10 @@ error:
  *   true  If it is the same device.
  *   false If it is not the same device or on error.
  */
-static bool device_matched(const struct btrfs_device *device, const char *path)
+static bool device_matched(const struct btrfs_device *device, dev_t dev_new)
 {
        char *device_name;
        dev_t dev_old;
-       dev_t dev_new;
        int ret;
 
        /*
@@ -568,29 +567,26 @@ static bool device_matched(const struct btrfs_device *device, const char *path)
        if (ret)
                return false;
 
-       ret = lookup_bdev(path, &dev_new);
-       if (ret)
-               return false;
-
        if (dev_old == dev_new)
                return true;
 
        return false;
 }
 
-/*
- *  Search and remove all stale (devices which are not mounted) devices.
+/**
+ *  Search and remove all stale devices (which are not mounted).
  *  When both inputs are NULL, it will search and release all stale devices.
- *  path:      Optional. When provided will it release all unmounted devices
- *             matching this path only.
- *  skip_dev:  Optional. Will skip this device when searching for the stale
+ *
+ *  @devt:     Optional. When provided will it release all unmounted devices
+ *             matching this devt only.
+ *  @skip_device:  Optional. Will skip this device when searching for the stale
  *             devices.
- *  Return:    0 for success or if @path is NULL.
- *             -EBUSY if @path is a mounted device.
- *             -ENOENT if @path does not match any device in the list.
+ *
+ *  Return:    0 for success or if @devt is 0.
+ *             -EBUSY if @devt is a mounted device.
+ *             -ENOENT if @devt does not match any device in the list.
  */
-static int btrfs_free_stale_devices(const char *path,
-                                    struct btrfs_device *skip_device)
+static int btrfs_free_stale_devices(dev_t devt, struct btrfs_device *skip_device)
 {
        struct btrfs_fs_devices *fs_devices, *tmp_fs_devices;
        struct btrfs_device *device, *tmp_device;
@@ -598,7 +594,7 @@ static int btrfs_free_stale_devices(const char *path,
 
        lockdep_assert_held(&uuid_mutex);
 
-       if (path)
+       if (devt)
                ret = -ENOENT;
 
        list_for_each_entry_safe(fs_devices, tmp_fs_devices, &fs_uuids, fs_list) {
@@ -608,11 +604,11 @@ static int btrfs_free_stale_devices(const char *path,
                                         &fs_devices->devices, dev_list) {
                        if (skip_device && skip_device == device)
                                continue;
-                       if (path && !device_matched(device, path))
+                       if (devt && !device_matched(device, devt))
                                continue;
                        if (fs_devices->opened) {
                                /* for an already deleted device return 0 */
-                               if (path && ret != 0)
+                               if (devt && ret != 0)
                                        ret = -EBUSY;
                                break;
                        }
@@ -1362,12 +1358,12 @@ static struct btrfs_super_block *btrfs_read_disk_super(struct block_device *bdev
        return disk_super;
 }
 
-int btrfs_forget_devices(const char *path)
+int btrfs_forget_devices(dev_t devt)
 {
        int ret;
 
        mutex_lock(&uuid_mutex);
-       ret = btrfs_free_stale_devices(strlen(path) ? path : NULL, NULL);
+       ret = btrfs_free_stale_devices(devt, NULL);
        mutex_unlock(&uuid_mutex);
 
        return ret;
@@ -1416,9 +1412,15 @@ struct btrfs_device *btrfs_scan_one_device(const char *path, fmode_t flags,
        }
 
        device = device_list_add(path, disk_super, &new_device_added);
-       if (!IS_ERR(device)) {
-               if (new_device_added)
-                       btrfs_free_stale_devices(path, device);
+       if (!IS_ERR(device) && new_device_added) {
+               dev_t devt;
+
+               /*
+                * It is ok to ignore if we fail to free the stale device (if
+                * any). As there is nothing much that can be done about it.
+                */
+               if (lookup_bdev(path, &devt) == 0)
+                       btrfs_free_stale_devices(devt, device);
        }
 
        btrfs_release_disk_super(disk_super);
@@ -2650,6 +2652,7 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
        int ret = 0;
        bool seeding_dev = false;
        bool locked = false;
+       dev_t devt;
 
        if (sb_rdonly(sb) && !fs_devices->seeding)
                return -EROFS;
@@ -2842,10 +2845,13 @@ int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *device_path
         * Now that we have written a new super block to this device, check all
         * other fs_devices list if device_path alienates any other scanned
         * device.
+        * Skip forget_deivces if lookup_bdev() fails as there is nothing much
+        * that can be done about it.
         * We can ignore the return value as it typically returns -EINVAL and
         * only succeeds if the device was an alien.
         */
-       btrfs_forget_devices(device_path);
+       if (lookup_bdev(device_path, &devt) == 0)
+               btrfs_forget_devices(devt);
 
        /* Update ctime/mtime for blkid or udev */
        update_dev_time(device_path);