From patchwork Wed Sep 12 20:49:23 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Su Yue X-Patchwork-Id: 10597473 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 029AD920 for ; Wed, 12 Sep 2018 12:50:11 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E8C6129EB7 for ; Wed, 12 Sep 2018 12:50:10 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id DD1C729EE2; Wed, 12 Sep 2018 12:50:10 +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=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,FREEMAIL_FROM,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 40F7129ED4 for ; Wed, 12 Sep 2018 12:50:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726970AbeILRyb (ORCPT ); Wed, 12 Sep 2018 13:54:31 -0400 Received: from mail-pl1-f195.google.com ([209.85.214.195]:33934 "EHLO mail-pl1-f195.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726491AbeILRyb (ORCPT ); Wed, 12 Sep 2018 13:54:31 -0400 Received: by mail-pl1-f195.google.com with SMTP id f6-v6so949303plo.1 for ; Wed, 12 Sep 2018 05:50:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=SgFZbqFuo8IayjETyOxV+cFtZfIL4o1etpUJKGpLWXo=; b=sUba2uoD3XsVs07AqZl9YDxhgLyQORLtuBdkxLmy+N7Y9A2Uz6U7UpETrqEDIChNjy icfaJQMC5Ze6Y5BGMCt+IPp0cTS4id/IqhmK5Vj22FUbmzM7ZL4zxRcCo1oBzHG2WKw/ BfjfKIVGmoyoYaGXna3SLm0GVgDmKeIO0k495W7EROO7clFBINdJjhj74kAjRFNBnxAW dZk9daz9g5uryd0GyCW0cEMbCrELYedzn3xBWS4yFBjJ4kFYvZE8twa05n10sRJf/NMz +9THo1DcS51Mrwm2srmhj0FImEAxlF+GPLQ+qnxiE3GWEdsJj0ZPpP3ZDH5IrJPPDWZp o9OA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=SgFZbqFuo8IayjETyOxV+cFtZfIL4o1etpUJKGpLWXo=; b=U64t4zTNDu14v0Zrs52dnzQ5w5B5Z0gXhc0mEBhdhxjZTwm0GZ9N0WAhflKfiDvJYU WoFa77MaB3p7SJaB37TrjGm4GbJwcxMuVzhVhMtCDzwXWsIr1YV6ySl4vPOdSuI7uxaX P81ORisscpCcB/Uhzk4oar5xHx+Swx7KnSlOKNdhJkQ1PDv384YuR6Am1ZjEtdJkr8jf K/WumNRNyVJhE9Buh67lRQV9BLPqMEIJTlqG4L5VBpT5E8UEE8Phbz62O7MR7w1DYiEG klHq1ujwFHlHvV7IhT/pP2pliDrMA8V9S5rQ0b8Gk+o2UppKmS+fj4b/evymSsKB8wl1 0l5A== X-Gm-Message-State: APzg51CEm1Q83ups21oIgyyYzpq3YU0emZroI2LTT21GWd5jgvXTRjsG fBWeqVzvHRj+2dCHDbeX25lP89i9 X-Google-Smtp-Source: ANB0VdZrVvnQrDVZV4OdAxOdUXInlzX1wB42Abc+sgrwjtMlAAiVnSSCc0bJo5GzK09TkAsgNQZ6wA== X-Received: by 2002:a17:902:6115:: with SMTP id t21-v6mr2118143plj.92.1536756607888; Wed, 12 Sep 2018 05:50:07 -0700 (PDT) Received: from cat-arch.lan (li1862-137.members.linode.com. [172.105.208.137]) by smtp.gmail.com with ESMTPSA id w12-v6sm1739393pfd.110.2018.09.12.05.50.03 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 12 Sep 2018 05:50:06 -0700 (PDT) From: damenly.su@gmail.com X-Google-Original-From: suy.fnst@cn.fujitsu.com To: linux-btrfs@vger.kernel.org Cc: suy.fnst@cn.fujitsu.com Subject: [PATCH v2 6/7] btrfs-progs: lowmem: improve check_inode_extref() Date: Wed, 12 Sep 2018 20:49:23 +0000 Message-Id: <20180912204924.10089-7-suy.fnst@cn.fujitsu.com> X-Mailer: git-send-email 2.18.0 In-Reply-To: <20180912204924.10089-1-suy.fnst@cn.fujitsu.com> References: <20180912204924.10089-1-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 From: Su Yue inode_extref is much similar with inode_ref, most codes are reused in check_inode_extref(). Exception: There is no need to check root directory, so remove it. Make check_inode_extref() verify hash value with key offset now. And lowmem check can detect errors about inode_extref and try to repair errors. Signed-off-by: Su Yue --- check/mode-lowmem.c | 119 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 92 insertions(+), 27 deletions(-) diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c index b6b33786d02b..bec2ee185cc8 100644 --- a/check/mode-lowmem.c +++ b/check/mode-lowmem.c @@ -1182,37 +1182,79 @@ out: * * Return 0 if no error occurred. */ -static int check_inode_extref(struct btrfs_root *root, - struct btrfs_key *ref_key, - struct extent_buffer *node, int slot, u64 *refs, - int mode) +static int check_inode_extref(struct btrfs_root *root, struct btrfs_key *ref_key, + struct btrfs_path *path, char *name_ret, + u32 *namelen_ret, u64 *refs_ret, int mode) { struct btrfs_key key; struct btrfs_key location; struct btrfs_inode_extref *extref; + struct extent_buffer *node; char namebuf[BTRFS_NAME_LEN] = {0}; u32 total; - u32 cur = 0; + u32 cur; u32 len; u32 name_len; u64 index; u64 parent; + int err; + int tmp_err; int ret; - int err = 0; + int slot; + u64 refs; + bool search_again = false; location.objectid = ref_key->objectid; location.type = BTRFS_INODE_ITEM_KEY; location.offset = 0; +begin: + cur = 0; + err = 0; + refs = *refs_ret; + *namelen_ret = 0; + + /* since after repair, path and the dir item may be changed */ + if (search_again) { + search_again = false; + btrfs_release_path(path); + ret = btrfs_search_slot(NULL, root, ref_key, path, 0, 0); + /* + * The item was deleted, let the path point to the last checked + * item. + */ + if (ret > 0) { + if (path->slots[0] == 0) { + ret = btrfs_prev_leaf(root, path); + /* + * we are checking the inode item, there must + * be some items before, the case shall never + * happen. + */ + BUG_ON(ret); + } else { + path->slots[0]--; + } + goto out; + } else if (ret < 0) { + err |= ret; + goto out; + } + } + + node = path->nodes[0]; + slot = path->slots[0]; extref = btrfs_item_ptr(node, slot, struct btrfs_inode_extref); total = btrfs_item_size_nr(node, slot); -next: - /* update inode ref count */ - (*refs)++; - name_len = btrfs_inode_extref_name_len(node, extref); - index = btrfs_inode_extref_index(node, extref); +loop: + /* Update inode ref count */ + refs++; + tmp_err = 0; parent = btrfs_inode_extref_parent(node, extref); + index = btrfs_inode_extref_index(node, extref); + name_len = btrfs_inode_extref_name_len(node, extref); + if (name_len <= BTRFS_NAME_LEN) { len = name_len; } else { @@ -1220,37 +1262,60 @@ next: warning("root %llu INODE_EXTREF[%llu %llu] name too long", root->objectid, ref_key->objectid, ref_key->offset); } + read_extent_buffer(node, namebuf, (unsigned long)(extref + 1), len); - /* Check root dir ref name */ - if (index == 0 && strncmp(namebuf, "..", name_len)) { - error("root %llu INODE_EXTREF[%llu %llu] ROOT_DIR name shouldn't be %s", + /* verify hash value */ + if (ref_key->offset != btrfs_extref_hash(parent, namebuf, len)) { + err |= -EIO; + error("root %llu INODE_EXTREF[%llu %llu] name %s namelen %u mode %d mismatch with its hash, wanted %llu have %llu", root->objectid, ref_key->objectid, ref_key->offset, - namebuf); - err |= ROOT_DIR_ERROR; + namebuf, len, mode, ref_key->offset, + btrfs_extref_hash(parent, namebuf, len)); + goto out; } - /* find related dir_index */ + /* copy the first name found to name_ret */ + if (refs == 1 && name_ret) { + memcpy(name_ret, namebuf, len); + *namelen_ret = len; + } + + /* Find related DIR_INDEX */ key.objectid = parent; key.type = BTRFS_DIR_INDEX_KEY; key.offset = index; - ret = find_dir_item(root, &key, &location, namebuf, len, mode); - err |= ret; + tmp_err |= find_dir_item(root, &key, &location, namebuf, len, + imode_to_type(mode)); - /* find related dir_item */ + /* Find related dir_item */ key.objectid = parent; key.type = BTRFS_DIR_ITEM_KEY; key.offset = btrfs_name_hash(namebuf, len); - ret = find_dir_item(root, &key, &location, namebuf, len, mode); - err |= ret; + tmp_err |= find_dir_item(root, &key, &location, namebuf, len, + imode_to_type(mode)); + + if (tmp_err && repair) { + ret = repair_ternary_lowmem(root, parent, ref_key->objectid, + index, namebuf, name_len, imode_to_type(mode), + tmp_err); + if (!ret) { + search_again = true; + goto begin; + } + } + print_inode_ref_err(root, ref_key, index, namebuf, name_len, + imode_to_type(mode), tmp_err); + + err |= tmp_err; len = sizeof(*extref) + name_len; extref = (struct btrfs_inode_extref *)((char *)extref + len); cur += len; - if (cur < total) - goto next; - + goto loop; +out: + *refs_ret = refs; return err; } @@ -2426,8 +2491,8 @@ static int check_inode_item(struct btrfs_root *root, struct btrfs_path *path) warning("root %llu EXTREF[%llu %llu] isn't supported", root->objectid, key.objectid, key.offset); - ret = check_inode_extref(root, &key, node, slot, &refs, - mode); + ret = check_inode_extref(root, &key, path, namebuf, + &name_len, &refs, mode); err |= ret; break; }