On Mon, 17 Oct 2016 09:27:31 +0800 Qu Wenruo <quwen...@cn.fujitsu.com> wrote:
> For READ, caller normally hopes to get what they request, other than > full stripe map. > > In this case, we should remove unrelated stripe map, just like the > following case: > 32K 96K > |<-request range->| > 0 64k 128K > RAID0: | Data 1 | Data 2 | > disk1 disk2 > Before this patch, we return the full stripe: > Stripe 0: Logical 0, Physical X, Len 64K, Dev disk1 > Stripe 1: Logical 64k, Physical Y, Len 64K, Dev disk2 > > After this patch, we limit the stripe result to the request range: > Stripe 0: Logical 32K, Physical X+32K, Len 32K, Dev disk1 > Stripe 1: Logical 64k, Physical Y, Len 32K, Dev disk2 > > And if it's a RAID5/6 stripe, we just handle it like RAID0, ignoring > parities. > > This should make caller easier to use. > > Signed-off-by: Qu Wenruo <quwen...@cn.fujitsu.com> > --- > volumes.c | 103 > +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- > 1 file changed, 102 insertions(+), 1 deletion(-) > > diff --git a/volumes.c b/volumes.c > index 94f3e42..ba16d19 100644 > --- a/volumes.c > +++ b/volumes.c > @@ -1682,6 +1682,107 @@ static int fill_full_map_block(struct map_lookup > *map, u64 start, u64 length, > return 0; > } > > +static void del_one_stripe(struct btrfs_map_block *map_block, int i) > +{ > + int cur_nr = map_block->num_stripes; > + int size_left = (cur_nr - 1 - i) * sizeof(struct btrfs_map_stripe); > + > + memmove(&map_block->stripes[i], &map_block->stripes[i + 1], size_left); > + map_block->num_stripes--; > +} > + > +static void remove_unrelated_stripes(struct map_lookup *map, > + int rw, u64 start, u64 length, > + struct btrfs_map_block *map_block) > +{ > + int i = 0; > + /* > + * RAID5/6 write must use full stripe. > + * No need to do anything. > + */ > + if (map->type & (BTRFS_BLOCK_GROUP_RAID5 | BTRFS_BLOCK_GROUP_RAID6) && > + rw == WRITE) > + return; I believe it should be an "or" operation in the loop condition, rather than a single pipe. Sanidhya > + /* > + * For RAID0/1/10/DUP, whatever read/write, we can remove unrelated > + * stripes without causing anything wrong. > + * RAID5/6 READ is just like RAID0, we don't care parity unless we need > + * to recovery. > + * For recovery, rw should be set to WRITE. > + */ > + while (i < map_block->num_stripes) { > + struct btrfs_map_stripe *stripe; > + u64 orig_logical; /* Original stripe logical start */ > + u64 orig_end; /* Original stripe logical end */ > + > + stripe = &map_block->stripes[i]; > + > + /* > + * For READ, we don't really care parity > + */ > + if (stripe->logical == BTRFS_RAID5_P_STRIPE || > + stripe->logical == BTRFS_RAID6_Q_STRIPE) { > + del_one_stripe(map_block, i); > + continue; > + } > + /* Completely unrelated stripe */ > + if (stripe->logical >= start + length || > + stripe->logical + stripe->length <= start) { > + del_one_stripe(map_block, i); > + continue; > + } > + /* Covered stripe, modify its logical and physical */ > + orig_logical = stripe->logical; > + orig_end = stripe->logical + stripe->length; > + if (start + length <= orig_end) { > + /* > + * |<--range-->| > + * | stripe | > + * Or > + * |<range>| > + * | stripe | > + */ > + stripe->logical = max(orig_logical, start); > + stripe->length = start + length; > + stripe->physical += stripe->logical - orig_logical; > + } else if (start >= orig_logical) { > + /* > + * |<-range--->| > + * | stripe | > + * Or > + * |<range>| > + * | stripe | > + */ > + stripe->logical = start; > + stripe->length = min(orig_end, start + length); > + stripe->physical += stripe->logical - orig_logical; > + } > + /* > + * Remaining case: > + * |<----range----->| > + * | stripe | > + * No need to do any modification > + */ > + i++; > + } > + > + /* Recaculate map_block size */ > + map_block->start = 0; > + map_block->length = 0; > + for (i = 0; i < map_block->num_stripes; i++) { > + struct btrfs_map_stripe *stripe; > + > + stripe = &map_block->stripes[i]; > + if (stripe->logical > map_block->start) > + map_block->start = stripe->logical; > + if (stripe->logical + stripe->length > > + map_block->start + map_block->length) > + map_block->length = stripe->logical + stripe->length - > + map_block->start; > + } > +} > + > int __btrfs_map_block_v2(struct btrfs_fs_info *fs_info, int rw, u64 logical, > u64 length, struct btrfs_map_block **map_ret) > { > @@ -1717,7 +1818,7 @@ int __btrfs_map_block_v2(struct btrfs_fs_info *fs_info, > int rw, u64 logical, > free(map_block); > return ret; > } > - /* TODO: Remove unrelated map_stripes for READ operation */ > + remove_unrelated_stripes(map, rw, logical, length, map_block); > > *map_ret = map_block; > return 0; -- To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html