From patchwork Tue Aug 22 07:37:15 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Qu Wenruo X-Patchwork-Id: 9914343 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 2EEA7600C5 for ; Tue, 22 Aug 2017 07:38:04 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 1F2AB287DC for ; Tue, 22 Aug 2017 07:38:04 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 11D5C28809; Tue, 22 Aug 2017 07:38:04 +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.4 required=2.0 tests=BAYES_00,FREEMAIL_FROM, RCVD_IN_DNSWL_HI,RCVD_IN_SORBS_SPAM 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 7C42D287DC for ; Tue, 22 Aug 2017 07:38:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754717AbdHVHhb (ORCPT ); Tue, 22 Aug 2017 03:37:31 -0400 Received: from mout.gmx.net ([212.227.15.15]:65082 "EHLO mout.gmx.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754710AbdHVHhZ (ORCPT ); Tue, 22 Aug 2017 03:37:25 -0400 Received: from localhost.localdomain ([45.32.39.184]) by mail.gmx.com (mrgmx001 [212.227.17.184]) with ESMTPSA (Nemesis) id 0MSuMn-1eBF8Z3miL-00RqaN; Tue, 22 Aug 2017 09:37:23 +0200 From: Qu Wenruo To: linux-btrfs@vger.kernel.org Cc: dsterba@suse.cz Subject: [PATCH 1/3] btrfs: Refactor check_leaf function for later expansion. Date: Tue, 22 Aug 2017 16:37:15 +0900 Message-Id: <20170822073717.13081-2-quwenruo.btrfs@gmx.com> X-Mailer: git-send-email 2.13.3 In-Reply-To: <20170822073717.13081-1-quwenruo.btrfs@gmx.com> References: <20170822073717.13081-1-quwenruo.btrfs@gmx.com> X-Provags-ID: V03:K0:dYqgVmZXqYQH4kjwhzcdTMpNdbkrFmHvZwgoV/USCcHjTvouUMe 8FsMo0e8fuyOOHXFWEeoXcweR/QT93SUICsQdD0rstf+rBzq/52toQYGCQEXpb///6skOVy w1y81kCtX47FUQX4Wfk53eAj5LZTdjTsIZs0ji6BDc2O+WGlgsLXHl38urXoV/Fbu8QtZS4 jxVovcveuSJnN+60xWOZg== X-UI-Out-Filterresults: notjunk:1; V01:K0:h1q502wZnDc=:0WOzIbhNm9La8ZAD6JjUgj LRP1W1WYdgdD70Pq2k4fPZTtTY2KvWrI11yVET1sM5ttf1tcreDbO2oUVTIty6hExCn8UKM8z 2YOpC7/MvNsb99dTXfgb2NbTz/ziBu+pCOFYYxhfnAB/LSpErhCR/YmxCCD/QIqU94EyU4+AU RAT/Homc2YpvB9HqUn+7ZB2cujTu92wl1p2p9ms9QlxHl7DqCNryZLMjeo+77CQf+uP+XZPr/ gUCCgnxxW6tTBwo/Ri7McdjPVhe8mcXapdmmig3+gXsIrBGHEJDlXVuL7h3k5HtiLKNcRTt8x HfYQdpMRnhvhqdSZY4psQHJzw6YFQ12wEJLkeXQEohexFhouEe3IbPP/XLxh3ltViw0Y7aBlB h0fS+BKKFPFt6u/P1aB+W77lw1V/6vkKU4fz4eP9DnsEKmFgq15iYJSUpbnCBLpNhRgQIMNPn Dizn1Byosmc8BcnLUMpzrjlKqlzSXtDBHnN7wc01itmMlVoQ010TKXEb/oTm9BeYeXiCA5EMg aGku8pD98CjQa2Ee1gLlalh67E0zm+Xvgz2JAEAvzYjLHRt7NCcbaOe8zJaOJXA1N79620mrf 0Mp8zso/vHaPmZCgW9VBwOSzarPfWtwdkdq9D++nIIOnQMm/XDLE3TzRVELC6ZTZud0eGuOBg rucTxXR//YYW2hjbGdn81GbWKUEYP4Q9/AZ9EfANArHUTRB/Xs3kJL7BIQfEewX1cE81uKILu ZzQ3UicAv1kc3qJFmgZ8zg60vpoAzoqTIGBNwXYoFVg2zmAeFF/iz8uPqO0DUzY3BsONFoZFh yMcGBf/WZrBsxgkeOo8ffzM7K0ANA== 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. Signed-off-by: Qu Wenruo --- fs/btrfs/disk-io.c | 42 +++++++++++++++++++++++------------------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/fs/btrfs/disk-io.c b/fs/btrfs/disk-io.c index 080e2ebb8aa0..919ddd4b774c 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; @@ -597,26 +598,21 @@ 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; } @@ -626,8 +622,12 @@ 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; } @@ -642,6 +642,10 @@ static noinline int check_leaf(struct btrfs_root *root, CORRUPT("slot end outside of leaf", leaf, root, slot); return -EIO; } + + prev_key.objectid = key.objectid; + prev_key.type = key.type; + prev_key.offset = key.offset; } return 0;