From patchwork Mon Dec 26 06:29:27 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 9488505 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id C42DA60839 for ; Mon, 26 Dec 2016 06:30:35 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id B5EA92022C for ; Mon, 26 Dec 2016 06:30:35 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id AA9311FFCA; Mon, 26 Dec 2016 06:30:35 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3E7C21FFCA for ; Mon, 26 Dec 2016 06:30:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754991AbcLZGaX (ORCPT ); Mon, 26 Dec 2016 01:30:23 -0500 Received: from cn.fujitsu.com ([222.73.24.84]:26380 "EHLO song.cn.fujitsu.com" rhost-flags-OK-FAIL-OK-OK) by vger.kernel.org with ESMTP id S1754858AbcLZGaR (ORCPT ); Mon, 26 Dec 2016 01:30:17 -0500 X-IronPort-AV: E=Sophos;i="5.20,367,1444665600"; d="scan'208";a="1036574" Received: from unknown (HELO cn.fujitsu.com) ([10.167.250.3]) by song.cn.fujitsu.com with ESMTP; 26 Dec 2016 14:29:47 +0800 Received: from localhost.localdomain (unknown [10.167.226.34]) by cn.fujitsu.com (Postfix) with ESMTP id F1ADA41B4BDE for ; Mon, 26 Dec 2016 14:29:43 +0800 (CST) From: Qu Wenruo To: linux-btrfs@vger.kernel.org Subject: [PATCH v2 07/19] btrfs-progs: Allow __btrfs_map_block_v2 to remove unrelated stripes Date: Mon, 26 Dec 2016 14:29:27 +0800 Message-Id: <20161226062939.5841-8-quwenruo@cn.fujitsu.com> X-Mailer: git-send-email 2.11.0 In-Reply-To: <20161226062939.5841-1-quwenruo@cn.fujitsu.com> References: <20161226062939.5841-1-quwenruo@cn.fujitsu.com> MIME-Version: 1.0 X-yoursite-MailScanner-ID: F1ADA41B4BDE.A1A67 X-yoursite-MailScanner: Found to be clean X-yoursite-MailScanner-From: quwenruo@cn.fujitsu.com Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP 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 --- volumes.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 102 insertions(+), 1 deletion(-) diff --git a/volumes.c b/volumes.c index 11d1f0e8..79b877c9 100644 --- a/volumes.c +++ b/volumes.c @@ -1733,6 +1733,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; + + /* + * 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 + * || + * | 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 + * || + * | 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) { @@ -1768,7 +1869,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;