]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
btrfs: refactor btrfs_free_stale_devices() to get return value
authorAnand Jain <anand.jain@oracle.com>
Fri, 4 Jan 2019 05:31:53 +0000 (13:31 +0800)
committerDavid Sterba <dsterba@suse.com>
Mon, 25 Feb 2019 13:13:23 +0000 (14:13 +0100)
Preparatory patch to add ioctl that allows to forget a device (ie.
reverse of scan).

Refactors btrfs_free_stale_devices() to obtain return status. As this
function can fail if it can't find the given path (returns -ENOENT) or
trying to delete a mounted device (returns -EBUSY).

Signed-off-by: Anand Jain <anand.jain@oracle.com>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/volumes.c

index 1bb2a7923fc6a138bdf3cc76cfa7f2e2390907b7..74bbfed6428b375e60c9de8be65acabbe1648d0d 100644 (file)
@@ -734,6 +734,17 @@ static void pending_bios_fn(struct btrfs_work *work)
        run_scheduled_bios(device);
 }
 
+static bool device_path_matched(const char *path, struct btrfs_device *device)
+{
+       int found;
+
+       rcu_read_lock();
+       found = strcmp(rcu_str_deref(device->name), path);
+       rcu_read_unlock();
+
+       return found == 0;
+}
+
 /*
  *  Search and remove all stale (devices which are not mounted) devices.
  *  When both inputs are NULL, it will search and release all stale devices.
@@ -741,52 +752,57 @@ static void pending_bios_fn(struct btrfs_work *work)
  *             matching this path only.
  *  skip_dev:  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.
  */
-static void btrfs_free_stale_devices(const char *path,
+static int btrfs_free_stale_devices(const char *path,
                                     struct btrfs_device *skip_device)
 {
        struct btrfs_fs_devices *fs_devices, *tmp_fs_devices;
        struct btrfs_device *device, *tmp_device;
+       int ret = 0;
+
+       if (path)
+               ret = -ENOENT;
 
        list_for_each_entry_safe(fs_devices, tmp_fs_devices, &fs_uuids, fs_list) {
-               mutex_lock(&fs_devices->device_list_mutex);
-               if (fs_devices->opened) {
-                       mutex_unlock(&fs_devices->device_list_mutex);
-                       continue;
-               }
 
+               mutex_lock(&fs_devices->device_list_mutex);
                list_for_each_entry_safe(device, tmp_device,
                                         &fs_devices->devices, dev_list) {
-                       int not_found = 0;
-
                        if (skip_device && skip_device == device)
                                continue;
                        if (path && !device->name)
                                continue;
-
-                       rcu_read_lock();
-                       if (path)
-                               not_found = strcmp(rcu_str_deref(device->name),
-                                                  path);
-                       rcu_read_unlock();
-                       if (not_found)
+                       if (path && !device_path_matched(path, device))
                                continue;
+                       if (fs_devices->opened) {
+                               /* for an already deleted device return 0 */
+                               if (path && ret != 0)
+                                       ret = -EBUSY;
+                               break;
+                       }
 
                        /* delete the stale device */
                        fs_devices->num_devices--;
                        list_del(&device->dev_list);
                        btrfs_free_device(device);
 
+                       ret = 0;
                        if (fs_devices->num_devices == 0)
                                break;
                }
                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);
                }
        }
+
+       return ret;
 }
 
 static int btrfs_open_one_device(struct btrfs_fs_devices *fs_devices,