mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	btrfs: add a btrfs_get_dev_args_from_path helper
We are going to want to populate our device lookup args outside of any locks and then do the actual device lookup later, so add a helper to do this work and make btrfs_find_device_by_devspec() use this helper for now. Reviewed-by: Nikolay Borisov <nborisov@suse.com> Reviewed-by: Anand Jain <anand.jain@oracle.com> Signed-off-by: Josef Bacik <josef@toxicpanda.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
		
							parent
							
								
									562d7b1512
								
							
						
					
					
						commit
						faa775c41d
					
				
					 2 changed files with 68 additions and 32 deletions
				
			
		| 
						 | 
				
			
			@ -2325,45 +2325,81 @@ void btrfs_destroy_dev_replace_tgtdev(struct btrfs_device *tgtdev)
 | 
			
		|||
	btrfs_free_device(tgtdev);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static struct btrfs_device *btrfs_find_device_by_path(
 | 
			
		||||
		struct btrfs_fs_info *fs_info, const char *device_path)
 | 
			
		||||
/**
 | 
			
		||||
 * Populate args from device at path
 | 
			
		||||
 *
 | 
			
		||||
 * @fs_info:	the filesystem
 | 
			
		||||
 * @args:	the args to populate
 | 
			
		||||
 * @path:	the path to the device
 | 
			
		||||
 *
 | 
			
		||||
 * This will read the super block of the device at @path and populate @args with
 | 
			
		||||
 * the devid, fsid, and uuid.  This is meant to be used for ioctls that need to
 | 
			
		||||
 * lookup a device to operate on, but need to do it before we take any locks.
 | 
			
		||||
 * This properly handles the special case of "missing" that a user may pass in,
 | 
			
		||||
 * and does some basic sanity checks.  The caller must make sure that @path is
 | 
			
		||||
 * properly NUL terminated before calling in, and must call
 | 
			
		||||
 * btrfs_put_dev_args_from_path() in order to free up the temporary fsid and
 | 
			
		||||
 * uuid buffers.
 | 
			
		||||
 *
 | 
			
		||||
 * Return: 0 for success, -errno for failure
 | 
			
		||||
 */
 | 
			
		||||
int btrfs_get_dev_args_from_path(struct btrfs_fs_info *fs_info,
 | 
			
		||||
				 struct btrfs_dev_lookup_args *args,
 | 
			
		||||
				 const char *path)
 | 
			
		||||
{
 | 
			
		||||
	BTRFS_DEV_LOOKUP_ARGS(args);
 | 
			
		||||
	int ret = 0;
 | 
			
		||||
	struct btrfs_super_block *disk_super;
 | 
			
		||||
	struct block_device *bdev;
 | 
			
		||||
	struct btrfs_device *device;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	ret = btrfs_get_bdev_and_sb(device_path, FMODE_READ,
 | 
			
		||||
				    fs_info->bdev_holder, 0, &bdev, &disk_super);
 | 
			
		||||
	if (!path || !path[0])
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
	if (!strcmp(path, "missing")) {
 | 
			
		||||
		args->missing = true;
 | 
			
		||||
		return 0;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	args->uuid = kzalloc(BTRFS_UUID_SIZE, GFP_KERNEL);
 | 
			
		||||
	args->fsid = kzalloc(BTRFS_FSID_SIZE, GFP_KERNEL);
 | 
			
		||||
	if (!args->uuid || !args->fsid) {
 | 
			
		||||
		btrfs_put_dev_args_from_path(args);
 | 
			
		||||
		return -ENOMEM;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	ret = btrfs_get_bdev_and_sb(path, FMODE_READ, fs_info->bdev_holder, 0,
 | 
			
		||||
				    &bdev, &disk_super);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ERR_PTR(ret);
 | 
			
		||||
 | 
			
		||||
	args.devid = btrfs_stack_device_id(&disk_super->dev_item);
 | 
			
		||||
	args.uuid = disk_super->dev_item.uuid;
 | 
			
		||||
		return ret;
 | 
			
		||||
	args->devid = btrfs_stack_device_id(&disk_super->dev_item);
 | 
			
		||||
	memcpy(args->uuid, disk_super->dev_item.uuid, BTRFS_UUID_SIZE);
 | 
			
		||||
	if (btrfs_fs_incompat(fs_info, METADATA_UUID))
 | 
			
		||||
		args.fsid = disk_super->metadata_uuid;
 | 
			
		||||
		memcpy(args->fsid, disk_super->metadata_uuid, BTRFS_FSID_SIZE);
 | 
			
		||||
	else
 | 
			
		||||
		args.fsid = disk_super->fsid;
 | 
			
		||||
 | 
			
		||||
	device = btrfs_find_device(fs_info->fs_devices, &args);
 | 
			
		||||
 | 
			
		||||
		memcpy(args->fsid, disk_super->fsid, BTRFS_FSID_SIZE);
 | 
			
		||||
	btrfs_release_disk_super(disk_super);
 | 
			
		||||
	if (!device)
 | 
			
		||||
		device = ERR_PTR(-ENOENT);
 | 
			
		||||
	blkdev_put(bdev, FMODE_READ);
 | 
			
		||||
	return device;
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Lookup a device given by device id, or the path if the id is 0.
 | 
			
		||||
 * Only use this jointly with btrfs_get_dev_args_from_path() because we will
 | 
			
		||||
 * allocate our ->uuid and ->fsid pointers, everybody else uses local variables
 | 
			
		||||
 * that don't need to be freed.
 | 
			
		||||
 */
 | 
			
		||||
void btrfs_put_dev_args_from_path(struct btrfs_dev_lookup_args *args)
 | 
			
		||||
{
 | 
			
		||||
	kfree(args->uuid);
 | 
			
		||||
	kfree(args->fsid);
 | 
			
		||||
	args->uuid = NULL;
 | 
			
		||||
	args->fsid = NULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct btrfs_device *btrfs_find_device_by_devspec(
 | 
			
		||||
		struct btrfs_fs_info *fs_info, u64 devid,
 | 
			
		||||
		const char *device_path)
 | 
			
		||||
{
 | 
			
		||||
	BTRFS_DEV_LOOKUP_ARGS(args);
 | 
			
		||||
	struct btrfs_device *device;
 | 
			
		||||
	int ret;
 | 
			
		||||
 | 
			
		||||
	if (devid) {
 | 
			
		||||
		args.devid = devid;
 | 
			
		||||
| 
						 | 
				
			
			@ -2373,18 +2409,14 @@ struct btrfs_device *btrfs_find_device_by_devspec(
 | 
			
		|||
		return device;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (!device_path || !device_path[0])
 | 
			
		||||
		return ERR_PTR(-EINVAL);
 | 
			
		||||
 | 
			
		||||
	if (strcmp(device_path, "missing") == 0) {
 | 
			
		||||
		args.missing = true;
 | 
			
		||||
		device = btrfs_find_device(fs_info->fs_devices, &args);
 | 
			
		||||
		if (!device)
 | 
			
		||||
			return ERR_PTR(-ENOENT);
 | 
			
		||||
		return device;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	return btrfs_find_device_by_path(fs_info, device_path);
 | 
			
		||||
	ret = btrfs_get_dev_args_from_path(fs_info, &args, device_path);
 | 
			
		||||
	if (ret)
 | 
			
		||||
		return ERR_PTR(ret);
 | 
			
		||||
	device = btrfs_find_device(fs_info->fs_devices, &args);
 | 
			
		||||
	btrfs_put_dev_args_from_path(&args);
 | 
			
		||||
	if (!device)
 | 
			
		||||
		return ERR_PTR(-ENOENT);
 | 
			
		||||
	return device;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -520,9 +520,13 @@ void btrfs_assign_next_active_device(struct btrfs_device *device,
 | 
			
		|||
struct btrfs_device *btrfs_find_device_by_devspec(struct btrfs_fs_info *fs_info,
 | 
			
		||||
						  u64 devid,
 | 
			
		||||
						  const char *devpath);
 | 
			
		||||
int btrfs_get_dev_args_from_path(struct btrfs_fs_info *fs_info,
 | 
			
		||||
				 struct btrfs_dev_lookup_args *args,
 | 
			
		||||
				 const char *path);
 | 
			
		||||
struct btrfs_device *btrfs_alloc_device(struct btrfs_fs_info *fs_info,
 | 
			
		||||
					const u64 *devid,
 | 
			
		||||
					const u8 *uuid);
 | 
			
		||||
void btrfs_put_dev_args_from_path(struct btrfs_dev_lookup_args *args);
 | 
			
		||||
void btrfs_free_device(struct btrfs_device *device);
 | 
			
		||||
int btrfs_rm_device(struct btrfs_fs_info *fs_info,
 | 
			
		||||
		    const char *device_path, u64 devid,
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue