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: Anand Jain <anand.jain@oracle.com> Reviewed-by: David Sterba <dsterba@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
Родитель
e4319cd9ca
Коммит
70bc7088aa
|
@ -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,
|
||||
|
|
Загрузка…
Ссылка в новой задаче