Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 70bc7088 authored by Anand Jain's avatar Anand Jain Committed by David Sterba
Browse files

btrfs: refactor btrfs_free_stale_devices() to get return value



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: default avatarAnand Jain <anand.jain@oracle.com>
Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
parent e4319cd9
Loading
Loading
Loading
Loading
+31 −15
Original line number Diff line number Diff line
@@ -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,