Re: [RFC ONLY 6/8] btrfs: add code to read raid extent

Josef Bacik
2022-05-16T14:55:24Z

On Mon, May 16, 2022 at 07:31:41AM -0700, Johannes Thumshirn wrote:
> Add boilerplate code to lookup the physical address from the
> raid-stripe-tree when a read on an RAID volume formatted with the
> raid-stripe-tree was attempted.
>
> Signed-off-by: Johannes Thumshirn <johannes.thumshirn@wdc.com>
> ---
> fs/btrfs/raid-stripe-tree.c | 68 +++++++++++++++++++++++++++++++++++++
> fs/btrfs/raid-stripe-tree.h | 3 ++
> fs/btrfs/volumes.c | 23 +++++++++++--
> 3 files changed, 91 insertions(+), 3 deletions(-)
>
> diff --git a/fs/btrfs/raid-stripe-tree.c b/fs/btrfs/raid-stripe-tree.c
> index 370ea68fe343..ecc8205be760 100644
> --- a/fs/btrfs/raid-stripe-tree.c
> +++ b/fs/btrfs/raid-stripe-tree.c
> @@ -1,10 +1,78 @@
> // SPDX-License-Identifier: GPL-2.0
>
> +#include <linux/btrfs_tree.h>
> +
> #include "ctree.h"
> #include "transaction.h"
> #include "disk-io.h"
> #include "raid-stripe-tree.h"
> #include "volumes.h"
> +#include "misc.h"
> +
> +int btrfs_get_raid_extent_offset(struct btrfs_fs_info *fs_info,
> + u64 logical, u64 length, u64 map_type,
> + u64 devid, u64 *physical)
> +{
> + struct btrfs_root *stripe_root = fs_info->stripe_root;
> + struct btrfs_dp_stripe *raid_stripe;
> + struct btrfs_key stripe_key;
> + struct btrfs_key found_key;
> + struct btrfs_path *path;
> + struct extent_buffer *leaf;
> + u64 offset;
> + u64 found_logical, found_length;
> + int num_stripes;
> + int slot;
> + int ret;
> + int i;
> +
> + stripe_key.objectid = logical;
> + stripe_key.type = BTRFS_RAID_STRIPE_KEY;
> + stripe_key.offset = length;
> +
> + path = btrfs_alloc_path();
> + if (!path)
> + return -ENOMEM;
> +
> + num_stripes = btrfs_bg_type_to_factor(map_type);
> +
> + ret = btrfs_search_slot_for_read(stripe_root, &stripe_key, path, 0, 0);
> + if (ret < 0) {
> + goto out;
> + }
> +
> + if (ret == 1)
> + ret = 0;
> +
> + while (1) {
> + leaf = path->nodes[0];
> + slot = path->slots[0];
> +
> + btrfs_item_key_to_cpu(leaf, &found_key, slot);
> + found_logical = found_key.objectid;
> + found_length = found_key.offset;
> +
> + if (!in_range(logical, found_logical, found_length))
> + goto next;
> + offset = logical - found_logical;
> +
> + raid_stripe = btrfs_item_ptr(leaf, slot, struct btrfs_dp_stripe);
> + for (i = 0; i < num_stripes; i++) {
> + if (btrfs_stripe_extent_devid_nr(leaf, raid_stripe, i) != devid)
> + continue;
> + *physical = btrfs_stripe_extent_offset_nr(leaf, raid_stripe, i) + offset;
> + goto out;
> + }
> +next:
> + ret = btrfs_next_item(stripe_root, path);
> + if (ret)

This will leak 1 if we don't find a stripe, probably should do EUCLEAN if we
don't have a raid stripe for this? Thanks,

Josef