From patchwork Mon Sep 17 07:28:50 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Su Yue X-Patchwork-Id: 10602125 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 44AEE13AD for ; Mon, 17 Sep 2018 07:22:13 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2E9D129608 for ; Mon, 17 Sep 2018 07:22:13 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 22F5F29609; Mon, 17 Sep 2018 07:22:13 +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=-7.9 required=2.0 tests=BAYES_00,MAILING_LIST_MULTI, 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 B7D6729605 for ; Mon, 17 Sep 2018 07:22:12 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1728316AbeIQMsR (ORCPT ); Mon, 17 Sep 2018 08:48:17 -0400 Received: from mail.cn.fujitsu.com ([183.91.158.132]:52508 "EHLO heian.cn.fujitsu.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1727690AbeIQMsQ (ORCPT ); Mon, 17 Sep 2018 08:48:16 -0400 X-IronPort-AV: E=Sophos;i="5.43,368,1503331200"; d="scan'208";a="44983913" Received: from unknown (HELO cn.fujitsu.com) ([10.167.33.5]) by heian.cn.fujitsu.com with ESMTP; 17 Sep 2018 15:22:06 +0800 Received: from G08CNEXCHPEKD03.g08.fujitsu.local (unknown [10.167.33.85]) by cn.fujitsu.com (Postfix) with ESMTP id 1F7414B6EC97 for ; Mon, 17 Sep 2018 15:22:02 +0800 (CST) Received: from archlinux.g08.fujitsu.local (10.167.226.31) by G08CNEXCHPEKD03.g08.fujitsu.local (10.167.33.89) with Microsoft SMTP Server (TLS) id 14.3.408.0; Mon, 17 Sep 2018 15:22:04 +0800 From: Su Yue To: CC: Subject: [PATCH v3 5/7] btrfs-progs: lowmem: do missing check of last item after check_inode_item() Date: Mon, 17 Sep 2018 15:28:50 +0800 Message-ID: <20180917072852.25831-6-suy.fnst@cn.fujitsu.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20180917072852.25831-1-suy.fnst@cn.fujitsu.com> References: <20180917072852.25831-1-suy.fnst@cn.fujitsu.com> MIME-Version: 1.0 X-Originating-IP: [10.167.226.31] X-yoursite-MailScanner-ID: 1F7414B6EC97.AAB44 X-yoursite-MailScanner: Found to be clean X-yoursite-MailScanner-From: suy.fnst@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 After call of check_inode_item(), path may point to the last unchecked slot of the leaf. The outer walk_up_tree() always treats the position as checked slot then skips to the next. The last item will never be checked. While checking backrefs, path passed to walk_up_tree() always points to a checked slot. While checking fs trees, path passed to walk_up_tree() always points to an unchecked slot. Solution: Add an argument @is_checked to walk_up_tree() to decide whether to skip current slot. Fixes: 5e2dc770471b ("btrfs-progs: check: skip shared node or leaf check for low_memory mode") Signed-off-by: Su Yue --- check/mode-lowmem.c | 37 +++++++++++++++++++++++++++++++++---- 1 file changed, 33 insertions(+), 4 deletions(-) diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c index db44456fd85b..612e5e28e45b 100644 --- a/check/mode-lowmem.c +++ b/check/mode-lowmem.c @@ -4597,22 +4597,38 @@ static int walk_down_tree(struct btrfs_root *root, struct btrfs_path *path, return err; } +/* + * Walk up throuh the path. Make path point to next slot to be checked. + * walk_down_tree() should be called after this function. + * + * @root: root of the tree + * @path: will point to next slot to check for walk_down_tree() + * @level: returns with level of next node to be checked + * @is_checked: means is the current node checked or not + * if false, the slot is unchecked, do not increase the slot + * if true, means increase the slot of the current node + * + * Returns 0 means success. + * Returns >0 means the whole loop of walk up/down should be broken. + */ static int walk_up_tree(struct btrfs_root *root, struct btrfs_path *path, - int *level) + int *level, bool is_checked) { int i; struct extent_buffer *leaf; + int skip_cur = is_checked ? 1 : 0; for (i = *level; i < BTRFS_MAX_LEVEL - 1 && path->nodes[i]; i++) { leaf = path->nodes[i]; - if (path->slots[i] + 1 < btrfs_header_nritems(leaf)) { - path->slots[i]++; + if (path->slots[i] + skip_cur < btrfs_header_nritems(leaf)) { + path->slots[i] += skip_cur; *level = i; return 0; } free_extent_buffer(path->nodes[*level]); path->nodes[*level] = NULL; *level = i + 1; + skip_cur = 1; } return 1; } @@ -4815,7 +4831,20 @@ static int check_btrfs_root(struct btrfs_root *root, int check_all) break; } - ret = walk_up_tree(root, &path, &level); + /* + * The logical of walk trees are shared between backrefs + * check and fs trees check. + * In checking backrefs(check_all is true), after + * check_leaf_items() returns, path points to + * last checked item. + * In checking fs roots(check_all is false), after + * process_one_leaf() returns, path points to unchecked item. + * + * walk_up_tree() is reponsible to make path point to next + * slot to be checked, above case is handled in + * walk_up_tree(). + */ + ret = walk_up_tree(root, &path, &level, check_all); if (ret != 0) { /* Normal exit, reset ret to err */ ret = err;