Message ID | 2aa8aae2f6394b774f480d877f2701fed6fd74c4.1652711187.git.johannes.thumshirn@wdc.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | btrfs: introduce raid-stripe-tree | expand |
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
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) + break; + } +out: + btrfs_free_path(path); + + return ret; +} int btrfs_delete_raid_extent(struct btrfs_trans_handle *trans, u64 start, u64 length) diff --git a/fs/btrfs/raid-stripe-tree.h b/fs/btrfs/raid-stripe-tree.h index 766634df8601..1bfa6274eef8 100644 --- a/fs/btrfs/raid-stripe-tree.h +++ b/fs/btrfs/raid-stripe-tree.h @@ -5,6 +5,9 @@ #include "volumes.h" +int btrfs_get_raid_extent_offset(struct btrfs_fs_info *fs_info, + u64 logical, u64 length, u64 map_type, + u64 devid, u64 *physical); int btrfs_delete_raid_extent(struct btrfs_trans_handle *trans, u64 start, u64 length); void btrfs_raid_stripe_tree_fn(struct work_struct *work); diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 36acef2ae5d8..38329728425c 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -6559,11 +6559,29 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, ret = -ENOMEM; goto out; } + bioc->map_type = map->type; for (i = 0; i < num_stripes; i++) { - bioc->stripes[i].physical = map->stripes[stripe_index].physical + - stripe_offset + stripe_nr * map->stripe_len; + u64 physical; + bioc->stripes[i].dev = map->stripes[stripe_index].dev; + + if (fs_info->stripe_root && op == BTRFS_MAP_READ && + btrfs_need_stripe_tree_update(bioc)) { + ret = btrfs_get_raid_extent_offset(fs_info, logical, + map->stripe_len, + map->type, + bioc->stripes[i].dev->devid, + &physical); + if (ret) { + btrfs_put_bioc(bioc); + goto out; + } + } else { + physical = map->stripes[stripe_index].physical + + stripe_offset + stripe_nr * map->stripe_len; + } + bioc->stripes[i].physical = physical; stripe_index++; } @@ -6600,7 +6618,6 @@ static int __btrfs_map_block(struct btrfs_fs_info *fs_info, } *bioc_ret = bioc; - bioc->map_type = map->type; bioc->num_stripes = num_stripes; bioc->max_errors = max_errors; bioc->mirror_num = mirror_num;
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(-)