diff mbox series

[v3,4/6] btrfs: handle device lookup with btrfs_dev_lookup_args

Message ID 5fb28919a4034e6ebd0c677e5bb1b52bf8fb4fdd.1633367810.git.josef@toxicpanda.com (mailing list archive)
State New, archived
Headers show
Series Fix lockdep issues around device removal | expand

Commit Message

Josef Bacik Oct. 4, 2021, 5:19 p.m. UTC
We have a lot of device lookup functions that all do something slightly
different.  Clean this up by adding a struct to hold the different
lookup criteria, and then pass this around to btrfs_find_device() so it
can do the proper matching based on the lookup criteria.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 fs/btrfs/dev-replace.c |  18 +++----
 fs/btrfs/ioctl.c       |  13 ++---
 fs/btrfs/scrub.c       |   6 ++-
 fs/btrfs/volumes.c     | 120 +++++++++++++++++++++++++----------------
 fs/btrfs/volumes.h     |  15 +++++-
 5 files changed, 108 insertions(+), 64 deletions(-)

Comments

Anand Jain Oct. 5, 2021, 4:48 a.m. UTC | #1
On 05/10/2021 01:19, Josef Bacik wrote:
> We have a lot of device lookup functions that all do something slightly
> different.

>  Clean this up by adding a struct to hold the different
> lookup criteria, and then pass this around to btrfs_find_device() so it
> can do the proper matching based on the lookup criteria.

  It is better now.

> Signed-off-by: Josef Bacik <josef@toxicpanda.com>

  Looks good.

  Reviewed-by: Anand Jain <anand.jain@oracle.com>

Thanks, Anand


> ---
>   fs/btrfs/dev-replace.c |  18 +++----
>   fs/btrfs/ioctl.c       |  13 ++---
>   fs/btrfs/scrub.c       |   6 ++-
>   fs/btrfs/volumes.c     | 120 +++++++++++++++++++++++++----------------
>   fs/btrfs/volumes.h     |  15 +++++-
>   5 files changed, 108 insertions(+), 64 deletions(-)
> 
> diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c
> index d029be40ea6f..ff25da2dbd59 100644
> --- a/fs/btrfs/dev-replace.c
> +++ b/fs/btrfs/dev-replace.c
> @@ -70,6 +70,7 @@ static int btrfs_dev_replace_kthread(void *data);
>   
>   int btrfs_init_dev_replace(struct btrfs_fs_info *fs_info)
>   {
> +	BTRFS_DEV_LOOKUP_ARGS(args);
>   	struct btrfs_key key;
>   	struct btrfs_root *dev_root = fs_info->dev_root;
>   	struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;
> @@ -84,6 +85,8 @@ int btrfs_init_dev_replace(struct btrfs_fs_info *fs_info)
>   	if (!dev_root)
>   		return 0;
>   
> +	args.devid = BTRFS_DEV_REPLACE_DEVID;
> +
>   	path = btrfs_alloc_path();
>   	if (!path) {
>   		ret = -ENOMEM;
> @@ -100,8 +103,7 @@ int btrfs_init_dev_replace(struct btrfs_fs_info *fs_info)
>   		 * We don't have a replace item or it's corrupted.  If there is
>   		 * a replace target, fail the mount.
>   		 */
> -		if (btrfs_find_device(fs_info->fs_devices,
> -				      BTRFS_DEV_REPLACE_DEVID, NULL, NULL)) {
> +		if (btrfs_find_device(fs_info->fs_devices, &args)) {
>   			btrfs_err(fs_info,
>   			"found replace target device without a valid replace item");
>   			ret = -EUCLEAN;
> @@ -163,8 +165,7 @@ int btrfs_init_dev_replace(struct btrfs_fs_info *fs_info)
>   		 * We don't have an active replace item but if there is a
>   		 * replace target, fail the mount.
>   		 */
> -		if (btrfs_find_device(fs_info->fs_devices,
> -				      BTRFS_DEV_REPLACE_DEVID, NULL, NULL)) {
> +		if (btrfs_find_device(fs_info->fs_devices, &args)) {
>   			btrfs_err(fs_info,
>   			"replace devid present without an active replace item");
>   			ret = -EUCLEAN;
> @@ -175,11 +176,10 @@ int btrfs_init_dev_replace(struct btrfs_fs_info *fs_info)
>   		break;
>   	case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED:
>   	case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED:
> -		dev_replace->srcdev = btrfs_find_device(fs_info->fs_devices,
> -						src_devid, NULL, NULL);
> -		dev_replace->tgtdev = btrfs_find_device(fs_info->fs_devices,
> -							BTRFS_DEV_REPLACE_DEVID,
> -							NULL, NULL);
> +		dev_replace->tgtdev = btrfs_find_device(fs_info->fs_devices, &args);
> +		args.devid = src_devid;
> +		dev_replace->srcdev = btrfs_find_device(fs_info->fs_devices, &args);
> +
>   		/*
>   		 * allow 'btrfs dev replace_cancel' if src/tgt device is
>   		 * missing
> diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
> index 9eb0c1eb568e..b8508af4e539 100644
> --- a/fs/btrfs/ioctl.c
> +++ b/fs/btrfs/ioctl.c
> @@ -1602,6 +1602,7 @@ static int exclop_start_or_cancel_reloc(struct btrfs_fs_info *fs_info,
>   static noinline int btrfs_ioctl_resize(struct file *file,
>   					void __user *arg)
>   {
> +	BTRFS_DEV_LOOKUP_ARGS(args);
>   	struct inode *inode = file_inode(file);
>   	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
>   	u64 new_size;
> @@ -1657,7 +1658,8 @@ static noinline int btrfs_ioctl_resize(struct file *file,
>   		btrfs_info(fs_info, "resizing devid %llu", devid);
>   	}
>   
> -	device = btrfs_find_device(fs_info->fs_devices, devid, NULL, NULL);
> +	args.devid = devid;
> +	device = btrfs_find_device(fs_info->fs_devices, &args);
>   	if (!device) {
>   		btrfs_info(fs_info, "resizer unable to find device %llu",
>   			   devid);
> @@ -3317,22 +3319,21 @@ static long btrfs_ioctl_fs_info(struct btrfs_fs_info *fs_info,
>   static long btrfs_ioctl_dev_info(struct btrfs_fs_info *fs_info,
>   				 void __user *arg)
>   {
> +	BTRFS_DEV_LOOKUP_ARGS(args);
>   	struct btrfs_ioctl_dev_info_args *di_args;
>   	struct btrfs_device *dev;
>   	int ret = 0;
> -	char *s_uuid = NULL;
>   
>   	di_args = memdup_user(arg, sizeof(*di_args));
>   	if (IS_ERR(di_args))
>   		return PTR_ERR(di_args);
>   
> +	args.devid = di_args->devid;
>   	if (!btrfs_is_empty_uuid(di_args->uuid))
> -		s_uuid = di_args->uuid;
> +		args.uuid = di_args->uuid;
>   
>   	rcu_read_lock();
> -	dev = btrfs_find_device(fs_info->fs_devices, di_args->devid, s_uuid,
> -				NULL);
> -
> +	dev = btrfs_find_device(fs_info->fs_devices, &args);
>   	if (!dev) {
>   		ret = -ENODEV;
>   		goto out;
> diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
> index bd3cd7427391..1e29b9aa45df 100644
> --- a/fs/btrfs/scrub.c
> +++ b/fs/btrfs/scrub.c
> @@ -4067,6 +4067,7 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,
>   		    u64 end, struct btrfs_scrub_progress *progress,
>   		    int readonly, int is_dev_replace)
>   {
> +	struct btrfs_dev_lookup_args args = { .devid = devid };

>   	struct scrub_ctx *sctx;
>   	int ret;
>   	struct btrfs_device *dev;
> @@ -4114,7 +4115,7 @@ int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,
>   		goto out_free_ctx;
>   
>   	mutex_lock(&fs_info->fs_devices->device_list_mutex);
> -	dev = btrfs_find_device(fs_info->fs_devices, devid, NULL, NULL);
> +	dev = btrfs_find_device(fs_info->fs_devices, &args);
>   	if (!dev || (test_bit(BTRFS_DEV_STATE_MISSING, &dev->dev_state) &&
>   		     !is_dev_replace)) {
>   		mutex_unlock(&fs_info->fs_devices->device_list_mutex);
> @@ -4287,11 +4288,12 @@ int btrfs_scrub_cancel_dev(struct btrfs_device *dev)
>   int btrfs_scrub_progress(struct btrfs_fs_info *fs_info, u64 devid,
>   			 struct btrfs_scrub_progress *progress)
>   {
> +	struct btrfs_dev_lookup_args args = { .devid = devid };


>   	struct btrfs_device *dev;
>   	struct scrub_ctx *sctx = NULL;
>   
>   	mutex_lock(&fs_info->fs_devices->device_list_mutex);
> -	dev = btrfs_find_device(fs_info->fs_devices, devid, NULL, NULL);
> +	dev = btrfs_find_device(fs_info->fs_devices, &args);
>   	if (dev)
>   		sctx = dev->scrub_ctx;
>   	if (sctx)
> diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
> index 5f19d0863094..191360e44a20 100644
> --- a/fs/btrfs/volumes.c
> +++ b/fs/btrfs/volumes.c
> @@ -812,9 +812,13 @@ static noinline struct btrfs_device *device_list_add(const char *path,
>   
>   		device = NULL;
>   	} else {
> +		struct btrfs_dev_lookup_args args = {
> +			.devid = devid,
> +			.uuid = disk_super->dev_item.uuid,
> +		};
> +
>   		mutex_lock(&fs_devices->device_list_mutex);
> -		device = btrfs_find_device(fs_devices, devid,
> -				disk_super->dev_item.uuid, NULL);
> +		device = btrfs_find_device(fs_devices, &args);
>   
>   		/*
>   		 * If this disk has been pulled into an fs devices created by
> @@ -2323,10 +2327,9 @@ void btrfs_destroy_dev_replace_tgtdev(struct btrfs_device *tgtdev)
>   static struct btrfs_device *btrfs_find_device_by_path(
>   		struct btrfs_fs_info *fs_info, const char *device_path)
>   {
> +	BTRFS_DEV_LOOKUP_ARGS(args);
>   	int ret = 0;
>   	struct btrfs_super_block *disk_super;
> -	u64 devid;
> -	u8 *dev_uuid;
>   	struct block_device *bdev;
>   	struct btrfs_device *device;
>   
> @@ -2335,14 +2338,14 @@ static struct btrfs_device *btrfs_find_device_by_path(
>   	if (ret)
>   		return ERR_PTR(ret);
>   
> -	devid = btrfs_stack_device_id(&disk_super->dev_item);
> -	dev_uuid = disk_super->dev_item.uuid;
> +	args.devid = btrfs_stack_device_id(&disk_super->dev_item);
> +	args.uuid = disk_super->dev_item.uuid;
>   	if (btrfs_fs_incompat(fs_info, METADATA_UUID))
> -		device = btrfs_find_device(fs_info->fs_devices, devid, dev_uuid,
> -					   disk_super->metadata_uuid);
> +		args.fsid = disk_super->metadata_uuid;
>   	else
> -		device = btrfs_find_device(fs_info->fs_devices, devid, dev_uuid,
> -					   disk_super->fsid);
> +		args.fsid = disk_super->fsid;
> +
> +	device = btrfs_find_device(fs_info->fs_devices, &args);
>   
>   	btrfs_release_disk_super(disk_super);
>   	if (!device)
> @@ -2358,11 +2361,12 @@ 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;
>   
>   	if (devid) {
> -		device = btrfs_find_device(fs_info->fs_devices, devid, NULL,
> -					   NULL);
> +		args.devid = devid;
> +		device = btrfs_find_device(fs_info->fs_devices, &args);
>   		if (!device)
>   			return ERR_PTR(-ENOENT);
>   		return device;
> @@ -2372,14 +2376,11 @@ struct btrfs_device *btrfs_find_device_by_devspec(
>   		return ERR_PTR(-EINVAL);
>   
>   	if (strcmp(device_path, "missing") == 0) {
> -		/* Find first missing device */
> -		list_for_each_entry(device, &fs_info->fs_devices->devices,
> -				    dev_list) {
> -			if (test_bit(BTRFS_DEV_STATE_IN_FS_METADATA,
> -				     &device->dev_state) && !device->bdev)
> -				return device;
> -		}
> -		return ERR_PTR(-ENOENT);
> +		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);
> @@ -2459,6 +2460,7 @@ static int btrfs_prepare_sprout(struct btrfs_fs_info *fs_info)
>    */
>   static int btrfs_finish_sprout(struct btrfs_trans_handle *trans)
>   {
> +	BTRFS_DEV_LOOKUP_ARGS(args);
>   	struct btrfs_fs_info *fs_info = trans->fs_info;
>   	struct btrfs_root *root = fs_info->chunk_root;
>   	struct btrfs_path *path;
> @@ -2468,7 +2470,6 @@ static int btrfs_finish_sprout(struct btrfs_trans_handle *trans)
>   	struct btrfs_key key;
>   	u8 fs_uuid[BTRFS_FSID_SIZE];
>   	u8 dev_uuid[BTRFS_UUID_SIZE];
> -	u64 devid;
>   	int ret;
>   
>   	path = btrfs_alloc_path();
> @@ -2505,13 +2506,14 @@ static int btrfs_finish_sprout(struct btrfs_trans_handle *trans)
>   
>   		dev_item = btrfs_item_ptr(leaf, path->slots[0],
>   					  struct btrfs_dev_item);

> -		devid = btrfs_device_id(leaf, dev_item);
> +		args.devid = btrfs_device_id(leaf, dev_item);

>   		read_extent_buffer(leaf, dev_uuid, btrfs_device_uuid(dev_item),
>   				   BTRFS_UUID_SIZE);
>   		read_extent_buffer(leaf, fs_uuid, btrfs_device_fsid(dev_item),
>   				   BTRFS_FSID_SIZE);
> -		device = btrfs_find_device(fs_info->fs_devices, devid, dev_uuid,
> -					   fs_uuid);
> +		args.uuid = dev_uuid;
> +		args.fsid = fs_uuid;



> +		device = btrfs_find_device(fs_info->fs_devices, &args);
>   		BUG_ON(!device); /* Logic error */
>   
>   		if (device->fs_devices->seeding) {
> @@ -6753,6 +6755,32 @@ blk_status_t btrfs_map_bio(struct btrfs_fs_info *fs_info, struct bio *bio,
>   	return BLK_STS_OK;
>   }
>   
> +static inline bool dev_args_match_fs_devices(struct btrfs_dev_lookup_args *args,
> +					     struct btrfs_fs_devices *fs_devices)
> +{
> +	if (args->fsid == NULL)
> +		return true;
> +	if (!memcmp(fs_devices->metadata_uuid, args->fsid, BTRFS_FSID_SIZE))
> +		return true;
> +	return false;
> +}
> +

> +static inline bool dev_args_match_device(struct btrfs_dev_lookup_args *args,
> +					 struct btrfs_device *device)
> +{
> +	ASSERT((args->devid != (u64)-1) || args->missing);
> +	if ((args->devid != (u64)-1) && device->devid != args->devid)
> +		return false;
> +	if (args->uuid && memcmp(device->uuid, args->uuid, BTRFS_UUID_SIZE))
> +		return false;
> +	if (!args->missing)
> +		return true;
> +	if (test_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &device->dev_state) &&
> +	    !device->bdev)
> +		return true;
> +	return false;
> +}


> +
>   /*
>    * Find a device specified by @devid or @uuid in the list of @fs_devices, or
>    * return NULL.
> @@ -6761,30 +6789,24 @@ blk_status_t btrfs_map_bio(struct btrfs_fs_info *fs_info, struct bio *bio,
>    * only devid is used.
>    */
>   struct btrfs_device *btrfs_find_device(struct btrfs_fs_devices *fs_devices,
> -				       u64 devid, u8 *uuid, u8 *fsid)
> +				       struct btrfs_dev_lookup_args *args)
>   {
>   	struct btrfs_device *device;
>   	struct btrfs_fs_devices *seed_devs;
>   
> -	if (!fsid || !memcmp(fs_devices->metadata_uuid, fsid, BTRFS_FSID_SIZE)) {
> +	if (dev_args_match_fs_devices(args, fs_devices)) {
>   		list_for_each_entry(device, &fs_devices->devices, dev_list) {
> -			if (device->devid == devid &&
> -			    (!uuid || memcmp(device->uuid, uuid,
> -					     BTRFS_UUID_SIZE) == 0))
> +			if (dev_args_match_device(args, device))
>   				return device;
>   		}
>   	}
>   
>   	list_for_each_entry(seed_devs, &fs_devices->seed_list, seed_list) {
> -		if (!fsid ||
> -		    !memcmp(seed_devs->metadata_uuid, fsid, BTRFS_FSID_SIZE)) {
> -			list_for_each_entry(device, &seed_devs->devices,
> -					    dev_list) {
> -				if (device->devid == devid &&
> -				    (!uuid || memcmp(device->uuid, uuid,
> -						     BTRFS_UUID_SIZE) == 0))
> -					return device;
> -			}
> +		if (!dev_args_match_fs_devices(args, seed_devs))
> +			continue;
> +		list_for_each_entry(device, &seed_devs->devices, dev_list) {
> +			if (dev_args_match_device(args, device))
> +				return device;
>   		}
>   	}
>   
> @@ -6950,6 +6972,7 @@ static void warn_32bit_meta_chunk(struct btrfs_fs_info *fs_info,
>   static int read_one_chunk(struct btrfs_key *key, struct extent_buffer *leaf,
>   			  struct btrfs_chunk *chunk)
>   {
> +	BTRFS_DEV_LOOKUP_ARGS(args);
>   	struct btrfs_fs_info *fs_info = leaf->fs_info;
>   	struct extent_map_tree *map_tree = &fs_info->mapping_tree;
>   	struct map_lookup *map;
> @@ -7026,12 +7049,12 @@ static int read_one_chunk(struct btrfs_key *key, struct extent_buffer *leaf,
>   	for (i = 0; i < num_stripes; i++) {
>   		map->stripes[i].physical =
>   			btrfs_stripe_offset_nr(leaf, chunk, i);
> -		devid = btrfs_stripe_devid_nr(leaf, chunk, i);
> +		args.devid = btrfs_stripe_devid_nr(leaf, chunk, i);
>   		read_extent_buffer(leaf, uuid, (unsigned long)
>   				   btrfs_stripe_dev_uuid_nr(chunk, i),
>   				   BTRFS_UUID_SIZE);
> -		map->stripes[i].dev = btrfs_find_device(fs_info->fs_devices,
> -							devid, uuid, NULL);
> +		args.uuid = uuid;
> +		map->stripes[i].dev = btrfs_find_device(fs_info->fs_devices, &args);
>   		if (!map->stripes[i].dev &&
>   		    !btrfs_test_opt(fs_info, DEGRADED)) {
>   			free_extent_map(em);
> @@ -7149,6 +7172,7 @@ static struct btrfs_fs_devices *open_seed_devices(struct btrfs_fs_info *fs_info,
>   static int read_one_dev(struct extent_buffer *leaf,
>   			struct btrfs_dev_item *dev_item)
>   {
> +	BTRFS_DEV_LOOKUP_ARGS(args);
>   	struct btrfs_fs_info *fs_info = leaf->fs_info;
>   	struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
>   	struct btrfs_device *device;
> @@ -7157,11 +7181,13 @@ static int read_one_dev(struct extent_buffer *leaf,
>   	u8 fs_uuid[BTRFS_FSID_SIZE];
>   	u8 dev_uuid[BTRFS_UUID_SIZE];
>   
> -	devid = btrfs_device_id(leaf, dev_item);
> +	args.devid = btrfs_device_id(leaf, dev_item);
>   	read_extent_buffer(leaf, dev_uuid, btrfs_device_uuid(dev_item),
>   			   BTRFS_UUID_SIZE);
>   	read_extent_buffer(leaf, fs_uuid, btrfs_device_fsid(dev_item),
>   			   BTRFS_FSID_SIZE);
> +	args.uuid = dev_uuid;
> +	args.fsid = fs_uuid;
>   
>   	if (memcmp(fs_uuid, fs_devices->metadata_uuid, BTRFS_FSID_SIZE)) {
>   		fs_devices = open_seed_devices(fs_info, fs_uuid);
> @@ -7169,8 +7195,7 @@ static int read_one_dev(struct extent_buffer *leaf,
>   			return PTR_ERR(fs_devices);
>   	}
>   
> -	device = btrfs_find_device(fs_info->fs_devices, devid, dev_uuid,
> -				   fs_uuid);
> +	device = btrfs_find_device(fs_info->fs_devices, &args);
>   	if (!device) {
>   		if (!btrfs_test_opt(fs_info, DEGRADED)) {
>   			btrfs_report_missing_device(fs_info, devid,
> @@ -7839,12 +7864,14 @@ static void btrfs_dev_stat_print_on_load(struct btrfs_device *dev)
>   int btrfs_get_dev_stats(struct btrfs_fs_info *fs_info,
>   			struct btrfs_ioctl_get_dev_stats *stats)
>   {
> +	BTRFS_DEV_LOOKUP_ARGS(args);
>   	struct btrfs_device *dev;
>   	struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
>   	int i;
>   
>   	mutex_lock(&fs_devices->device_list_mutex);
> -	dev = btrfs_find_device(fs_info->fs_devices, stats->devid, NULL, NULL);
> +	args.devid = stats->devid;
> +	dev = btrfs_find_device(fs_info->fs_devices, &args);
>   	mutex_unlock(&fs_devices->device_list_mutex);
>   
>   	if (!dev) {
> @@ -7920,6 +7947,7 @@ static int verify_one_dev_extent(struct btrfs_fs_info *fs_info,
>   				 u64 chunk_offset, u64 devid,
>   				 u64 physical_offset, u64 physical_len)
>   {
> +	struct btrfs_dev_lookup_args args = { .devid = devid };
>   	struct extent_map_tree *em_tree = &fs_info->mapping_tree;
>   	struct extent_map *em;
>   	struct map_lookup *map;
> @@ -7975,7 +8003,7 @@ static int verify_one_dev_extent(struct btrfs_fs_info *fs_info,
>   	}
>   
>   	/* Make sure no dev extent is beyond device boundary */
> -	dev = btrfs_find_device(fs_info->fs_devices, devid, NULL, NULL);
> +	dev = btrfs_find_device(fs_info->fs_devices, &args);
>   	if (!dev) {
>   		btrfs_err(fs_info, "failed to find devid %llu", devid);
>   		ret = -EUCLEAN;
> diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
> index c7ac43d8a7e8..fa9a56c37d45 100644
> --- a/fs/btrfs/volumes.h
> +++ b/fs/btrfs/volumes.h
> @@ -452,6 +452,19 @@ struct btrfs_balance_control {
>   	struct btrfs_balance_progress stat;
>   };
>   
> +struct btrfs_dev_lookup_args {
> +	u64 devid;
> +	u8 *uuid;
> +	u8 *fsid;
> +	bool missing;
> +};
> +
> +/* We have to init to -1 because BTRFS_DEV_REPLACE_DEVID is 0 */
> +#define BTRFS_DEV_LOOKUP_ARGS_INIT { .devid = (u64)-1 }
> +
> +#define BTRFS_DEV_LOOKUP_ARGS(name) \
> +	struct btrfs_dev_lookup_args name = BTRFS_DEV_LOOKUP_ARGS_INIT
> +
>   enum btrfs_map_op {
>   	BTRFS_MAP_READ,
>   	BTRFS_MAP_WRITE,
> @@ -517,7 +530,7 @@ int btrfs_num_copies(struct btrfs_fs_info *fs_info, u64 logical, u64 len);
>   int btrfs_grow_device(struct btrfs_trans_handle *trans,
>   		      struct btrfs_device *device, u64 new_size);
>   struct btrfs_device *btrfs_find_device(struct btrfs_fs_devices *fs_devices,
> -				       u64 devid, u8 *uuid, u8 *fsid);
> +				       struct btrfs_dev_lookup_args *args);
>   int btrfs_shrink_device(struct btrfs_device *device, u64 new_size);
>   int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *path);
>   int btrfs_balance(struct btrfs_fs_info *fs_info,
>
Anand Jain Oct. 5, 2021, 5:25 a.m. UTC | #2
On 05/10/2021 12:48, Anand Jain wrote:
> On 05/10/2021 01:19, Josef Bacik wrote:
>> We have a lot of device lookup functions that all do something slightly
>> different.
> 
>>  Clean this up by adding a struct to hold the different
>> lookup criteria, and then pass this around to btrfs_find_device() so it
>> can do the proper matching based on the lookup criteria.
> 
>   It is better now.
> 
>> Signed-off-by: Josef Bacik <josef@toxicpanda.com>
> 
>   Looks good.
> 
>   Reviewed-by: Anand Jain <anand.jain@oracle.com>
> 
> Thanks, Anand
> 
> 
>> ---
>>   fs/btrfs/dev-replace.c |  18 +++----
>>   fs/btrfs/ioctl.c       |  13 ++---
>>   fs/btrfs/scrub.c       |   6 ++-
>>   fs/btrfs/volumes.c     | 120 +++++++++++++++++++++++++----------------
>>   fs/btrfs/volumes.h     |  15 +++++-
>>   5 files changed, 108 insertions(+), 64 deletions(-)
>>
>> diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c
>> index d029be40ea6f..ff25da2dbd59 100644
>> --- a/fs/btrfs/dev-replace.c
>> +++ b/fs/btrfs/dev-replace.c
>> @@ -70,6 +70,7 @@ static int btrfs_dev_replace_kthread(void *data);
>>   int btrfs_init_dev_replace(struct btrfs_fs_info *fs_info)
>>   {
>> +    BTRFS_DEV_LOOKUP_ARGS(args);
>>       struct btrfs_key key;
>>       struct btrfs_root *dev_root = fs_info->dev_root;
>>       struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;
>> @@ -84,6 +85,8 @@ int btrfs_init_dev_replace(struct btrfs_fs_info 
>> *fs_info)
>>       if (!dev_root)
>>           return 0;
>> +    args.devid = BTRFS_DEV_REPLACE_DEVID;
>> +
>>       path = btrfs_alloc_path();
>>       if (!path) {
>>           ret = -ENOMEM;
>> @@ -100,8 +103,7 @@ int btrfs_init_dev_replace(struct btrfs_fs_info 
>> *fs_info)
>>            * We don't have a replace item or it's corrupted.  If there is
>>            * a replace target, fail the mount.
>>            */
>> -        if (btrfs_find_device(fs_info->fs_devices,
>> -                      BTRFS_DEV_REPLACE_DEVID, NULL, NULL)) {
>> +        if (btrfs_find_device(fs_info->fs_devices, &args)) {
>>               btrfs_err(fs_info,
>>               "found replace target device without a valid replace 
>> item");
>>               ret = -EUCLEAN;
>> @@ -163,8 +165,7 @@ int btrfs_init_dev_replace(struct btrfs_fs_info 
>> *fs_info)
>>            * We don't have an active replace item but if there is a
>>            * replace target, fail the mount.
>>            */
>> -        if (btrfs_find_device(fs_info->fs_devices,
>> -                      BTRFS_DEV_REPLACE_DEVID, NULL, NULL)) {
>> +        if (btrfs_find_device(fs_info->fs_devices, &args)) {
>>               btrfs_err(fs_info,
>>               "replace devid present without an active replace item");
>>               ret = -EUCLEAN;
>> @@ -175,11 +176,10 @@ int btrfs_init_dev_replace(struct btrfs_fs_info 
>> *fs_info)
>>           break;
>>       case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED:
>>       case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED:
>> -        dev_replace->srcdev = btrfs_find_device(fs_info->fs_devices,
>> -                        src_devid, NULL, NULL);
>> -        dev_replace->tgtdev = btrfs_find_device(fs_info->fs_devices,
>> -                            BTRFS_DEV_REPLACE_DEVID,
>> -                            NULL, NULL);
>> +        dev_replace->tgtdev = btrfs_find_device(fs_info->fs_devices, 
>> &args);
>> +        args.devid = src_devid;
>> +        dev_replace->srcdev = btrfs_find_device(fs_info->fs_devices, 
>> &args);
>> +
>>           /*
>>            * allow 'btrfs dev replace_cancel' if src/tgt device is
>>            * missing
>> diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
>> index 9eb0c1eb568e..b8508af4e539 100644
>> --- a/fs/btrfs/ioctl.c
>> +++ b/fs/btrfs/ioctl.c
>> @@ -1602,6 +1602,7 @@ static int exclop_start_or_cancel_reloc(struct 
>> btrfs_fs_info *fs_info,
>>   static noinline int btrfs_ioctl_resize(struct file *file,
>>                       void __user *arg)
>>   {
>> +    BTRFS_DEV_LOOKUP_ARGS(args);
>>       struct inode *inode = file_inode(file);
>>       struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
>>       u64 new_size;
>> @@ -1657,7 +1658,8 @@ static noinline int btrfs_ioctl_resize(struct 
>> file *file,
>>           btrfs_info(fs_info, "resizing devid %llu", devid);
>>       }
>> -    device = btrfs_find_device(fs_info->fs_devices, devid, NULL, NULL);
>> +    args.devid = devid;
>> +    device = btrfs_find_device(fs_info->fs_devices, &args);
>>       if (!device) {
>>           btrfs_info(fs_info, "resizer unable to find device %llu",
>>                  devid);
>> @@ -3317,22 +3319,21 @@ static long btrfs_ioctl_fs_info(struct 
>> btrfs_fs_info *fs_info,
>>   static long btrfs_ioctl_dev_info(struct btrfs_fs_info *fs_info,
>>                    void __user *arg)
>>   {
>> +    BTRFS_DEV_LOOKUP_ARGS(args);
>>       struct btrfs_ioctl_dev_info_args *di_args;
>>       struct btrfs_device *dev;
>>       int ret = 0;
>> -    char *s_uuid = NULL;
>>       di_args = memdup_user(arg, sizeof(*di_args));
>>       if (IS_ERR(di_args))
>>           return PTR_ERR(di_args);
>> +    args.devid = di_args->devid;
>>       if (!btrfs_is_empty_uuid(di_args->uuid))
>> -        s_uuid = di_args->uuid;
>> +        args.uuid = di_args->uuid;
>>       rcu_read_lock();
>> -    dev = btrfs_find_device(fs_info->fs_devices, di_args->devid, s_uuid,
>> -                NULL);
>> -
>> +    dev = btrfs_find_device(fs_info->fs_devices, &args);
>>       if (!dev) {
>>           ret = -ENODEV;
>>           goto out;
>> diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
>> index bd3cd7427391..1e29b9aa45df 100644
>> --- a/fs/btrfs/scrub.c
>> +++ b/fs/btrfs/scrub.c
>> @@ -4067,6 +4067,7 @@ int btrfs_scrub_dev(struct btrfs_fs_info 
>> *fs_info, u64 devid, u64 start,
>>               u64 end, struct btrfs_scrub_progress *progress,
>>               int readonly, int is_dev_replace)
>>   {
>> +    struct btrfs_dev_lookup_args args = { .devid = devid };
> 
>>       struct scrub_ctx *sctx;
>>       int ret;
>>       struct btrfs_device *dev;
>> @@ -4114,7 +4115,7 @@ int btrfs_scrub_dev(struct btrfs_fs_info 
>> *fs_info, u64 devid, u64 start,
>>           goto out_free_ctx;
>>       mutex_lock(&fs_info->fs_devices->device_list_mutex);
>> -    dev = btrfs_find_device(fs_info->fs_devices, devid, NULL, NULL);
>> +    dev = btrfs_find_device(fs_info->fs_devices, &args);
>>       if (!dev || (test_bit(BTRFS_DEV_STATE_MISSING, &dev->dev_state) &&
>>                !is_dev_replace)) {
>>           mutex_unlock(&fs_info->fs_devices->device_list_mutex);
>> @@ -4287,11 +4288,12 @@ int btrfs_scrub_cancel_dev(struct btrfs_device 
>> *dev)
>>   int btrfs_scrub_progress(struct btrfs_fs_info *fs_info, u64 devid,
>>                struct btrfs_scrub_progress *progress)
>>   {
>> +    struct btrfs_dev_lookup_args args = { .devid = devid };
> 
> 
>>       struct btrfs_device *dev;
>>       struct scrub_ctx *sctx = NULL;
>>       mutex_lock(&fs_info->fs_devices->device_list_mutex);
>> -    dev = btrfs_find_device(fs_info->fs_devices, devid, NULL, NULL);
>> +    dev = btrfs_find_device(fs_info->fs_devices, &args);
>>       if (dev)
>>           sctx = dev->scrub_ctx;
>>       if (sctx)
>> diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
>> index 5f19d0863094..191360e44a20 100644
>> --- a/fs/btrfs/volumes.c
>> +++ b/fs/btrfs/volumes.c
>> @@ -812,9 +812,13 @@ static noinline struct btrfs_device 
>> *device_list_add(const char *path,
>>           device = NULL;
>>       } else {
>> +        struct btrfs_dev_lookup_args args = {
>> +            .devid = devid,
>> +            .uuid = disk_super->dev_item.uuid,
>> +        };
>> +
>>           mutex_lock(&fs_devices->device_list_mutex);
>> -        device = btrfs_find_device(fs_devices, devid,
>> -                disk_super->dev_item.uuid, NULL);
>> +        device = btrfs_find_device(fs_devices, &args);
>>           /*
>>            * If this disk has been pulled into an fs devices created by
>> @@ -2323,10 +2327,9 @@ void btrfs_destroy_dev_replace_tgtdev(struct 
>> btrfs_device *tgtdev)
>>   static struct btrfs_device *btrfs_find_device_by_path(
>>           struct btrfs_fs_info *fs_info, const char *device_path)
>>   {
>> +    BTRFS_DEV_LOOKUP_ARGS(args);
>>       int ret = 0;
>>       struct btrfs_super_block *disk_super;
>> -    u64 devid;
>> -    u8 *dev_uuid;
>>       struct block_device *bdev;
>>       struct btrfs_device *device;
>> @@ -2335,14 +2338,14 @@ static struct btrfs_device 
>> *btrfs_find_device_by_path(
>>       if (ret)
>>           return ERR_PTR(ret);
>> -    devid = btrfs_stack_device_id(&disk_super->dev_item);
>> -    dev_uuid = disk_super->dev_item.uuid;
>> +    args.devid = btrfs_stack_device_id(&disk_super->dev_item);
>> +    args.uuid = disk_super->dev_item.uuid;
>>       if (btrfs_fs_incompat(fs_info, METADATA_UUID))
>> -        device = btrfs_find_device(fs_info->fs_devices, devid, dev_uuid,
>> -                       disk_super->metadata_uuid);
>> +        args.fsid = disk_super->metadata_uuid;
>>       else
>> -        device = btrfs_find_device(fs_info->fs_devices, devid, dev_uuid,
>> -                       disk_super->fsid);
>> +        args.fsid = disk_super->fsid;
>> +
>> +    device = btrfs_find_device(fs_info->fs_devices, &args);
>>       btrfs_release_disk_super(disk_super);
>>       if (!device)
>> @@ -2358,11 +2361,12 @@ 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;
>>       if (devid) {
>> -        device = btrfs_find_device(fs_info->fs_devices, devid, NULL,
>> -                       NULL);
>> +        args.devid = devid;
>> +        device = btrfs_find_device(fs_info->fs_devices, &args);
>>           if (!device)
>>               return ERR_PTR(-ENOENT);
>>           return device;
>> @@ -2372,14 +2376,11 @@ struct btrfs_device 
>> *btrfs_find_device_by_devspec(
>>           return ERR_PTR(-EINVAL);
>>       if (strcmp(device_path, "missing") == 0) {
>> -        /* Find first missing device */
>> -        list_for_each_entry(device, &fs_info->fs_devices->devices,
>> -                    dev_list) {
>> -            if (test_bit(BTRFS_DEV_STATE_IN_FS_METADATA,
>> -                     &device->dev_state) && !device->bdev)
>> -                return device;
>> -        }
>> -        return ERR_PTR(-ENOENT);
>> +        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);
>> @@ -2459,6 +2460,7 @@ static int btrfs_prepare_sprout(struct 
>> btrfs_fs_info *fs_info)
>>    */
>>   static int btrfs_finish_sprout(struct btrfs_trans_handle *trans)
>>   {
>> +    BTRFS_DEV_LOOKUP_ARGS(args);
>>       struct btrfs_fs_info *fs_info = trans->fs_info;
>>       struct btrfs_root *root = fs_info->chunk_root;
>>       struct btrfs_path *path;
>> @@ -2468,7 +2470,6 @@ static int btrfs_finish_sprout(struct 
>> btrfs_trans_handle *trans)
>>       struct btrfs_key key;
>>       u8 fs_uuid[BTRFS_FSID_SIZE];
>>       u8 dev_uuid[BTRFS_UUID_SIZE];
>> -    u64 devid;
>>       int ret;
>>       path = btrfs_alloc_path();
>> @@ -2505,13 +2506,14 @@ static int btrfs_finish_sprout(struct 
>> btrfs_trans_handle *trans)
>>           dev_item = btrfs_item_ptr(leaf, path->slots[0],
>>                         struct btrfs_dev_item);
> 
>> -        devid = btrfs_device_id(leaf, dev_item);
>> +        args.devid = btrfs_device_id(leaf, dev_item);
> 
>>           read_extent_buffer(leaf, dev_uuid, btrfs_device_uuid(dev_item),
>>                      BTRFS_UUID_SIZE);
>>           read_extent_buffer(leaf, fs_uuid, btrfs_device_fsid(dev_item),
>>                      BTRFS_FSID_SIZE);
>> -        device = btrfs_find_device(fs_info->fs_devices, devid, dev_uuid,
>> -                       fs_uuid);
>> +        args.uuid = dev_uuid;
>> +        args.fsid = fs_uuid;
> 
> 
> 
>> +        device = btrfs_find_device(fs_info->fs_devices, &args);
>>           BUG_ON(!device); /* Logic error */
>>           if (device->fs_devices->seeding) {
>> @@ -6753,6 +6755,32 @@ blk_status_t btrfs_map_bio(struct btrfs_fs_info 
>> *fs_info, struct bio *bio,
>>       return BLK_STS_OK;
>>   }
>> +static inline bool dev_args_match_fs_devices(struct 
>> btrfs_dev_lookup_args *args,
>> +                         struct btrfs_fs_devices *fs_devices)
>> +{
>> +    if (args->fsid == NULL)
>> +        return true;
>> +    if (!memcmp(fs_devices->metadata_uuid, args->fsid, BTRFS_FSID_SIZE))
>> +        return true;
>> +    return false;
>> +}
>> +
> 
>> +static inline bool dev_args_match_device(struct btrfs_dev_lookup_args 
>> *args,
>> +                     struct btrfs_device *device)
>> +{
>> +    ASSERT((args->devid != (u64)-1) || args->missing);
>> +    if ((args->devid != (u64)-1) && device->devid != args->devid)
>> +        return false;
>> +    if (args->uuid && memcmp(device->uuid, args->uuid, BTRFS_UUID_SIZE))
>> +        return false;
>> +    if (!args->missing)
>> +        return true;
>> +    if (test_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &device->dev_state) &&
>> +        !device->bdev)
>> +        return true;
>> +    return false;
>> +}
> 
> 
>> +
>>   /*
>>    * Find a device specified by @devid or @uuid in the list of 
>> @fs_devices, or
>>    * return NULL.
>> @@ -6761,30 +6789,24 @@ blk_status_t btrfs_map_bio(struct 
>> btrfs_fs_info *fs_info, struct bio *bio,
>>    * only devid is used.
>>    */
>>   struct btrfs_device *btrfs_find_device(struct btrfs_fs_devices 
>> *fs_devices,
>> -                       u64 devid, u8 *uuid, u8 *fsid)
>> +                       struct btrfs_dev_lookup_args *args)
>>   {
>>       struct btrfs_device *device;
>>       struct btrfs_fs_devices *seed_devs;
>> -    if (!fsid || !memcmp(fs_devices->metadata_uuid, fsid, 
>> BTRFS_FSID_SIZE)) {
>> +    if (dev_args_match_fs_devices(args, fs_devices)) {
>>           list_for_each_entry(device, &fs_devices->devices, dev_list) {
>> -            if (device->devid == devid &&
>> -                (!uuid || memcmp(device->uuid, uuid,
>> -                         BTRFS_UUID_SIZE) == 0))
>> +            if (dev_args_match_device(args, device))
>>                   return device;
>>           }
>>       }
>>       list_for_each_entry(seed_devs, &fs_devices->seed_list, seed_list) {
>> -        if (!fsid ||
>> -            !memcmp(seed_devs->metadata_uuid, fsid, BTRFS_FSID_SIZE)) {
>> -            list_for_each_entry(device, &seed_devs->devices,
>> -                        dev_list) {
>> -                if (device->devid == devid &&
>> -                    (!uuid || memcmp(device->uuid, uuid,
>> -                             BTRFS_UUID_SIZE) == 0))
>> -                    return device;
>> -            }
>> +        if (!dev_args_match_fs_devices(args, seed_devs))
>> +            continue;
>> +        list_for_each_entry(device, &seed_devs->devices, dev_list) {
>> +            if (dev_args_match_device(args, device))
>> +                return device;
>>           }
>>       }
>> @@ -6950,6 +6972,7 @@ static void warn_32bit_meta_chunk(struct 
>> btrfs_fs_info *fs_info,
>>   static int read_one_chunk(struct btrfs_key *key, struct 
>> extent_buffer *leaf,
>>                 struct btrfs_chunk *chunk)
>>   {
>> +    BTRFS_DEV_LOOKUP_ARGS(args);
>>       struct btrfs_fs_info *fs_info = leaf->fs_info;
>>       struct extent_map_tree *map_tree = &fs_info->mapping_tree;
>>       struct map_lookup *map;
>> @@ -7026,12 +7049,12 @@ static int read_one_chunk(struct btrfs_key 
>> *key, struct extent_buffer *leaf,
>>       for (i = 0; i < num_stripes; i++) {
>>           map->stripes[i].physical =
>>               btrfs_stripe_offset_nr(leaf, chunk, i);
>> -        devid = btrfs_stripe_devid_nr(leaf, chunk, i);

  We need devid to initialize here for local use.
  This fix is in the path 5/6. However, it should move here.


>> +        args.devid = btrfs_stripe_devid_nr(leaf, chunk, i);
>>           read_extent_buffer(leaf, uuid, (unsigned long)
>>                      btrfs_stripe_dev_uuid_nr(chunk, i),
>>                      BTRFS_UUID_SIZE);
>> -        map->stripes[i].dev = btrfs_find_device(fs_info->fs_devices,
>> -                            devid, uuid, NULL);
>> +        args.uuid = uuid;
>> +        map->stripes[i].dev = btrfs_find_device(fs_info->fs_devices, 
>> &args);
>>           if (!map->stripes[i].dev &&
>>               !btrfs_test_opt(fs_info, DEGRADED)) {
>>               free_extent_map(em);
>> @@ -7149,6 +7172,7 @@ static struct btrfs_fs_devices 
>> *open_seed_devices(struct btrfs_fs_info *fs_info,
>>   static int read_one_dev(struct extent_buffer *leaf,
>>               struct btrfs_dev_item *dev_item)
>>   {
>> +    BTRFS_DEV_LOOKUP_ARGS(args);
>>       struct btrfs_fs_info *fs_info = leaf->fs_info;
>>       struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
>>       struct btrfs_device *device;
>> @@ -7157,11 +7181,13 @@ static int read_one_dev(struct extent_buffer 
>> *leaf,
>>       u8 fs_uuid[BTRFS_FSID_SIZE];
>>       u8 dev_uuid[BTRFS_UUID_SIZE];
>> -    devid = btrfs_device_id(leaf, dev_item);

  We need devid to initialize here for local use.
  This fix is in the path 5/6. However, it should move here.

Thanks, Anand


>> +    args.devid = btrfs_device_id(leaf, dev_item);
>>       read_extent_buffer(leaf, dev_uuid, btrfs_device_uuid(dev_item),
>>                  BTRFS_UUID_SIZE);
>>       read_extent_buffer(leaf, fs_uuid, btrfs_device_fsid(dev_item),
>>                  BTRFS_FSID_SIZE);
>> +    args.uuid = dev_uuid;
>> +    args.fsid = fs_uuid;
>>       if (memcmp(fs_uuid, fs_devices->metadata_uuid, BTRFS_FSID_SIZE)) {
>>           fs_devices = open_seed_devices(fs_info, fs_uuid);
>> @@ -7169,8 +7195,7 @@ static int read_one_dev(struct extent_buffer *leaf,
>>               return PTR_ERR(fs_devices);
>>       }
>> -    device = btrfs_find_device(fs_info->fs_devices, devid, dev_uuid,
>> -                   fs_uuid);
>> +    device = btrfs_find_device(fs_info->fs_devices, &args);
>>       if (!device) {
>>           if (!btrfs_test_opt(fs_info, DEGRADED)) {
>>               btrfs_report_missing_device(fs_info, devid,
>> @@ -7839,12 +7864,14 @@ static void 
>> btrfs_dev_stat_print_on_load(struct btrfs_device *dev)
>>   int btrfs_get_dev_stats(struct btrfs_fs_info *fs_info,
>>               struct btrfs_ioctl_get_dev_stats *stats)
>>   {
>> +    BTRFS_DEV_LOOKUP_ARGS(args);
>>       struct btrfs_device *dev;
>>       struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
>>       int i;
>>       mutex_lock(&fs_devices->device_list_mutex);
>> -    dev = btrfs_find_device(fs_info->fs_devices, stats->devid, NULL, 
>> NULL);
>> +    args.devid = stats->devid;
>> +    dev = btrfs_find_device(fs_info->fs_devices, &args);
>>       mutex_unlock(&fs_devices->device_list_mutex);
>>       if (!dev) {
>> @@ -7920,6 +7947,7 @@ static int verify_one_dev_extent(struct 
>> btrfs_fs_info *fs_info,
>>                    u64 chunk_offset, u64 devid,
>>                    u64 physical_offset, u64 physical_len)
>>   {
>> +    struct btrfs_dev_lookup_args args = { .devid = devid };
>>       struct extent_map_tree *em_tree = &fs_info->mapping_tree;
>>       struct extent_map *em;
>>       struct map_lookup *map;
>> @@ -7975,7 +8003,7 @@ static int verify_one_dev_extent(struct 
>> btrfs_fs_info *fs_info,
>>       }
>>       /* Make sure no dev extent is beyond device boundary */
>> -    dev = btrfs_find_device(fs_info->fs_devices, devid, NULL, NULL);
>> +    dev = btrfs_find_device(fs_info->fs_devices, &args);
>>       if (!dev) {
>>           btrfs_err(fs_info, "failed to find devid %llu", devid);
>>           ret = -EUCLEAN;
>> diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
>> index c7ac43d8a7e8..fa9a56c37d45 100644
>> --- a/fs/btrfs/volumes.h
>> +++ b/fs/btrfs/volumes.h
>> @@ -452,6 +452,19 @@ struct btrfs_balance_control {
>>       struct btrfs_balance_progress stat;
>>   };
>> +struct btrfs_dev_lookup_args {
>> +    u64 devid;
>> +    u8 *uuid;
>> +    u8 *fsid;
>> +    bool missing;
>> +};
>> +
>> +/* We have to init to -1 because BTRFS_DEV_REPLACE_DEVID is 0 */
>> +#define BTRFS_DEV_LOOKUP_ARGS_INIT { .devid = (u64)-1 }
>> +
>> +#define BTRFS_DEV_LOOKUP_ARGS(name) \
>> +    struct btrfs_dev_lookup_args name = BTRFS_DEV_LOOKUP_ARGS_INIT
>> +
>>   enum btrfs_map_op {
>>       BTRFS_MAP_READ,
>>       BTRFS_MAP_WRITE,
>> @@ -517,7 +530,7 @@ int btrfs_num_copies(struct btrfs_fs_info 
>> *fs_info, u64 logical, u64 len);
>>   int btrfs_grow_device(struct btrfs_trans_handle *trans,
>>                 struct btrfs_device *device, u64 new_size);
>>   struct btrfs_device *btrfs_find_device(struct btrfs_fs_devices 
>> *fs_devices,
>> -                       u64 devid, u8 *uuid, u8 *fsid);
>> +                       struct btrfs_dev_lookup_args *args);
>>   int btrfs_shrink_device(struct btrfs_device *device, u64 new_size);
>>   int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char 
>> *path);
>>   int btrfs_balance(struct btrfs_fs_info *fs_info,
>>
>
diff mbox series

Patch

diff --git a/fs/btrfs/dev-replace.c b/fs/btrfs/dev-replace.c
index d029be40ea6f..ff25da2dbd59 100644
--- a/fs/btrfs/dev-replace.c
+++ b/fs/btrfs/dev-replace.c
@@ -70,6 +70,7 @@  static int btrfs_dev_replace_kthread(void *data);
 
 int btrfs_init_dev_replace(struct btrfs_fs_info *fs_info)
 {
+	BTRFS_DEV_LOOKUP_ARGS(args);
 	struct btrfs_key key;
 	struct btrfs_root *dev_root = fs_info->dev_root;
 	struct btrfs_dev_replace *dev_replace = &fs_info->dev_replace;
@@ -84,6 +85,8 @@  int btrfs_init_dev_replace(struct btrfs_fs_info *fs_info)
 	if (!dev_root)
 		return 0;
 
+	args.devid = BTRFS_DEV_REPLACE_DEVID;
+
 	path = btrfs_alloc_path();
 	if (!path) {
 		ret = -ENOMEM;
@@ -100,8 +103,7 @@  int btrfs_init_dev_replace(struct btrfs_fs_info *fs_info)
 		 * We don't have a replace item or it's corrupted.  If there is
 		 * a replace target, fail the mount.
 		 */
-		if (btrfs_find_device(fs_info->fs_devices,
-				      BTRFS_DEV_REPLACE_DEVID, NULL, NULL)) {
+		if (btrfs_find_device(fs_info->fs_devices, &args)) {
 			btrfs_err(fs_info,
 			"found replace target device without a valid replace item");
 			ret = -EUCLEAN;
@@ -163,8 +165,7 @@  int btrfs_init_dev_replace(struct btrfs_fs_info *fs_info)
 		 * We don't have an active replace item but if there is a
 		 * replace target, fail the mount.
 		 */
-		if (btrfs_find_device(fs_info->fs_devices,
-				      BTRFS_DEV_REPLACE_DEVID, NULL, NULL)) {
+		if (btrfs_find_device(fs_info->fs_devices, &args)) {
 			btrfs_err(fs_info,
 			"replace devid present without an active replace item");
 			ret = -EUCLEAN;
@@ -175,11 +176,10 @@  int btrfs_init_dev_replace(struct btrfs_fs_info *fs_info)
 		break;
 	case BTRFS_IOCTL_DEV_REPLACE_STATE_STARTED:
 	case BTRFS_IOCTL_DEV_REPLACE_STATE_SUSPENDED:
-		dev_replace->srcdev = btrfs_find_device(fs_info->fs_devices,
-						src_devid, NULL, NULL);
-		dev_replace->tgtdev = btrfs_find_device(fs_info->fs_devices,
-							BTRFS_DEV_REPLACE_DEVID,
-							NULL, NULL);
+		dev_replace->tgtdev = btrfs_find_device(fs_info->fs_devices, &args);
+		args.devid = src_devid;
+		dev_replace->srcdev = btrfs_find_device(fs_info->fs_devices, &args);
+
 		/*
 		 * allow 'btrfs dev replace_cancel' if src/tgt device is
 		 * missing
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 9eb0c1eb568e..b8508af4e539 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -1602,6 +1602,7 @@  static int exclop_start_or_cancel_reloc(struct btrfs_fs_info *fs_info,
 static noinline int btrfs_ioctl_resize(struct file *file,
 					void __user *arg)
 {
+	BTRFS_DEV_LOOKUP_ARGS(args);
 	struct inode *inode = file_inode(file);
 	struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
 	u64 new_size;
@@ -1657,7 +1658,8 @@  static noinline int btrfs_ioctl_resize(struct file *file,
 		btrfs_info(fs_info, "resizing devid %llu", devid);
 	}
 
-	device = btrfs_find_device(fs_info->fs_devices, devid, NULL, NULL);
+	args.devid = devid;
+	device = btrfs_find_device(fs_info->fs_devices, &args);
 	if (!device) {
 		btrfs_info(fs_info, "resizer unable to find device %llu",
 			   devid);
@@ -3317,22 +3319,21 @@  static long btrfs_ioctl_fs_info(struct btrfs_fs_info *fs_info,
 static long btrfs_ioctl_dev_info(struct btrfs_fs_info *fs_info,
 				 void __user *arg)
 {
+	BTRFS_DEV_LOOKUP_ARGS(args);
 	struct btrfs_ioctl_dev_info_args *di_args;
 	struct btrfs_device *dev;
 	int ret = 0;
-	char *s_uuid = NULL;
 
 	di_args = memdup_user(arg, sizeof(*di_args));
 	if (IS_ERR(di_args))
 		return PTR_ERR(di_args);
 
+	args.devid = di_args->devid;
 	if (!btrfs_is_empty_uuid(di_args->uuid))
-		s_uuid = di_args->uuid;
+		args.uuid = di_args->uuid;
 
 	rcu_read_lock();
-	dev = btrfs_find_device(fs_info->fs_devices, di_args->devid, s_uuid,
-				NULL);
-
+	dev = btrfs_find_device(fs_info->fs_devices, &args);
 	if (!dev) {
 		ret = -ENODEV;
 		goto out;
diff --git a/fs/btrfs/scrub.c b/fs/btrfs/scrub.c
index bd3cd7427391..1e29b9aa45df 100644
--- a/fs/btrfs/scrub.c
+++ b/fs/btrfs/scrub.c
@@ -4067,6 +4067,7 @@  int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,
 		    u64 end, struct btrfs_scrub_progress *progress,
 		    int readonly, int is_dev_replace)
 {
+	struct btrfs_dev_lookup_args args = { .devid = devid };
 	struct scrub_ctx *sctx;
 	int ret;
 	struct btrfs_device *dev;
@@ -4114,7 +4115,7 @@  int btrfs_scrub_dev(struct btrfs_fs_info *fs_info, u64 devid, u64 start,
 		goto out_free_ctx;
 
 	mutex_lock(&fs_info->fs_devices->device_list_mutex);
-	dev = btrfs_find_device(fs_info->fs_devices, devid, NULL, NULL);
+	dev = btrfs_find_device(fs_info->fs_devices, &args);
 	if (!dev || (test_bit(BTRFS_DEV_STATE_MISSING, &dev->dev_state) &&
 		     !is_dev_replace)) {
 		mutex_unlock(&fs_info->fs_devices->device_list_mutex);
@@ -4287,11 +4288,12 @@  int btrfs_scrub_cancel_dev(struct btrfs_device *dev)
 int btrfs_scrub_progress(struct btrfs_fs_info *fs_info, u64 devid,
 			 struct btrfs_scrub_progress *progress)
 {
+	struct btrfs_dev_lookup_args args = { .devid = devid };
 	struct btrfs_device *dev;
 	struct scrub_ctx *sctx = NULL;
 
 	mutex_lock(&fs_info->fs_devices->device_list_mutex);
-	dev = btrfs_find_device(fs_info->fs_devices, devid, NULL, NULL);
+	dev = btrfs_find_device(fs_info->fs_devices, &args);
 	if (dev)
 		sctx = dev->scrub_ctx;
 	if (sctx)
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 5f19d0863094..191360e44a20 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -812,9 +812,13 @@  static noinline struct btrfs_device *device_list_add(const char *path,
 
 		device = NULL;
 	} else {
+		struct btrfs_dev_lookup_args args = {
+			.devid = devid,
+			.uuid = disk_super->dev_item.uuid,
+		};
+
 		mutex_lock(&fs_devices->device_list_mutex);
-		device = btrfs_find_device(fs_devices, devid,
-				disk_super->dev_item.uuid, NULL);
+		device = btrfs_find_device(fs_devices, &args);
 
 		/*
 		 * If this disk has been pulled into an fs devices created by
@@ -2323,10 +2327,9 @@  void btrfs_destroy_dev_replace_tgtdev(struct btrfs_device *tgtdev)
 static struct btrfs_device *btrfs_find_device_by_path(
 		struct btrfs_fs_info *fs_info, const char *device_path)
 {
+	BTRFS_DEV_LOOKUP_ARGS(args);
 	int ret = 0;
 	struct btrfs_super_block *disk_super;
-	u64 devid;
-	u8 *dev_uuid;
 	struct block_device *bdev;
 	struct btrfs_device *device;
 
@@ -2335,14 +2338,14 @@  static struct btrfs_device *btrfs_find_device_by_path(
 	if (ret)
 		return ERR_PTR(ret);
 
-	devid = btrfs_stack_device_id(&disk_super->dev_item);
-	dev_uuid = disk_super->dev_item.uuid;
+	args.devid = btrfs_stack_device_id(&disk_super->dev_item);
+	args.uuid = disk_super->dev_item.uuid;
 	if (btrfs_fs_incompat(fs_info, METADATA_UUID))
-		device = btrfs_find_device(fs_info->fs_devices, devid, dev_uuid,
-					   disk_super->metadata_uuid);
+		args.fsid = disk_super->metadata_uuid;
 	else
-		device = btrfs_find_device(fs_info->fs_devices, devid, dev_uuid,
-					   disk_super->fsid);
+		args.fsid = disk_super->fsid;
+
+	device = btrfs_find_device(fs_info->fs_devices, &args);
 
 	btrfs_release_disk_super(disk_super);
 	if (!device)
@@ -2358,11 +2361,12 @@  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;
 
 	if (devid) {
-		device = btrfs_find_device(fs_info->fs_devices, devid, NULL,
-					   NULL);
+		args.devid = devid;
+		device = btrfs_find_device(fs_info->fs_devices, &args);
 		if (!device)
 			return ERR_PTR(-ENOENT);
 		return device;
@@ -2372,14 +2376,11 @@  struct btrfs_device *btrfs_find_device_by_devspec(
 		return ERR_PTR(-EINVAL);
 
 	if (strcmp(device_path, "missing") == 0) {
-		/* Find first missing device */
-		list_for_each_entry(device, &fs_info->fs_devices->devices,
-				    dev_list) {
-			if (test_bit(BTRFS_DEV_STATE_IN_FS_METADATA,
-				     &device->dev_state) && !device->bdev)
-				return device;
-		}
-		return ERR_PTR(-ENOENT);
+		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);
@@ -2459,6 +2460,7 @@  static int btrfs_prepare_sprout(struct btrfs_fs_info *fs_info)
  */
 static int btrfs_finish_sprout(struct btrfs_trans_handle *trans)
 {
+	BTRFS_DEV_LOOKUP_ARGS(args);
 	struct btrfs_fs_info *fs_info = trans->fs_info;
 	struct btrfs_root *root = fs_info->chunk_root;
 	struct btrfs_path *path;
@@ -2468,7 +2470,6 @@  static int btrfs_finish_sprout(struct btrfs_trans_handle *trans)
 	struct btrfs_key key;
 	u8 fs_uuid[BTRFS_FSID_SIZE];
 	u8 dev_uuid[BTRFS_UUID_SIZE];
-	u64 devid;
 	int ret;
 
 	path = btrfs_alloc_path();
@@ -2505,13 +2506,14 @@  static int btrfs_finish_sprout(struct btrfs_trans_handle *trans)
 
 		dev_item = btrfs_item_ptr(leaf, path->slots[0],
 					  struct btrfs_dev_item);
-		devid = btrfs_device_id(leaf, dev_item);
+		args.devid = btrfs_device_id(leaf, dev_item);
 		read_extent_buffer(leaf, dev_uuid, btrfs_device_uuid(dev_item),
 				   BTRFS_UUID_SIZE);
 		read_extent_buffer(leaf, fs_uuid, btrfs_device_fsid(dev_item),
 				   BTRFS_FSID_SIZE);
-		device = btrfs_find_device(fs_info->fs_devices, devid, dev_uuid,
-					   fs_uuid);
+		args.uuid = dev_uuid;
+		args.fsid = fs_uuid;
+		device = btrfs_find_device(fs_info->fs_devices, &args);
 		BUG_ON(!device); /* Logic error */
 
 		if (device->fs_devices->seeding) {
@@ -6753,6 +6755,32 @@  blk_status_t btrfs_map_bio(struct btrfs_fs_info *fs_info, struct bio *bio,
 	return BLK_STS_OK;
 }
 
+static inline bool dev_args_match_fs_devices(struct btrfs_dev_lookup_args *args,
+					     struct btrfs_fs_devices *fs_devices)
+{
+	if (args->fsid == NULL)
+		return true;
+	if (!memcmp(fs_devices->metadata_uuid, args->fsid, BTRFS_FSID_SIZE))
+		return true;
+	return false;
+}
+
+static inline bool dev_args_match_device(struct btrfs_dev_lookup_args *args,
+					 struct btrfs_device *device)
+{
+	ASSERT((args->devid != (u64)-1) || args->missing);
+	if ((args->devid != (u64)-1) && device->devid != args->devid)
+		return false;
+	if (args->uuid && memcmp(device->uuid, args->uuid, BTRFS_UUID_SIZE))
+		return false;
+	if (!args->missing)
+		return true;
+	if (test_bit(BTRFS_DEV_STATE_IN_FS_METADATA, &device->dev_state) &&
+	    !device->bdev)
+		return true;
+	return false;
+}
+
 /*
  * Find a device specified by @devid or @uuid in the list of @fs_devices, or
  * return NULL.
@@ -6761,30 +6789,24 @@  blk_status_t btrfs_map_bio(struct btrfs_fs_info *fs_info, struct bio *bio,
  * only devid is used.
  */
 struct btrfs_device *btrfs_find_device(struct btrfs_fs_devices *fs_devices,
-				       u64 devid, u8 *uuid, u8 *fsid)
+				       struct btrfs_dev_lookup_args *args)
 {
 	struct btrfs_device *device;
 	struct btrfs_fs_devices *seed_devs;
 
-	if (!fsid || !memcmp(fs_devices->metadata_uuid, fsid, BTRFS_FSID_SIZE)) {
+	if (dev_args_match_fs_devices(args, fs_devices)) {
 		list_for_each_entry(device, &fs_devices->devices, dev_list) {
-			if (device->devid == devid &&
-			    (!uuid || memcmp(device->uuid, uuid,
-					     BTRFS_UUID_SIZE) == 0))
+			if (dev_args_match_device(args, device))
 				return device;
 		}
 	}
 
 	list_for_each_entry(seed_devs, &fs_devices->seed_list, seed_list) {
-		if (!fsid ||
-		    !memcmp(seed_devs->metadata_uuid, fsid, BTRFS_FSID_SIZE)) {
-			list_for_each_entry(device, &seed_devs->devices,
-					    dev_list) {
-				if (device->devid == devid &&
-				    (!uuid || memcmp(device->uuid, uuid,
-						     BTRFS_UUID_SIZE) == 0))
-					return device;
-			}
+		if (!dev_args_match_fs_devices(args, seed_devs))
+			continue;
+		list_for_each_entry(device, &seed_devs->devices, dev_list) {
+			if (dev_args_match_device(args, device))
+				return device;
 		}
 	}
 
@@ -6950,6 +6972,7 @@  static void warn_32bit_meta_chunk(struct btrfs_fs_info *fs_info,
 static int read_one_chunk(struct btrfs_key *key, struct extent_buffer *leaf,
 			  struct btrfs_chunk *chunk)
 {
+	BTRFS_DEV_LOOKUP_ARGS(args);
 	struct btrfs_fs_info *fs_info = leaf->fs_info;
 	struct extent_map_tree *map_tree = &fs_info->mapping_tree;
 	struct map_lookup *map;
@@ -7026,12 +7049,12 @@  static int read_one_chunk(struct btrfs_key *key, struct extent_buffer *leaf,
 	for (i = 0; i < num_stripes; i++) {
 		map->stripes[i].physical =
 			btrfs_stripe_offset_nr(leaf, chunk, i);
-		devid = btrfs_stripe_devid_nr(leaf, chunk, i);
+		args.devid = btrfs_stripe_devid_nr(leaf, chunk, i);
 		read_extent_buffer(leaf, uuid, (unsigned long)
 				   btrfs_stripe_dev_uuid_nr(chunk, i),
 				   BTRFS_UUID_SIZE);
-		map->stripes[i].dev = btrfs_find_device(fs_info->fs_devices,
-							devid, uuid, NULL);
+		args.uuid = uuid;
+		map->stripes[i].dev = btrfs_find_device(fs_info->fs_devices, &args);
 		if (!map->stripes[i].dev &&
 		    !btrfs_test_opt(fs_info, DEGRADED)) {
 			free_extent_map(em);
@@ -7149,6 +7172,7 @@  static struct btrfs_fs_devices *open_seed_devices(struct btrfs_fs_info *fs_info,
 static int read_one_dev(struct extent_buffer *leaf,
 			struct btrfs_dev_item *dev_item)
 {
+	BTRFS_DEV_LOOKUP_ARGS(args);
 	struct btrfs_fs_info *fs_info = leaf->fs_info;
 	struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
 	struct btrfs_device *device;
@@ -7157,11 +7181,13 @@  static int read_one_dev(struct extent_buffer *leaf,
 	u8 fs_uuid[BTRFS_FSID_SIZE];
 	u8 dev_uuid[BTRFS_UUID_SIZE];
 
-	devid = btrfs_device_id(leaf, dev_item);
+	args.devid = btrfs_device_id(leaf, dev_item);
 	read_extent_buffer(leaf, dev_uuid, btrfs_device_uuid(dev_item),
 			   BTRFS_UUID_SIZE);
 	read_extent_buffer(leaf, fs_uuid, btrfs_device_fsid(dev_item),
 			   BTRFS_FSID_SIZE);
+	args.uuid = dev_uuid;
+	args.fsid = fs_uuid;
 
 	if (memcmp(fs_uuid, fs_devices->metadata_uuid, BTRFS_FSID_SIZE)) {
 		fs_devices = open_seed_devices(fs_info, fs_uuid);
@@ -7169,8 +7195,7 @@  static int read_one_dev(struct extent_buffer *leaf,
 			return PTR_ERR(fs_devices);
 	}
 
-	device = btrfs_find_device(fs_info->fs_devices, devid, dev_uuid,
-				   fs_uuid);
+	device = btrfs_find_device(fs_info->fs_devices, &args);
 	if (!device) {
 		if (!btrfs_test_opt(fs_info, DEGRADED)) {
 			btrfs_report_missing_device(fs_info, devid,
@@ -7839,12 +7864,14 @@  static void btrfs_dev_stat_print_on_load(struct btrfs_device *dev)
 int btrfs_get_dev_stats(struct btrfs_fs_info *fs_info,
 			struct btrfs_ioctl_get_dev_stats *stats)
 {
+	BTRFS_DEV_LOOKUP_ARGS(args);
 	struct btrfs_device *dev;
 	struct btrfs_fs_devices *fs_devices = fs_info->fs_devices;
 	int i;
 
 	mutex_lock(&fs_devices->device_list_mutex);
-	dev = btrfs_find_device(fs_info->fs_devices, stats->devid, NULL, NULL);
+	args.devid = stats->devid;
+	dev = btrfs_find_device(fs_info->fs_devices, &args);
 	mutex_unlock(&fs_devices->device_list_mutex);
 
 	if (!dev) {
@@ -7920,6 +7947,7 @@  static int verify_one_dev_extent(struct btrfs_fs_info *fs_info,
 				 u64 chunk_offset, u64 devid,
 				 u64 physical_offset, u64 physical_len)
 {
+	struct btrfs_dev_lookup_args args = { .devid = devid };
 	struct extent_map_tree *em_tree = &fs_info->mapping_tree;
 	struct extent_map *em;
 	struct map_lookup *map;
@@ -7975,7 +8003,7 @@  static int verify_one_dev_extent(struct btrfs_fs_info *fs_info,
 	}
 
 	/* Make sure no dev extent is beyond device boundary */
-	dev = btrfs_find_device(fs_info->fs_devices, devid, NULL, NULL);
+	dev = btrfs_find_device(fs_info->fs_devices, &args);
 	if (!dev) {
 		btrfs_err(fs_info, "failed to find devid %llu", devid);
 		ret = -EUCLEAN;
diff --git a/fs/btrfs/volumes.h b/fs/btrfs/volumes.h
index c7ac43d8a7e8..fa9a56c37d45 100644
--- a/fs/btrfs/volumes.h
+++ b/fs/btrfs/volumes.h
@@ -452,6 +452,19 @@  struct btrfs_balance_control {
 	struct btrfs_balance_progress stat;
 };
 
+struct btrfs_dev_lookup_args {
+	u64 devid;
+	u8 *uuid;
+	u8 *fsid;
+	bool missing;
+};
+
+/* We have to init to -1 because BTRFS_DEV_REPLACE_DEVID is 0 */
+#define BTRFS_DEV_LOOKUP_ARGS_INIT { .devid = (u64)-1 }
+
+#define BTRFS_DEV_LOOKUP_ARGS(name) \
+	struct btrfs_dev_lookup_args name = BTRFS_DEV_LOOKUP_ARGS_INIT
+
 enum btrfs_map_op {
 	BTRFS_MAP_READ,
 	BTRFS_MAP_WRITE,
@@ -517,7 +530,7 @@  int btrfs_num_copies(struct btrfs_fs_info *fs_info, u64 logical, u64 len);
 int btrfs_grow_device(struct btrfs_trans_handle *trans,
 		      struct btrfs_device *device, u64 new_size);
 struct btrfs_device *btrfs_find_device(struct btrfs_fs_devices *fs_devices,
-				       u64 devid, u8 *uuid, u8 *fsid);
+				       struct btrfs_dev_lookup_args *args);
 int btrfs_shrink_device(struct btrfs_device *device, u64 new_size);
 int btrfs_init_new_device(struct btrfs_fs_info *fs_info, const char *path);
 int btrfs_balance(struct btrfs_fs_info *fs_info,