From patchwork Wed Aug 23 07:57:56 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 9916797 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 6D64A60327 for ; Wed, 23 Aug 2017 07:58:15 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5FBF1288BD for ; Wed, 23 Aug 2017 07:58:15 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 54AC428948; Wed, 23 Aug 2017 07:58:15 +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,FREEMAIL_FROM, 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 B4493288BD for ; Wed, 23 Aug 2017 07:58:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753469AbdHWH6L (ORCPT ); Wed, 23 Aug 2017 03:58:11 -0400 Received: from mout.gmx.net ([212.227.17.20]:59742 "EHLO mout.gmx.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753415AbdHWH6J (ORCPT ); Wed, 23 Aug 2017 03:58:09 -0400 Received: from localhost.localdomain ([45.32.39.184]) by mail.gmx.com (mrgmx103 [212.227.17.174]) with ESMTPSA (Nemesis) id 0MPD8G-1dg0hp2Ui0-004VQr; Wed, 23 Aug 2017 09:58:06 +0200 From: Qu Wenruo To: linux-btrfs@vger.kernel.org Cc: dsterba@suse.cz Subject: [PATCH v2 1/4] btrfs: Refactor check_leaf function for later expansion. Date: Wed, 23 Aug 2017 16:57:56 +0900 Message-Id: <20170823075759.13982-2-quwenruo.btrfs@gmx.com> X-Mailer: git-send-email 2.13.3 In-Reply-To: <20170823075759.13982-1-quwenruo.btrfs@gmx.com> References: <20170823075759.13982-1-quwenruo.btrfs@gmx.com> X-Provags-ID: V03:K0:PPxgR4Lb8HxgYphW8tu1hb6AzQx8g0rhwDWqDL5l9MGh/2lOHRS VTbasUNYYFnX8nb8qbtEUZ9WIWPmWtLjYZgp6tAQV1PoFa/lbTdWw/NLmcGvtx48iJkddIx oDfNB6MwNxS2PxYeuRl57xllLRgRCluOJqa7fJQuDCC33mPZ98ycyr7gCPmQtB1okNEQeXX pyziCeMwGfyhIZCN04fGg== X-UI-Out-Filterresults: notjunk:1; V01:K0:HJu+u2eme4Y=:SizpmFQbgcr5fkeNinIZuT FdiGmRMg5DY/hyPr22/dZ36MoE969viFpnlHsLcMGRDldfnZ2ZcjzcSbI1lkYIKGtANmfrINU cTcsmB2ARatCptQ94m2dJfBtKyPKOvniZFvAbaFL+d3gRQlwkpiPQu4NPG5mg04r9Ojgl4Js3 HqmGl0mfsXx+woL8E4DUDlw/S83yzN25jpDv4pd0TfNQheN20RhOMSACa3ovor8v9o344D4NB vwsDWY7/F05jiTD+oSX5rOrgGyB9iJ9syHUW9t4c2KlPfv/myRDolJmz4agq/ksEObD3OzG1z XDTlRIAb7/h2hQptfAZd+Ap++/pLIE7ZLFkHxi5EGmDdzM6dq3N4ZRQaVpXTIK0xG7aH9nhnv toTejxXcrQkcJstszvNAn62Yx4K1TwB3wD8sQDi5EbgZ3/PZ/DXTIrOZ35Tjblqb6/EAOuUKs gmGZ24dN/6rbJmrlFPqNE7T9KBYVnP71cYySHUCHZzFDhpglTw3nPu4gQtNO1p5WiH+yy/IAH NaRRGsqiWy+CsriStm5ImQNTw1pZGWd5ezK5riiYZz+oQH+5I2TWrzQFdTOyyLKO2JgLU6t/N 0NB2YaZLWbfKA3xeXrNOsZmGUpEsOYCE0MYE39uLgfFf4ZhQxa5bCsIZj2WUsedgjOL6ZddSK UlaqHMQnJbDNPgfT+6PU8oP3au+D3sz2RofajB6VnnOA5HF3dkUsuL01UMfMve7ib+vouhQr+ wUYoXKCq74keILJf9ldrnw1nhZg4H4d3qjJn68U5xUsNWsX59SQXHBzxUxUBfE41yY+yrN1Gr Gur0FF2dUoU9pMo4XsHcvuDVFHjaQ== 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 Current check_leaf() function does a good job checking key orders and item offset/size. However it only checks from slot 0 to the last but one slot, this is good but makes later expansion hard. So this refactoring iterates from slot 0 to the last slot. For key comparison, it uses a key with all 0 as initial key, so all valid key should be larger than it. And for item size/offset check, it compares current item end with previous item offset. For slot 0, use leaf end as special case. This makes later item/key offset check and item size check easier to be implemented. Also, makes check_leaf() to return -EUCLEAN other than -EIO to indicate error. Signed-off-by: Qu Wenruo --- fs/btrfs/disk-io.c | 50 +++++++++++++++++++++++++++----------------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 080e2ebb8aa0..ebc719b790ee 100644 --- a/fs/btrfs/disk-io.c +++ b/fs/btrfs/disk-io.c @@ -553,8 +553,9 @@ static noinline int check_leaf(struct btrfs_root *root, struct extent_buffer *leaf) { struct btrfs_fs_info *fs_info = root->fs_info; + /* No valid key type is 0, so all key should be larger than this key */ + struct btrfs_key prev_key = {0, 0, 0}; struct btrfs_key key; - struct btrfs_key leaf_key; u32 nritems = btrfs_header_nritems(leaf); int slot; @@ -587,7 +588,7 @@ static noinline int check_leaf(struct btrfs_root *root, CORRUPT("non-root leaf's nritems is 0", leaf, check_root, 0); free_extent_buffer(eb); - return -EIO; + return -EUCLEAN; } free_extent_buffer(eb); } @@ -597,28 +598,23 @@ static noinline int check_leaf(struct btrfs_root *root, if (nritems == 0) return 0; - /* Check the 0 item */ - if (btrfs_item_offset_nr(leaf, 0) + btrfs_item_size_nr(leaf, 0) != - BTRFS_LEAF_DATA_SIZE(fs_info)) { - CORRUPT("invalid item offset size pair", leaf, root, 0); - return -EIO; - } - /* - * Check to make sure each items keys are in the correct order and their - * offsets make sense. We only have to loop through nritems-1 because - * we check the current slot against the next slot, which verifies the - * next slot's offset+size makes sense and that the current's slot - * offset is correct. + * Check the following things to make sure this is a good leaf, and + * leaf users won't need to bother similar sanity check: + * + * 1) key order + * 2) item offset and size + * No overlap, no hole, all inside the leaf. */ - for (slot = 0; slot < nritems - 1; slot++) { - btrfs_item_key_to_cpu(leaf, &leaf_key, slot); - btrfs_item_key_to_cpu(leaf, &key, slot + 1); + for (slot = 0; slot < nritems; slot++) { + u32 item_end_expected; + + btrfs_item_key_to_cpu(leaf, &key, slot); /* Make sure the keys are in the right order */ - if (btrfs_comp_cpu_keys(&leaf_key, &key) >= 0) { + if (btrfs_comp_cpu_keys(&prev_key, &key) >= 0) { CORRUPT("bad key order", leaf, root, slot); - return -EIO; + return -EUCLEAN; } /* @@ -626,10 +622,14 @@ static noinline int check_leaf(struct btrfs_root *root, * item data starts at the end of the leaf and grows towards the * front. */ - if (btrfs_item_offset_nr(leaf, slot) != - btrfs_item_end_nr(leaf, slot + 1)) { + if (slot == 0) + item_end_expected = BTRFS_LEAF_DATA_SIZE(fs_info); + else + item_end_expected = btrfs_item_offset_nr(leaf, + slot - 1); + if (btrfs_item_end_nr(leaf, slot) != item_end_expected) { CORRUPT("slot offset bad", leaf, root, slot); - return -EIO; + return -EUCLEAN; } /* @@ -640,8 +640,12 @@ static noinline int check_leaf(struct btrfs_root *root, if (btrfs_item_end_nr(leaf, slot) > BTRFS_LEAF_DATA_SIZE(fs_info)) { CORRUPT("slot end outside of leaf", leaf, root, slot); - return -EIO; + return -EUCLEAN; } + + prev_key.objectid = key.objectid; + prev_key.type = key.type; + prev_key.offset = key.offset; } return 0;