From patchwork Wed Apr 19 21:23:52 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13217421 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E4444C77B73 for ; Wed, 19 Apr 2023 21:24:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231490AbjDSVYl (ORCPT ); Wed, 19 Apr 2023 17:24:41 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48422 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231478AbjDSVYk (ORCPT ); Wed, 19 Apr 2023 17:24:40 -0400 Received: from mail-qv1-xf34.google.com (mail-qv1-xf34.google.com [IPv6:2607:f8b0:4864:20::f34]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9BFCC83CD for ; Wed, 19 Apr 2023 14:24:16 -0700 (PDT) Received: by mail-qv1-xf34.google.com with SMTP id oj8so995328qvb.11 for ; Wed, 19 Apr 2023 14:24:16 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1681939455; x=1684531455; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=JogPAGMmyJ5vrU1UmjHbuPsmtHvZG94tIlFd63G5PoQ=; b=vKEXPNR+eDG3uqUm/jr4bL8GB4WGhpG2tc38bw9GIRLqPL5t27u3M09sMpwrgVXhr6 hXmsH31/dO2Z7ZY+An+6qDDLEbnDrbyaG3IOp1Q2q1W5bp00iY0Km9hR7zUXyHEUxA81 dJC5RcD4pmFlSMwMfuHc51h/0pI/s/a9RR9o1/B40PxEl3Z5sbTnBk7lTcZJW/ZYT4bp 9z/XuQs2jYc1cdBaYJZMMmT0Qy/c3y2H7ERsPNKnBEfBhexijDOZC8UJHrbz/mFVpPkZ x1R7XOB7ZmyeJg/jl8/oB9PgDiEzrIqKTE43R2WJvB+CjS49s21jEZobkF7bMoi4HJ8N kqFw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1681939455; x=1684531455; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=JogPAGMmyJ5vrU1UmjHbuPsmtHvZG94tIlFd63G5PoQ=; b=S0v8u58D8ctdoj0cr0XYi6ztIrSHg9BTrgq8ifbrHqp9qO6gS8o5J9V7U+mjdHrgOL ArL+VL84hy+4077SOgblVUIu+PUQx2UDBIFR5UwCv5Gitr0z4np24FaY7GmdxLq7+UwQ 90LpMo+uLKb9332IsELDbUw0n+3wiqtZ/CrbpnHAUwaJr1wKrzM+SLvY1qjIeIs3ulSs Ou39ERQPq/b+V0twUk/H9YPmdFqJvOAHXsB1yYrkYi+zL4uw8JtjGn8b/vbZ4bf/tKHk 1W2u6eLueRMLu39uLtsjtjNkpgeS/r49btoPSH90CNqi//a082kh/PvkkXfivDiRu67X tMig== X-Gm-Message-State: AAQBX9coTwfrPnZjEGtrPXXeb9vkTiesrLEI9nvfSfThQ/W0RUQE9gTM l3ylUVkn4+DZ5H7QjIPettH3ut+M+sbCWsmmWw4I+Q== X-Google-Smtp-Source: AKy350bShD0tINuVZcdu6Osh24jE5HA+vXYsj5HlSiM+fZ0zd8o6peyVw0V6eyauCN36zUlbR4fQRA== X-Received: by 2002:ad4:5baf:0:b0:537:6416:fc2b with SMTP id 15-20020ad45baf000000b005376416fc2bmr28845642qvq.52.1681939454658; Wed, 19 Apr 2023 14:24:14 -0700 (PDT) Received: from localhost (cpe-174-109-170-245.nc.res.rr.com. [174.109.170.245]) by smtp.gmail.com with ESMTPSA id b9-20020a0cc989000000b005eee320b5d7sm1103qvk.63.2023.04.19.14.24.14 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Apr 2023 14:24:14 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 01/18] btrfs-progs: sync and stub-out tree-mod-log.h Date: Wed, 19 Apr 2023 17:23:52 -0400 Message-Id: <41610cf9074900784876cb85b00dfa3846778598.1681939316.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org In order to sync ctree.c we're going to have to have definitions for the tree-mod-log stuff. However we don't need any of the code, we don't do live backref lookups in btrfs-progs, so simply sync the header file and stub all the helpers out. Signed-off-by: Josef Bacik --- kernel-shared/tree-mod-log.h | 96 ++++++++++++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 kernel-shared/tree-mod-log.h diff --git a/kernel-shared/tree-mod-log.h b/kernel-shared/tree-mod-log.h new file mode 100644 index 00000000..922862b2 --- /dev/null +++ b/kernel-shared/tree-mod-log.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: GPL-2.0 */ + +#ifndef BTRFS_TREE_MOD_LOG_H +#define BTRFS_TREE_MOD_LOG_H + +#include "ctree.h" + +/* Represents a tree mod log user. */ +struct btrfs_seq_list { + struct list_head list; + u64 seq; +}; + +#define BTRFS_SEQ_LIST_INIT(name) { .list = LIST_HEAD_INIT((name).list), .seq = 0 } +#define BTRFS_SEQ_LAST ((u64)-1) + +enum btrfs_mod_log_op { + BTRFS_MOD_LOG_KEY_REPLACE, + BTRFS_MOD_LOG_KEY_ADD, + BTRFS_MOD_LOG_KEY_REMOVE, + BTRFS_MOD_LOG_KEY_REMOVE_WHILE_FREEING, + BTRFS_MOD_LOG_KEY_REMOVE_WHILE_MOVING, + BTRFS_MOD_LOG_MOVE_KEYS, + BTRFS_MOD_LOG_ROOT_REPLACE, +}; + +static inline u64 btrfs_get_tree_mod_seq(struct btrfs_fs_info *fs_info, + struct btrfs_seq_list *elem) +{ + return 0; +} + +static inline void btrfs_put_tree_mod_seq(struct btrfs_fs_info *fs_info, + struct btrfs_seq_list *elem) +{ +} + +static inline int btrfs_tree_mod_log_insert_root(struct extent_buffer *old_root, + struct extent_buffer *new_root, + bool log_removal) +{ + return 0; +} + +static inline int btrfs_tree_mod_log_insert_key(struct extent_buffer *eb, int slot, + enum btrfs_mod_log_op op) +{ + return 0; +} + +static inline int btrfs_tree_mod_log_free_eb(struct extent_buffer *eb) +{ + return 0; +} + +static inline struct extent_buffer *btrfs_tree_mod_log_rewind(struct btrfs_fs_info *fs_info, + struct btrfs_path *path, + struct extent_buffer *eb, + u64 time_seq) +{ + return NULL; +} + +static inline struct extent_buffer *btrfs_get_old_root(struct btrfs_root *root, + u64 time_seq) +{ + return NULL; +} + +static inline int btrfs_old_root_level(struct btrfs_root *root, u64 time_seq) +{ + return btrfs_header_level(root->node); +} + +static inline int btrfs_tree_mod_log_eb_copy(struct extent_buffer *dst, + struct extent_buffer *src, + unsigned long dst_offset, + unsigned long src_offset, + int nr_items) +{ + return 0; +} + +static inline int btrfs_tree_mod_log_insert_move(struct extent_buffer *eb, + int dst_slot, int src_slot, + int nr_items) +{ + return 0; +} + +static inline u64 btrfs_tree_mod_log_lowest_seq(struct btrfs_fs_info *fs_info) +{ + return 0; +} + +#endif From patchwork Wed Apr 19 21:23:53 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13217422 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0568EC77B7A for ; Wed, 19 Apr 2023 21:24:45 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231478AbjDSVYn (ORCPT ); Wed, 19 Apr 2023 17:24:43 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48422 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231548AbjDSVYm (ORCPT ); Wed, 19 Apr 2023 17:24:42 -0400 Received: from mail-qv1-xf29.google.com (mail-qv1-xf29.google.com [IPv6:2607:f8b0:4864:20::f29]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 85169E60 for ; Wed, 19 Apr 2023 14:24:18 -0700 (PDT) Received: by mail-qv1-xf29.google.com with SMTP id oj8so995402qvb.11 for ; Wed, 19 Apr 2023 14:24:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1681939457; x=1684531457; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=BwhWVImHwlVJpKJyq0m+xGQR6xufVt8BES4EXZJ4PnY=; b=UBtpcO80AD5SWlzFNsGGTmyaKzHE/fqKYbwKrDx1HvVMV4GuEix5LmkZjsxjNpOsod v237n+6WBNhxcUPSRAWxf+9VFfgbMwQ5flvK1YVEJBp9GyRjBpEioPXiIJuwHL3HMZ2a GCKWEIpqBMX1CB18QMTCGjZRryXsJxi7j0qJoXj1nJhlPIATEsNRNhb8qwDtjhPD+PSe Jz4gMwx1ZGs3NZ6Zvsz4b6Q0iOtY0Vkanydli03FLR2oXlIqrk9TGc6jWuDkAUQj/Czz lECFWwZHMv5Kswp+LUmGagCL/PqkCVZrQcZ76hrZBUJHFAOv+Cffhum7CKgvQuxgLZyK aVHg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1681939457; x=1684531457; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=BwhWVImHwlVJpKJyq0m+xGQR6xufVt8BES4EXZJ4PnY=; b=YGCL5JGomBe08AK7Sg6eAopNwOCPTHC7DoJMrXZm0xp0dH/bqfAtMGxAMj9enRKnBX ZSbyilCq5NmMAJYHOHliSaFfLpJ92glZxc7sBXL1AKmoJcDYgQ33dhGYSv0MnKUxaJio apH/wOU4oL3ri+kHa4vjqHuTFxrcLu0QR69GjLeIUNbowvRF/+g6yCZh/ZcgnBhucaX7 yh0xl1PszfEOmNcHEdE0rycpzfVv1d8aFSJbRloJZ06kaEcx/jj2Hv2UyOpgL/pUg7X1 rjlM44puB1nzZ8KOG6cl8K98BpoTnpw42F2IrxCJAjXgIi7LP+HDpT8OVvhBm9I7LajY sSyQ== X-Gm-Message-State: AAQBX9d4xFUhf0WAFTIpiZSCYWbG94lYPkUN616EOqbR4/QQyl3YUtzg Vp7I9h9RPYaadAoyF4sGVaMcbLqTgX7wdD+rzVsdtw== X-Google-Smtp-Source: AKy350bEMnpf5e5T1c/MA67+PS1zoiSQJUNP014YwbRwSQbpdvm2T04mB5k5e8uweo1OHDoiUM8fXQ== X-Received: by 2002:a05:6214:b65:b0:5df:d35d:20fb with SMTP id ey5-20020a0562140b6500b005dfd35d20fbmr9193075qvb.7.1681939456018; Wed, 19 Apr 2023 14:24:16 -0700 (PDT) Received: from localhost (cpe-174-109-170-245.nc.res.rr.com. [174.109.170.245]) by smtp.gmail.com with ESMTPSA id z3-20020a0cf243000000b005dd8b934587sm6792qvl.31.2023.04.19.14.24.15 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Apr 2023 14:24:15 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 02/18] btrfs-progs: add btrfs_root_id helper Date: Wed, 19 Apr 2023 17:23:53 -0400 Message-Id: <832cc319f165f64cfd22a80e18de666b29e80520.1681939316.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org This exists in the kernel and is used throughout ctree.c, sync this helper to make sync'ing ctree.c easier. Signed-off-by: Josef Bacik --- kernel-shared/ctree.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h index 655b714f..d5cd7803 100644 --- a/kernel-shared/ctree.h +++ b/kernel-shared/ctree.h @@ -476,6 +476,11 @@ struct btrfs_root { struct rb_node rb_node; }; +static inline u64 btrfs_root_id(const struct btrfs_root *root) +{ + return root->root_key.objectid; +} + static inline u32 BTRFS_MAX_ITEM_SIZE(const struct btrfs_fs_info *info) { return BTRFS_LEAF_DATA_SIZE(info) - sizeof(struct btrfs_item); From patchwork Wed Apr 19 21:23:54 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13217423 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 4C2AEC77B73 for ; Wed, 19 Apr 2023 21:24:51 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232363AbjDSVYt (ORCPT ); Wed, 19 Apr 2023 17:24:49 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48382 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232036AbjDSVYn (ORCPT ); Wed, 19 Apr 2023 17:24:43 -0400 Received: from mail-qt1-x831.google.com (mail-qt1-x831.google.com [IPv6:2607:f8b0:4864:20::831]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id B790E76BD for ; Wed, 19 Apr 2023 14:24:18 -0700 (PDT) Received: by mail-qt1-x831.google.com with SMTP id ey8so674468qtb.3 for ; Wed, 19 Apr 2023 14:24:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1681939457; x=1684531457; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=rz1YLu+MmdhFfjhTIeHo4Qw3MKzLzFTxZhsTOEjXCkU=; b=5q9Mo2EHOt1Iz92djYUZ+2OzvDeQt7pkG1Bs/0dpXuuFjh613szmOIs1XXLfspwjxo 7vPluqkMdSMjWEa6Na1TUOaTK0idriahJEq7vAKI6/evAAviN7Fdf9xnTLY5mup85uUr YgzAEIlR6PUE95tX9NuAySt+4/qp4y+KlnH4uF/rW1XRX06akrOGhBFALV3/PxOW4L2R e9mDK5INpN4MWcL3JRtvys9RhkWJyKQkVhqU4E8Ia0A7uuKLcuZE/M4QjEgBjNV1K2Ln RFJ3e0cL9lluzRNFQuIJFOwtRMyHGolzS8bfy8Q/nZzmuWHk82RrJYAOZB4URg9vyEa2 JslA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1681939457; x=1684531457; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=rz1YLu+MmdhFfjhTIeHo4Qw3MKzLzFTxZhsTOEjXCkU=; b=F+n+iMiSj9IwxCgLZcCHpZCW8id6o9bD5HhT9AXuGS2W8ljSV+KLqRXPd+OWiMXeuk X2a9gYwi6u9zXhOpWDbrqb7ipKAEhNC6ebghsadoGNHtSH3yPHDzGr7AmJJ1BWhvmO/k VXQ5khV9nWlkEreyPPvQ42CdPw7ZeoH7/UruzzYyiuVOmb/EpDdcAWgZz4vYu3VX1FBg DCaCs0IZ20Pakdr7hgn3jM1zhcw9FNG7Z1bFzLgzpnghSmy5ZlVjKLMjYcUTs30Ns0bz L8xF7Qv1RUvfhwAUkU/JQbHRT3ew5pSL+cKuvzgghwZfN+7ix5Ay6EbZ9UIIXTU/sopk LKcg== X-Gm-Message-State: AAQBX9dUVENY8wC1wi6oIXptZeCxMiStLRzKXu8LUMTek6SLK9TeEcOA hSS30H+V5FWDVPmE+Ww4ftV5jALJS1hO0MNOvOX6Fw== X-Google-Smtp-Source: AKy350YEBMp71WoHxLVu/P6jKNkJujD878mdouuofPUmgqV+Okv7Kb9v61+SvBXvmt3Fh7xXpD9qkg== X-Received: by 2002:a05:622a:1aa7:b0:3e6:3851:b945 with SMTP id s39-20020a05622a1aa700b003e63851b945mr9299998qtc.67.1681939457409; Wed, 19 Apr 2023 14:24:17 -0700 (PDT) Received: from localhost (cpe-174-109-170-245.nc.res.rr.com. [174.109.170.245]) by smtp.gmail.com with ESMTPSA id x22-20020a05620a449600b0074e077c9317sm1322714qkp.99.2023.04.19.14.24.16 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Apr 2023 14:24:17 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 03/18] btrfs-progs: remove root argument from free_extent and inc_extent_ref Date: Wed, 19 Apr 2023 17:23:54 -0400 Message-Id: <49d525ba3ef5dc1a8b31b829e4f8ecd809a0cb46.1681939316.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org Neither of these actually need the root argument, we provide all the information for the ref through the arguments we pass through. Remove the root argument from both of them. These needed to be done in the same patch because of the __btrfs_mod_ref helper which will pick one or the other function for processing reference updates. Signed-off-by: Josef Bacik --- check/clear-cache.c | 5 +++-- check/main.c | 10 ++++------ check/mode-lowmem.c | 10 +++++----- kernel-shared/ctree.c | 29 +++++++++++++---------------- kernel-shared/ctree.h | 2 -- kernel-shared/extent-tree.c | 24 ++++++++++-------------- kernel-shared/free-space-cache.c | 5 ++--- 7 files changed, 37 insertions(+), 48 deletions(-) diff --git a/check/clear-cache.c b/check/clear-cache.c index 5ffdd430..031379ce 100644 --- a/check/clear-cache.c +++ b/check/clear-cache.c @@ -513,8 +513,9 @@ int truncate_free_ino_items(struct btrfs_root *root) extent_offset = found_key.offset - btrfs_file_extent_offset(leaf, fi); UASSERT(extent_offset == 0); - ret = btrfs_free_extent(trans, root, extent_disk_bytenr, - extent_num_bytes, 0, root->objectid, + ret = btrfs_free_extent(trans, extent_disk_bytenr, + extent_num_bytes, 0, + root->objectid, BTRFS_FREE_INO_OBJECTID, 0); if (ret < 0) { btrfs_abort_transaction(trans, ret); diff --git a/check/main.c b/check/main.c index 09805511..275f912b 100644 --- a/check/main.c +++ b/check/main.c @@ -3586,7 +3586,7 @@ static int repair_btree(struct btrfs_root *root, * return value is not concerned. */ btrfs_release_path(&path); - ret = btrfs_free_extent(trans, root, offset, + ret = btrfs_free_extent(trans, offset, gfs_info->nodesize, 0, root->root_key.objectid, level - 1, 0); cache = next_cache_extent(cache); @@ -6861,9 +6861,8 @@ static int record_extent(struct btrfs_trans_handle *trans, * just makes the backref allocator create a data * backref */ - ret = btrfs_inc_extent_ref(trans, extent_root, - rec->start, rec->max_size, - parent, + ret = btrfs_inc_extent_ref(trans, rec->start, + rec->max_size, parent, dback->root, parent ? BTRFS_FIRST_FREE_OBJECTID : @@ -6890,8 +6889,7 @@ static int record_extent(struct btrfs_trans_handle *trans, else parent = 0; - ret = btrfs_inc_extent_ref(trans, extent_root, - rec->start, rec->max_size, + ret = btrfs_inc_extent_ref(trans, rec->start, rec->max_size, parent, tback->root, 0, 0); fprintf(stderr, "adding new tree backref on start %llu len %llu parent %llu root %llu\n", diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c index 0bc95930..10f86161 100644 --- a/check/mode-lowmem.c +++ b/check/mode-lowmem.c @@ -755,8 +755,8 @@ static int repair_tree_block_ref(struct btrfs_root *root, parent = nrefs->bytenr[level + 1]; /* increase the ref */ - ret = btrfs_inc_extent_ref(trans, extent_root, bytenr, node_size, - parent, root->objectid, level, 0); + ret = btrfs_inc_extent_ref(trans, bytenr, node_size, parent, + root->objectid, level, 0); nrefs->refs[level]++; out: @@ -3335,7 +3335,7 @@ static int repair_extent_data_item(struct btrfs_root *root, btrfs_release_path(&path); } - ret = btrfs_inc_extent_ref(trans, root, disk_bytenr, num_bytes, parent, + ret = btrfs_inc_extent_ref(trans, disk_bytenr, num_bytes, parent, root->objectid, parent ? BTRFS_FIRST_FREE_OBJECTID : fi_key.objectid, offset); @@ -4132,8 +4132,8 @@ static int repair_extent_item(struct btrfs_path *path, u64 bytenr, u64 goto out; } /* delete the backref */ - ret = btrfs_free_extent(trans, gfs_info->fs_root, bytenr, - num_bytes, parent, root_objectid, owner, offset); + ret = btrfs_free_extent(trans, bytenr, num_bytes, parent, root_objectid, + owner, offset); if (!ret) printf("Delete backref in extent [%llu %llu]\n", bytenr, num_bytes); diff --git a/kernel-shared/ctree.c b/kernel-shared/ctree.c index da9282b9..c3e9830a 100644 --- a/kernel-shared/ctree.c +++ b/kernel-shared/ctree.c @@ -491,8 +491,8 @@ static int __btrfs_cow_block(struct btrfs_trans_handle *trans, root->node = cow; extent_buffer_get(cow); - btrfs_free_extent(trans, root, buf->start, buf->len, - 0, root->root_key.objectid, level, 0); + btrfs_free_extent(trans, buf->start, buf->len, 0, + root->root_key.objectid, level, 0); free_extent_buffer(buf); add_root_to_dirty_list(root); } else { @@ -504,8 +504,8 @@ static int __btrfs_cow_block(struct btrfs_trans_handle *trans, btrfs_mark_buffer_dirty(parent); WARN_ON(btrfs_header_generation(parent) != trans->transid); - btrfs_free_extent(trans, root, buf->start, buf->len, - 0, root->root_key.objectid, level, 0); + btrfs_free_extent(trans, buf->start, buf->len, 0, + root->root_key.objectid, level, 0); } if (!list_empty(&buf->recow)) { list_del_init(&buf->recow); @@ -942,9 +942,8 @@ static int balance_level(struct btrfs_trans_handle *trans, root_sub_used(root, mid->len); - ret = btrfs_free_extent(trans, root, mid->start, mid->len, - 0, root->root_key.objectid, - level, 0); + ret = btrfs_free_extent(trans, mid->start, mid->len, 0, + root->root_key.objectid, level, 0); /* once for the root ptr */ free_extent_buffer(mid); return ret; @@ -999,10 +998,9 @@ static int balance_level(struct btrfs_trans_handle *trans, ret = wret; root_sub_used(root, blocksize); - wret = btrfs_free_extent(trans, root, bytenr, - blocksize, 0, - root->root_key.objectid, - level, 0); + wret = btrfs_free_extent(trans, bytenr, blocksize, 0, + root->root_key.objectid, level, + 0); if (wret) ret = wret; } else { @@ -1047,9 +1045,8 @@ static int balance_level(struct btrfs_trans_handle *trans, ret = wret; root_sub_used(root, blocksize); - wret = btrfs_free_extent(trans, root, bytenr, blocksize, - 0, root->root_key.objectid, - level, 0); + wret = btrfs_free_extent(trans, bytenr, blocksize, 0, + root->root_key.objectid, level, 0); if (wret) ret = wret; } else { @@ -2956,8 +2953,8 @@ static noinline int btrfs_del_leaf(struct btrfs_trans_handle *trans, root_sub_used(root, leaf->len); - ret = btrfs_free_extent(trans, root, leaf->start, leaf->len, - 0, root->root_key.objectid, 0, 0); + ret = btrfs_free_extent(trans, leaf->start, leaf->len, 0, + root->root_key.objectid, 0, 0); return ret; } diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h index d5cd7803..2f41b58d 100644 --- a/kernel-shared/ctree.h +++ b/kernel-shared/ctree.h @@ -875,12 +875,10 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans, struct extent_buffer *buf, u64 parent, int last_ref); int btrfs_free_extent(struct btrfs_trans_handle *trans, - struct btrfs_root *root, u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid, u64 owner, u64 offset); void btrfs_finish_extent_commit(struct btrfs_trans_handle *trans); int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, - struct btrfs_root *root, u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid, u64 owner, u64 offset); int btrfs_update_extent_ref(struct btrfs_trans_handle *trans, diff --git a/kernel-shared/extent-tree.c b/kernel-shared/extent-tree.c index 4dfb35d4..8d4483cd 100644 --- a/kernel-shared/extent-tree.c +++ b/kernel-shared/extent-tree.c @@ -1242,11 +1242,10 @@ static int remove_extent_backref(struct btrfs_trans_handle *trans, } int btrfs_inc_extent_ref(struct btrfs_trans_handle *trans, - struct btrfs_root *root, u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid, u64 owner, u64 offset) { - struct btrfs_root *extent_root = btrfs_extent_root(root->fs_info, + struct btrfs_root *extent_root = btrfs_extent_root(trans->fs_info, bytenr); struct btrfs_path *path; struct extent_buffer *leaf; @@ -1467,7 +1466,6 @@ static int __btrfs_mod_ref(struct btrfs_trans_handle *trans, int level; int ret = 0; int (*process_func)(struct btrfs_trans_handle *trans, - struct btrfs_root *root, u64, u64, u64, u64, u64, u64); ref_root = btrfs_header_owner(buf); @@ -1504,9 +1502,8 @@ static int __btrfs_mod_ref(struct btrfs_trans_handle *trans, num_bytes = btrfs_file_extent_disk_num_bytes(buf, fi); key.offset -= btrfs_file_extent_offset(buf, fi); - ret = process_func(trans, root, bytenr, num_bytes, - parent, ref_root, key.objectid, - key.offset); + ret = process_func(trans, bytenr, num_bytes, parent, + ref_root, key.objectid, key.offset); if (ret) { WARN_ON(1); goto fail; @@ -1514,8 +1511,8 @@ static int __btrfs_mod_ref(struct btrfs_trans_handle *trans, } else { bytenr = btrfs_node_blockptr(buf, i); num_bytes = root->fs_info->nodesize; - ret = process_func(trans, root, bytenr, num_bytes, - parent, ref_root, level - 1, 0); + ret = process_func(trans, bytenr, num_bytes, parent, + ref_root, level - 1, 0); if (ret) { WARN_ON(1); goto fail; @@ -2148,7 +2145,7 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans, struct extent_buffer *buf, u64 parent, int last_ref) { - return btrfs_free_extent(trans, root, buf->start, buf->len, parent, + return btrfs_free_extent(trans, buf->start, buf->len, parent, root->root_key.objectid, btrfs_header_level(buf), 0); } @@ -2158,13 +2155,12 @@ int btrfs_free_tree_block(struct btrfs_trans_handle *trans, */ int btrfs_free_extent(struct btrfs_trans_handle *trans, - struct btrfs_root *root, u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid, u64 owner, u64 offset) { int ret; - WARN_ON(num_bytes < root->fs_info->sectorsize); + WARN_ON(num_bytes < trans->fs_info->sectorsize); /* * tree log blocks never actually go into the extent allocation * tree, just update pinning info and exit early. @@ -2579,8 +2575,8 @@ struct extent_buffer *btrfs_alloc_tree_block(struct btrfs_trans_handle *trans, buf = btrfs_find_create_tree_block(root->fs_info, ins.objectid); if (!buf) { - btrfs_free_extent(trans, root, ins.objectid, ins.offset, - 0, root->root_key.objectid, level, 0); + btrfs_free_extent(trans, ins.objectid, ins.offset, 0, + root->root_key.objectid, level, 0); BUG_ON(1); return ERR_PTR(-ENOMEM); } @@ -3723,7 +3719,7 @@ static int __btrfs_record_file_extent(struct btrfs_trans_handle *trans, btrfs_set_stack_inode_nbytes(inode, nbytes); btrfs_release_path(path); - ret = btrfs_inc_extent_ref(trans, root, extent_bytenr, extent_num_bytes, + ret = btrfs_inc_extent_ref(trans, extent_bytenr, extent_num_bytes, 0, root->root_key.objectid, objectid, file_pos - extent_offset); if (ret) diff --git a/kernel-shared/free-space-cache.c b/kernel-shared/free-space-cache.c index 83897f10..7bd76e39 100644 --- a/kernel-shared/free-space-cache.c +++ b/kernel-shared/free-space-cache.c @@ -982,9 +982,8 @@ int btrfs_clear_free_space_cache(struct btrfs_trans_handle *trans, disk_bytenr = btrfs_file_extent_disk_bytenr(node, fi); disk_num_bytes = btrfs_file_extent_disk_num_bytes(node, fi); - ret = btrfs_free_extent(trans, tree_root, disk_bytenr, - disk_num_bytes, 0, tree_root->objectid, - ino, key.offset); + ret = btrfs_free_extent(trans, disk_bytenr, disk_num_bytes, 0, + tree_root->objectid, ino, key.offset); if (ret < 0) { error("failed to remove backref for disk bytenr %llu: %d", disk_bytenr, ret); From patchwork Wed Apr 19 21:23:55 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13217424 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 99A1EC77B73 for ; Wed, 19 Apr 2023 21:25:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230244AbjDSVYv (ORCPT ); Wed, 19 Apr 2023 17:24:51 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48494 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230077AbjDSVYp (ORCPT ); Wed, 19 Apr 2023 17:24:45 -0400 Received: from mail-qv1-xf2b.google.com (mail-qv1-xf2b.google.com [IPv6:2607:f8b0:4864:20::f2b]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D9A1F900F for ; Wed, 19 Apr 2023 14:24:20 -0700 (PDT) Received: by mail-qv1-xf2b.google.com with SMTP id oj8so995452qvb.11 for ; Wed, 19 Apr 2023 14:24:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1681939459; x=1684531459; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=wHULyHjm8jrmit9J0XZ0vy3FmOaKwBpbxRNheiOXiHA=; b=m1NIYYAwHGHXbi/jopeW6MKNTUowrvor5TNpqKGo54WD7twLwwmAwl9JAeoNhYEX0A 4s1ujqNIn9okSsTsyWrdrFrF6LXQv5h+u0krE0pJiEQiuObmMPpnlSRERUhzkA0222zX zA9iiPtLWUnJOOsKYMHzGQ5esyvNACNGMOh0rsJL0Yx8YOMUrz7RsyB7HLyDB3cw2Hq9 G40G0zKsEJFQUVnkXW0tvO7Vtx7el2G2ra43iRhbMdFscEd69L+Dq3rrGAsDvr+L5Hjh Z6yqnJeR0988MbGPP6NJ1mu0FgrMc3sD2v8SLLLDa9kpnlguDymCgXC8taQ03sHXZH91 1TuQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1681939459; x=1684531459; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=wHULyHjm8jrmit9J0XZ0vy3FmOaKwBpbxRNheiOXiHA=; b=kh+94T2KscRd/VFrBrqy5ZviLM55iX58lvVpS5lOF00pqayZH65BEFugnT7EDNPosd Ccgdyb/tbmOIJdWAfDGbp4FVa4lNLrfQq0bzxDsl2IxKRZG9L9svRkn9ggWlnBPJt1sC wU8Hw6LW/b713QAZB1hzkUKGB8oYpUYEu52zGpk9JAsCAhcCr604Hq1PEAlCUeyWsfwz UWdqOn0AuI84ylsY9H/FRb04iXkp4oM8AYZBXkNBolY+JIHaYq+JPZ8WfSBDhfH7bOJ6 lMWpvESf1z5nm95EN+arEbHPTNNDnI+ON093OlqhwoOAB3tmyW4LA8/QvlZgLEnn+ue5 8UHA== X-Gm-Message-State: AAQBX9dJia+L1MT2BQgSysC77TqX1PCNT+kv7KhTx5AQTAQGsqcKjBrH opmjPJmekPTgwlDqV3m2TMp0qziobegstp+eyt1jOg== X-Google-Smtp-Source: AKy350b/Pr1GeFDuDapt/J6DzZK1oU2IX5NeMC0FAhnu67Z+j+w4ntCzhu50yzpTPn0Nvx5VTHxERw== X-Received: by 2002:a05:6214:da7:b0:5ee:e4f8:c7e5 with SMTP id h7-20020a0562140da700b005eee4f8c7e5mr32896052qvh.41.1681939458783; Wed, 19 Apr 2023 14:24:18 -0700 (PDT) Received: from localhost (cpe-174-109-170-245.nc.res.rr.com. [174.109.170.245]) by smtp.gmail.com with ESMTPSA id b10-20020a056214002a00b005f160622f3esm1141500qvr.85.2023.04.19.14.24.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Apr 2023 14:24:18 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 04/18] btrfs-progs: pass root_id for btrfs_free_tree_block Date: Wed, 19 Apr 2023 17:23:55 -0400 Message-Id: <1f77ce90dbec9e4e26590b6ea83ff5e6f6df404a.1681939316.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org In the kernel we pass in the root_id for btrfs_free_tree_block instead of the root itself. Update the btrfs-progs version of the helper to match what we do in the kernel. Signed-off-by: Josef Bacik --- cmds/rescue.c | 3 ++- kernel-shared/ctree.h | 6 ++---- kernel-shared/disk-io.c | 2 +- kernel-shared/extent-tree.c | 9 +++------ 4 files changed, 8 insertions(+), 12 deletions(-) diff --git a/cmds/rescue.c b/cmds/rescue.c index b84166ea..5551374d 100644 --- a/cmds/rescue.c +++ b/cmds/rescue.c @@ -343,7 +343,8 @@ static int clear_uuid_tree(struct btrfs_fs_info *fs_info) ret = btrfs_clear_buffer_dirty(uuid_root->node); if (ret < 0) goto out; - ret = btrfs_free_tree_block(trans, uuid_root, uuid_root->node, 0, 1); + ret = btrfs_free_tree_block(trans, btrfs_root_id(uuid_root), + uuid_root->node, 0, 1); if (ret < 0) goto out; free_extent_buffer(uuid_root->node); diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h index 2f41b58d..c892d707 100644 --- a/kernel-shared/ctree.h +++ b/kernel-shared/ctree.h @@ -870,10 +870,8 @@ int btrfs_inc_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct extent_buffer *buf, int record_parent); int btrfs_dec_ref(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct extent_buffer *buf, int record_parent); -int btrfs_free_tree_block(struct btrfs_trans_handle *trans, - struct btrfs_root *root, - struct extent_buffer *buf, - u64 parent, int last_ref); +int btrfs_free_tree_block(struct btrfs_trans_handle *trans, u64 root_id, + struct extent_buffer *buf, u64 parent, int last_ref); int btrfs_free_extent(struct btrfs_trans_handle *trans, u64 bytenr, u64 num_bytes, u64 parent, u64 root_objectid, u64 owner, u64 offset); diff --git a/kernel-shared/disk-io.c b/kernel-shared/disk-io.c index 7bbcc381..9d93f331 100644 --- a/kernel-shared/disk-io.c +++ b/kernel-shared/disk-io.c @@ -2301,7 +2301,7 @@ int btrfs_delete_and_free_root(struct btrfs_trans_handle *trans, ret = btrfs_clear_buffer_dirty(root->node); if (ret) return ret; - ret = btrfs_free_tree_block(trans, root, root->node, 0, 1); + ret = btrfs_free_tree_block(trans, btrfs_root_id(root), root->node, 0, 1); if (ret) return ret; if (is_global_root(root)) diff --git a/kernel-shared/extent-tree.c b/kernel-shared/extent-tree.c index 8d4483cd..5c33fd53 100644 --- a/kernel-shared/extent-tree.c +++ b/kernel-shared/extent-tree.c @@ -2140,13 +2140,10 @@ fail: return ret; } -int btrfs_free_tree_block(struct btrfs_trans_handle *trans, - struct btrfs_root *root, - struct extent_buffer *buf, - u64 parent, int last_ref) +int btrfs_free_tree_block(struct btrfs_trans_handle *trans, u64 root_id, + struct extent_buffer *buf, u64 parent, int last_ref) { - return btrfs_free_extent(trans, buf->start, buf->len, parent, - root->root_key.objectid, + return btrfs_free_extent(trans, buf->start, buf->len, parent, root_id, btrfs_header_level(buf), 0); } From patchwork Wed Apr 19 21:23:56 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13217425 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0B371C77B78 for ; Wed, 19 Apr 2023 21:25:09 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232203AbjDSVYw (ORCPT ); Wed, 19 Apr 2023 17:24:52 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48548 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232249AbjDSVYs (ORCPT ); Wed, 19 Apr 2023 17:24:48 -0400 Received: from mail-qv1-xf2f.google.com (mail-qv1-xf2f.google.com [IPv6:2607:f8b0:4864:20::f2f]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C0EC57A87 for ; Wed, 19 Apr 2023 14:24:22 -0700 (PDT) Received: by mail-qv1-xf2f.google.com with SMTP id dd8so972862qvb.13 for ; Wed, 19 Apr 2023 14:24:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1681939460; x=1684531460; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=fpagXFsxJft6J5gLjue1iEq0+I5OWYJ4dq12KNrkuWE=; b=XPDsyna9hta5dbDJQQ11Cp+M/b4rEAlhvc4++X58GQK/3F39pK4Jjgu6CK0pJu48VO TV1qkd0Uo/tGeQNOfbxiSIghxslw/PZ5Xq2xHNZQiwJRRjGabF8dHCnS0K8aAUEHAbgp tE3VgwaMyXczKfLN5ogK7iKEu55X4BeIUXTOsbh/QcG5A0sP1k1BfL6Zg6hPYRmSwv4u Lv4t/IymtCUGtxYXD4/Bf22HyAufY9Cz2a0x6XjgJKDk3cyXBSuyLpRKRD9iqr33aouh VDWjkJp+MsjLFBWXCUMpoPlYggSQTfHuVgIn+hnXdyVg2EnlAjn3WjUaT1ShFeBbj4Ym G1rg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1681939460; x=1684531460; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=fpagXFsxJft6J5gLjue1iEq0+I5OWYJ4dq12KNrkuWE=; b=k0vznuDMPiRsbJqcqM6SmnoPvXp/onGkn4jmpOHTTrXC88pK6HVmlOb54WQFcIn9oR WiG4wmYkROfn+4Ovu66H2UHeXz6FqdpJCtPHnKNhBkvdmJ1BUjkjkmjmFZSw/z5vd1+h O2BwYhGlYtgRigsdKcRfTfZh2XRvRXa3IJ3X4qHy9Y4G79jBwm0U/vr8QxHSyS+JiyzC TgpSu7gf2x1+rzyalMYIo3rt4VIpLPqGsyLLplBOiEj32elqTj3QGVlKuqkP2r3/SaXM p7pnjgjP1eecb0GLU3jTsExWFY5ugS2iRy+wNTmh+wPEd0UOmlMjIYEk1RK1PpG2vU3R egcQ== X-Gm-Message-State: AAQBX9fR3MaWyOVdNmV1tXbmQCOn6MghNQYFe8nEjsc3eWn0PbPBsJO9 SjzymMz/HqnYk9y0xiZmpK9t49q8SRWWx5zLR+LWtQ== X-Google-Smtp-Source: AKy350b62Yn3hu4UuvvAbiG+6u1RHRBZic2VsMCqDjko1iUvzBpv+BahRG3IyQruQzZq2V712pVCew== X-Received: by 2002:a05:6214:29cc:b0:5b1:a698:43c6 with SMTP id gh12-20020a05621429cc00b005b1a69843c6mr22921128qvb.18.1681939460104; Wed, 19 Apr 2023 14:24:20 -0700 (PDT) Received: from localhost (cpe-174-109-170-245.nc.res.rr.com. [174.109.170.245]) by smtp.gmail.com with ESMTPSA id g24-20020a05620a219800b0074db94ed42fsm3036832qka.116.2023.04.19.14.24.19 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Apr 2023 14:24:19 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 05/18] btrfs-progs: add a free_extent_buffer_stale helper Date: Wed, 19 Apr 2023 17:23:56 -0400 Message-Id: <8960058259d45ddda23064faa3e782d28599a262.1681939316.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org This does exactly what free_extent_buffer_nocache does, but we call btrfs_free_extent_buffer_stale in the kernel code, so add this extra helper. Once the kernel code is sync'ed we can get rid of the old helper. Signed-off-by: Josef Bacik --- kernel-shared/extent_io.c | 5 +++++ kernel-shared/extent_io.h | 1 + 2 files changed, 6 insertions(+) diff --git a/kernel-shared/extent_io.c b/kernel-shared/extent_io.c index 4dff81bd..992b5f35 100644 --- a/kernel-shared/extent_io.c +++ b/kernel-shared/extent_io.c @@ -204,6 +204,11 @@ void free_extent_buffer_nocache(struct extent_buffer *eb) free_extent_buffer_internal(eb, 1); } +void free_extent_buffer_stale(struct extent_buffer *eb) +{ + free_extent_buffer_internal(eb, 1); +} + struct extent_buffer *find_extent_buffer(struct btrfs_fs_info *fs_info, u64 bytenr, u32 blocksize) { diff --git a/kernel-shared/extent_io.h b/kernel-shared/extent_io.h index 09f3c82a..e4da3c57 100644 --- a/kernel-shared/extent_io.h +++ b/kernel-shared/extent_io.h @@ -104,6 +104,7 @@ struct extent_buffer *alloc_dummy_extent_buffer(struct btrfs_fs_info *fs_info, u64 bytenr, u32 blocksize); void free_extent_buffer(struct extent_buffer *eb); void free_extent_buffer_nocache(struct extent_buffer *eb); +void free_extent_buffer_stale(struct extent_buffer *eb); int memcmp_extent_buffer(const struct extent_buffer *eb, const void *ptrv, unsigned long start, unsigned long len); void read_extent_buffer(const struct extent_buffer *eb, void *dst, From patchwork Wed Apr 19 21:23:57 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13217426 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id AD754C6FD18 for ; Wed, 19 Apr 2023 21:25:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S230077AbjDSVZJ (ORCPT ); Wed, 19 Apr 2023 17:25:09 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48514 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232095AbjDSVYv (ORCPT ); Wed, 19 Apr 2023 17:24:51 -0400 Received: from mail-qv1-xf34.google.com (mail-qv1-xf34.google.com [IPv6:2607:f8b0:4864:20::f34]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 4B12B5240 for ; Wed, 19 Apr 2023 14:24:24 -0700 (PDT) Received: by mail-qv1-xf34.google.com with SMTP id qf26so1046610qvb.6 for ; Wed, 19 Apr 2023 14:24:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1681939461; x=1684531461; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=/aGUmJ58PhF22BYrne7qOV0ewnxxkSCoZ+9LxhYk7Ro=; b=DZ+A0yWmeJv0r7bY4TLbu95FsLlxf6M7IwxGVLYWGrrNmAnGj/IgbHbwRYuTDsHvWV jvOEzvZbTF6f4Uk/GOU2h/++PgokYTsHyfUXSFLzJE8XZgSpdP1ha3L6F5whSlNdS1NM UFgYQb0YIPCxSYvc32C5OAMG72Qvm/g/AW2PxxAZgH11wFEIrXlw2y4JWu3p0BrbYoxn nbTc0qSZmldevPhlL2DOuYk/t5SG7nxxvoPsEZd/5AH7f5BwkQoRX7beVf3PEVAMAYfk ry6a8DAXh+nNb26lV2hlVtoDBKhip4526ZBsS4TkCtaKP8p69a4Gy9ZpafSuoxQAJCsu Vueg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1681939461; x=1684531461; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=/aGUmJ58PhF22BYrne7qOV0ewnxxkSCoZ+9LxhYk7Ro=; b=UQxB5QBPimxL98ajhbKKpyREPR1SnKl7Q5RwEQUa7MZPz21eRjrIdpvRqVB9J5H1na ks+rbNt1k2NhLZAiCxoyPnd6YAwDvmkfapzs3khHvXZ3AgRvD4s6vi2gofhgfFJf6Lc7 RTmslU0J0Cp7LF9cdvByLpepI0UmML3zO9J+D8/i7eTG7Rp2ao2Wzy6HGUJ0zHi5gvJ/ /2IPIcUDFtUpYYNYMjpHWjrZm8l6Dm2yLr3bTYrnnXltsYtqbf5wD/fxFXgNLnimcX44 M4AtIvsthkJci7RCN6B5XQouEUE/Ko7AI88lzTvSg01F5jAlLjsh064Xd5iW2DuqbPJT jf+A== X-Gm-Message-State: AAQBX9eGC5aMiMoU/++m41JNpN7i9o0+AojGJyKHfR+il9oTVVoSXImq p2DcfX8YxQ56ByQ5SOGmnxIpjjW2o/AV27udye1+/Q== X-Google-Smtp-Source: AKy350YBb0NuqxsIxcFiNSxaTnrXYAS5qny+3m88bjvX42uqFVotwOTBpE+bIBP1q9Cs5TADFuk5hQ== X-Received: by 2002:a05:6214:da7:b0:5ef:5138:1e4d with SMTP id h7-20020a0562140da700b005ef51381e4dmr34425818qvh.42.1681939461491; Wed, 19 Apr 2023 14:24:21 -0700 (PDT) Received: from localhost (cpe-174-109-170-245.nc.res.rr.com. [174.109.170.245]) by smtp.gmail.com with ESMTPSA id e23-20020a0caa57000000b005e3bda8a5e0sm12790qvb.6.2023.04.19.14.24.21 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Apr 2023 14:24:21 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 06/18] btrfs-progs: add btrfs_is_testing helper Date: Wed, 19 Apr 2023 17:23:57 -0400 Message-Id: X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org This is sprinkled throughout the kernel code for the in-kernel self tests. Add the helper to btrfs-progs to make it easier to sync the kernel code. Signed-off-by: Josef Bacik --- kernel-shared/ctree.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h index c892d707..26171288 100644 --- a/kernel-shared/ctree.h +++ b/kernel-shared/ctree.h @@ -389,6 +389,11 @@ static inline bool btrfs_is_zoned(const struct btrfs_fs_info *fs_info) return fs_info->zoned != 0; } +static inline bool btrfs_is_testing(const struct btrfs_fs_info *fs_info) +{ + return false; +} + /* * The state of btrfs root */ From patchwork Wed Apr 19 21:23:58 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13217429 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 3C093C77B73 for ; Wed, 19 Apr 2023 21:25:13 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232249AbjDSVZL (ORCPT ); Wed, 19 Apr 2023 17:25:11 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48382 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232422AbjDSVYw (ORCPT ); Wed, 19 Apr 2023 17:24:52 -0400 Received: from mail-qv1-xf36.google.com (mail-qv1-xf36.google.com [IPv6:2607:f8b0:4864:20::f36]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C5E1B6A42 for ; Wed, 19 Apr 2023 14:24:24 -0700 (PDT) Received: by mail-qv1-xf36.google.com with SMTP id qf26so1046649qvb.6 for ; Wed, 19 Apr 2023 14:24:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1681939463; x=1684531463; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=4TneaNOI5xPmx1jwrTCHvRShtF0V3syewlI+A4v4lew=; b=vOWI4xSgW+PJ+8f159QaZyiHIVucTjz+dFMYQwn0tvg1M8865Iuo5P+LU5lM4Q5qlq mJgt3KNUX1ifPywIm0lBfIWTrOPuQqd3NOA9YKe7xrdEgfSlKYpKyC4sv7S7C9fFjBw5 9waIRib3HSuEda0azR1L2vOv7zpLVBn9BOmGGUEGXsEMLJqf/iZeb/U3kY89K10Xy6lz 5qierU/SKprmyAYucjKClnMLuxJGaBUetINhy46eGUjDg5JGuzSXi+iU1v2CkimaqNu2 NIkjfpJ7MwlwyRsoVQIjgRMJ514m6f3ZDU2RvS/bveba4c5xhEZ4fxDrC/ohLlCjfoP/ MCug== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1681939463; x=1684531463; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=4TneaNOI5xPmx1jwrTCHvRShtF0V3syewlI+A4v4lew=; b=cyIRy239PaL37qWX4GKYdU8UUSKUtcxd2XIodLbKcOz6j9/CxLayBvNXG4OL4BeqY0 2YxNPx0ADfSTzeMadUQZsDnEgqgCMZ7T0rO0Gta3r4tZ0Lk4agXE+0G1j0sKr6O9PkxG 5CauS41XOGtTCseQOZcKW5xIt4ygA4Si0qjY7B1TLS1VBGiDhqsib/48sDlSf9Jm48dg lgeZBoBwz9BPs3fGvn4FCr9aSzx5QYM1CQfOj0qYI+3GLIFwXXFBz4P+Hh/yz/sseRkv N0KMobPXHeLLit4XAvPaibpEK6KfqPfaRMvYK9iwfbxhqAvavqgBbpj3RB60llraKZYd Ufow== X-Gm-Message-State: AAQBX9cpOnyUtwawkiDKGfzZZ9UT4s8N1Bo8301JZPCuIIqLVvn21XZt KRv4N+59sP3RgR2igsofGKyyIhSZqUO3nAeirOLShA== X-Google-Smtp-Source: AKy350ZOvKoNPrdOXVoolZF4UOU20zILlE0lyocTAGbicSk7WhlpsqHB0gZ9y7xnQgPgluEWiomPVg== X-Received: by 2002:a05:6214:1c86:b0:5ef:4435:f1cd with SMTP id ib6-20020a0562141c8600b005ef4435f1cdmr25400629qvb.27.1681939462658; Wed, 19 Apr 2023 14:24:22 -0700 (PDT) Received: from localhost (cpe-174-109-170-245.nc.res.rr.com. [174.109.170.245]) by smtp.gmail.com with ESMTPSA id k15-20020a0cf58f000000b005dd8b934595sm4878qvm.45.2023.04.19.14.24.22 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Apr 2023 14:24:22 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 07/18] btrfs-progs: add accounting_lock to btrfs_root Date: Wed, 19 Apr 2023 17:23:58 -0400 Message-Id: <0aae3e1c47df23420ca83ff78fd261dd819bd2ef.1681939316.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org This is used to protect the used count for btrfs_root in the kernel, sync it to btrfs-progs to allow us to sync ctree.c into btrfs-progs. Signed-off-by: Josef Bacik --- kernel-shared/ctree.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h index 26171288..50f97533 100644 --- a/kernel-shared/ctree.h +++ b/kernel-shared/ctree.h @@ -479,6 +479,8 @@ struct btrfs_root { /* the dirty list is only used by non-reference counted roots */ struct list_head dirty_list; struct rb_node rb_node; + + spinlock_t accounting_lock; }; static inline u64 btrfs_root_id(const struct btrfs_root *root) From patchwork Wed Apr 19 21:23:59 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13217427 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0312DC77B78 for ; Wed, 19 Apr 2023 21:25:11 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232036AbjDSVZK (ORCPT ); Wed, 19 Apr 2023 17:25:10 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48512 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232563AbjDSVYy (ORCPT ); Wed, 19 Apr 2023 17:24:54 -0400 Received: from mail-qv1-xf29.google.com (mail-qv1-xf29.google.com [IPv6:2607:f8b0:4864:20::f29]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 6AA3C83C9 for ; Wed, 19 Apr 2023 14:24:25 -0700 (PDT) Received: by mail-qv1-xf29.google.com with SMTP id 6a1803df08f44-5f6058c0761so35316d6.1 for ; Wed, 19 Apr 2023 14:24:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1681939464; x=1684531464; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=PWY3Qt1r6Ey9H4egsgksV4AVNvmQ7AFAyqpK0XWjEjY=; b=bBcCCZxFX59fhW6Yg+SCcx2EQ2IDCaU0cwIBnYSBnvti8h6qs9VpBKhD2kB+zbGIhx V6egiBPEuokcsnNlFrZQ5uybAk7X+jZhNYsL86oRZ5Jk0IF3V6+27LJPU20g8qYf7Zph 3alp2F8F0584ci87POm6UWnukPSUJY1FNFKT28I7Zybx5AD4vdx/RvSV7hCtYRfZ4MUX 0FiSyjccxOqp4pjlk8lhtb+GkE9yVa1A5UQD/4Xa8e/EGPIGZffRC1CfYs0UmwZVz89j Z2XW/x8VoQkgVjUGoWRhZcvSy9h/sWHlFifuBNs5rWAnUFICnBCu8vJ8DqRONDT96UvJ wxnA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1681939464; x=1684531464; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=PWY3Qt1r6Ey9H4egsgksV4AVNvmQ7AFAyqpK0XWjEjY=; b=gmWsKXcNxDlXNeemtB88crBWVEmWFyeRx4tiSfK5uNp6+WmDSWIle28qwo/asRxNTf Qr6S4ApmKHF+Fok0eyQGEYAj1CHlkLmhPFVnUOeNac0I67oFYUFSvhZakyz//fItERuO PdVcdxJZqEfM0kxLb0uxtPz6/BR783VFRVkDd2rtGEo01qzxYQeRKz3HZQV/aWvCmr5P SNDRlqMTbIc/i4UYuU+fMVNjX6GspucLq3W9y3IHMnl3SY/+d2YxbmUWAYcFE/J2u4gR cqtpB7c8EDNCcdXdokW2V5frmG9iemvV125mnL6UADMlMymWHme9Rf2PDBH31SDelQLq DY3g== X-Gm-Message-State: AAQBX9dr2PxXAgAyt8Y1rZVOZPZQySLm54SKgm8ivzVLu/j5M4L5awcg 6++ZQ6a9ylEGvVvZI/L751veslK8tRCdFmcX0r5c7g== X-Google-Smtp-Source: AKy350bWzBNGP1r7lN36vKrDUwQIIfyr0ipTmjnY+6xH/9fixKkpw1CW8xc4zxHRXUWm5zfBj1Q/Lg== X-Received: by 2002:a05:6214:509d:b0:5f1:31eb:1f21 with SMTP id kk29-20020a056214509d00b005f131eb1f21mr37556qvb.5.1681939463909; Wed, 19 Apr 2023 14:24:23 -0700 (PDT) Received: from localhost (cpe-174-109-170-245.nc.res.rr.com. [174.109.170.245]) by smtp.gmail.com with ESMTPSA id x16-20020a0ce250000000b005ef6b124d39sm12882qvl.5.2023.04.19.14.24.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Apr 2023 14:24:23 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 08/18] btrfs-progs: update read_tree_block to match the kernel definition Date: Wed, 19 Apr 2023 17:23:59 -0400 Message-Id: <793acf814cf36b0359df1094ad8fc71608b41b78.1681939316.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org The in-kernel version of read_tree_block adds some extra sanity checks to make sure we don't return blocks that don't match what we expect. This includes the owning root, the level, and the expected first key. We don't actually do these checks in btrfs-progs, however kernel code we're going to sync will expect this calling convention, so update it to match the in-kernel code and then update all the callers. Signed-off-by: Josef Bacik --- btrfs-corrupt-block.c | 8 +++++--- btrfs-find-root.c | 2 +- check/main.c | 9 ++++++--- check/mode-common.c | 4 ++-- check/mode-lowmem.c | 12 +++++++----- check/qgroup-verify.c | 3 ++- check/repair.c | 8 ++++++-- cmds/inspect-dump-tree.c | 12 +++++++----- cmds/inspect-tree-stats.c | 4 +++- cmds/restore.c | 6 ++++-- image/main.c | 11 ++++++----- kernel-shared/backref.c | 6 ++++-- kernel-shared/ctree.c | 4 +++- kernel-shared/disk-io.c | 8 +++++--- kernel-shared/disk-io.h | 5 +++-- kernel-shared/print-tree.c | 4 +++- tune/change-uuid.c | 2 +- 17 files changed, 68 insertions(+), 40 deletions(-) diff --git a/btrfs-corrupt-block.c b/btrfs-corrupt-block.c index 35933854..98cfe598 100644 --- a/btrfs-corrupt-block.c +++ b/btrfs-corrupt-block.c @@ -166,7 +166,7 @@ static int corrupt_keys_in_block(struct btrfs_fs_info *fs_info, u64 bytenr) { struct extent_buffer *eb; - eb = read_tree_block(fs_info, bytenr, 0); + eb = read_tree_block(fs_info, bytenr, 0, 0, 0, NULL); if (!extent_buffer_uptodate(eb)) return -EIO;; @@ -296,7 +296,9 @@ static void btrfs_corrupt_extent_tree(struct btrfs_trans_handle *trans, struct extent_buffer *next; next = read_tree_block(fs_info, btrfs_node_blockptr(eb, i), - btrfs_node_ptr_generation(eb, i)); + btrfs_header_owner(eb), + btrfs_node_ptr_generation(eb, i), + btrfs_header_level(eb) - 1, NULL); if (!extent_buffer_uptodate(next)) continue; btrfs_corrupt_extent_tree(trans, root, next); @@ -860,7 +862,7 @@ static int corrupt_metadata_block(struct btrfs_fs_info *fs_info, u64 block, return -EINVAL; } - eb = read_tree_block(fs_info, block, 0); + eb = read_tree_block(fs_info, block, 0, 0, 0, NULL); if (!extent_buffer_uptodate(eb)) { error("couldn't read in tree block %s", field); return -EINVAL; diff --git a/btrfs-find-root.c b/btrfs-find-root.c index 9d7296c3..398d7f21 100644 --- a/btrfs-find-root.c +++ b/btrfs-find-root.c @@ -199,7 +199,7 @@ int btrfs_find_root_search(struct btrfs_fs_info *fs_info, for (offset = chunk_offset; offset < chunk_offset + chunk_size; offset += nodesize) { - eb = read_tree_block(fs_info, offset, 0); + eb = read_tree_block(fs_info, offset, 0, 0, 0, NULL); if (!eb || IS_ERR(eb)) continue; ret = add_eb_to_result(eb, result, nodesize, filter, diff --git a/check/main.c b/check/main.c index 275f912b..610c3091 100644 --- a/check/main.c +++ b/check/main.c @@ -1898,7 +1898,9 @@ static int walk_down_tree(struct btrfs_root *root, struct btrfs_path *path, if (!next || !btrfs_buffer_uptodate(next, ptr_gen)) { free_extent_buffer(next); reada_walk_down(root, cur, path->slots[*level]); - next = read_tree_block(gfs_info, bytenr, ptr_gen); + next = read_tree_block(gfs_info, bytenr, + btrfs_header_owner(cur), ptr_gen, + *level - 1, NULL); if (!extent_buffer_uptodate(next)) { struct btrfs_key node_key; @@ -6269,7 +6271,7 @@ static int run_next_block(struct btrfs_root *root, } /* fixme, get the real parent transid */ - buf = read_tree_block(gfs_info, bytenr, gen); + buf = read_tree_block(gfs_info, bytenr, 0, gen, 0, NULL); if (!extent_buffer_uptodate(buf)) { record_bad_block_io(extent_cache, bytenr, size); goto out; @@ -8615,7 +8617,8 @@ static int deal_root_from_list(struct list_head *list, rec = list_entry(list->next, struct root_item_record, list); last = 0; - buf = read_tree_block(gfs_info, rec->bytenr, 0); + buf = read_tree_block(gfs_info, rec->bytenr, rec->objectid, 0, + rec->level, NULL); if (!extent_buffer_uptodate(buf)) { free_extent_buffer(buf); ret = -EIO; diff --git a/check/mode-common.c b/check/mode-common.c index 394c35fe..a38d2afc 100644 --- a/check/mode-common.c +++ b/check/mode-common.c @@ -132,7 +132,7 @@ static int check_prealloc_shared_data_ref(u64 parent, u64 disk_bytenr) int i; int ret = 0; - eb = read_tree_block(gfs_info, parent, 0); + eb = read_tree_block(gfs_info, parent, 0, 0, 0, NULL); if (!extent_buffer_uptodate(eb)) { ret = -EIO; goto out; @@ -1127,7 +1127,7 @@ int get_extent_item_generation(u64 bytenr, u64 *gen_ret) BTRFS_EXTENT_FLAG_TREE_BLOCK) { struct extent_buffer *eb; - eb = read_tree_block(gfs_info, bytenr, 0); + eb = read_tree_block(gfs_info, bytenr, 0, 0, 0, NULL); if (extent_buffer_uptodate(eb)) { *gen_ret = btrfs_header_generation(eb); ret = 0; diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c index 10f86161..83b86e63 100644 --- a/check/mode-lowmem.c +++ b/check/mode-lowmem.c @@ -3748,7 +3748,7 @@ static int query_tree_block_level(u64 bytenr) btrfs_release_path(&path); /* Get level from tree block as an alternative source */ - eb = read_tree_block(gfs_info, bytenr, transid); + eb = read_tree_block(gfs_info, bytenr, 0, transid, 0, NULL); if (!extent_buffer_uptodate(eb)) { free_extent_buffer(eb); return -EIO; @@ -3800,7 +3800,7 @@ static int check_tree_block_backref(u64 root_id, u64 bytenr, int level) } /* Read out the tree block to get item/node key */ - eb = read_tree_block(gfs_info, bytenr, 0); + eb = read_tree_block(gfs_info, bytenr, root_id, 0, 0, NULL); if (!extent_buffer_uptodate(eb)) { err |= REFERENCER_MISSING; free_extent_buffer(eb); @@ -3899,7 +3899,7 @@ static int check_shared_block_backref(u64 parent, u64 bytenr, int level) int found_parent = 0; int i; - eb = read_tree_block(gfs_info, parent, 0); + eb = read_tree_block(gfs_info, parent, 0, 0, 0, NULL); if (!extent_buffer_uptodate(eb)) goto out; @@ -4072,7 +4072,7 @@ static int check_shared_data_backref(u64 parent, u64 bytenr) int found_parent = 0; int i; - eb = read_tree_block(gfs_info, parent, 0); + eb = read_tree_block(gfs_info, parent, 0, 0, 0, NULL); if (!extent_buffer_uptodate(eb)) goto out; @@ -5046,7 +5046,9 @@ static int walk_down_tree(struct btrfs_root *root, struct btrfs_path *path, if (!next || !btrfs_buffer_uptodate(next, ptr_gen)) { free_extent_buffer(next); reada_walk_down(root, cur, path->slots[*level]); - next = read_tree_block(gfs_info, bytenr, ptr_gen); + next = read_tree_block(gfs_info, bytenr, + btrfs_header_owner(cur), + ptr_gen, *level - 1, NULL); if (!extent_buffer_uptodate(next)) { struct btrfs_key node_key; diff --git a/check/qgroup-verify.c b/check/qgroup-verify.c index db49e3c9..1a62009b 100644 --- a/check/qgroup-verify.c +++ b/check/qgroup-verify.c @@ -720,7 +720,8 @@ static int travel_tree(struct btrfs_fs_info *info, struct btrfs_root *root, // printf("travel_tree: bytenr: %llu\tnum_bytes: %llu\tref_parent: %llu\n", // bytenr, num_bytes, ref_parent); - eb = read_tree_block(info, bytenr, 0); + eb = read_tree_block(info, bytenr, btrfs_root_id(root), 0, + 0, NULL); if (!extent_buffer_uptodate(eb)) return -EIO; diff --git a/check/repair.c b/check/repair.c index 07c432b3..ec8b0196 100644 --- a/check/repair.c +++ b/check/repair.c @@ -108,7 +108,9 @@ static int traverse_tree_blocks(struct extent_io_tree *tree, * in, but for now this doesn't actually use the root so * just pass in extent_root. */ - tmp = read_tree_block(fs_info, bytenr, 0); + tmp = read_tree_block(fs_info, bytenr, key.objectid, 0, + btrfs_disk_root_level(eb, ri), + NULL); if (!extent_buffer_uptodate(tmp)) { fprintf(stderr, "Error reading root block\n"); return -EIO; @@ -133,7 +135,9 @@ static int traverse_tree_blocks(struct extent_io_tree *tree, continue; } - tmp = read_tree_block(fs_info, bytenr, 0); + tmp = read_tree_block(fs_info, bytenr, + btrfs_header_owner(eb), 0, + level - 1, NULL); if (!extent_buffer_uptodate(tmp)) { fprintf(stderr, "Error reading tree block\n"); return -EIO; diff --git a/cmds/inspect-dump-tree.c b/cmds/inspect-dump-tree.c index 4c93056b..7c524b04 100644 --- a/cmds/inspect-dump-tree.c +++ b/cmds/inspect-dump-tree.c @@ -58,9 +58,10 @@ static void print_extents(struct extent_buffer *eb) nr = btrfs_header_nritems(eb); for (i = 0; i < nr; i++) { - next = read_tree_block(fs_info, - btrfs_node_blockptr(eb, i), - btrfs_node_ptr_generation(eb, i)); + next = read_tree_block(fs_info, btrfs_node_blockptr(eb, i), + btrfs_header_owner(eb), + btrfs_node_ptr_generation(eb, i), + btrfs_header_level(eb) - 1, NULL); if (!extent_buffer_uptodate(next)) continue; if (btrfs_is_leaf(next) && btrfs_header_level(eb) != 1) { @@ -288,7 +289,7 @@ static int dump_print_tree_blocks(struct btrfs_fs_info *fs_info, goto next; } - eb = read_tree_block(fs_info, bytenr, 0); + eb = read_tree_block(fs_info, bytenr, 0, 0, 0, NULL); if (!extent_buffer_uptodate(eb)) { error("failed to read tree block %llu", bytenr); ret = -EIO; @@ -625,7 +626,8 @@ again: offset = btrfs_item_ptr_offset(leaf, slot); read_extent_buffer(leaf, &ri, offset, sizeof(ri)); - buf = read_tree_block(info, btrfs_root_bytenr(&ri), 0); + buf = read_tree_block(info, btrfs_root_bytenr(&ri), + key.objectid, 0, 0, NULL); if (!extent_buffer_uptodate(buf)) goto next; if (tree_id && found_key.objectid != tree_id) { diff --git a/cmds/inspect-tree-stats.c b/cmds/inspect-tree-stats.c index 08be1686..716aa008 100644 --- a/cmds/inspect-tree-stats.c +++ b/cmds/inspect-tree-stats.c @@ -153,7 +153,9 @@ static int walk_nodes(struct btrfs_root *root, struct btrfs_path *path, path->slots[level] = i; if ((level - 1) > 0 || find_inline) { tmp = read_tree_block(root->fs_info, cur_blocknr, - btrfs_node_ptr_generation(b, i)); + btrfs_header_owner(b), + btrfs_node_ptr_generation(b, i), + level - 1, NULL); if (!extent_buffer_uptodate(tmp)) { error("failed to read blocknr %llu", btrfs_node_blockptr(b, i)); diff --git a/cmds/restore.c b/cmds/restore.c index c38cb541..72fc7a07 100644 --- a/cmds/restore.c +++ b/cmds/restore.c @@ -1260,7 +1260,8 @@ static struct btrfs_root *open_fs(const char *dev, u64 root_location, root_location = btrfs_super_root(fs_info->super_copy); generation = btrfs_super_generation(fs_info->super_copy); root->node = read_tree_block(fs_info, root_location, - generation); + btrfs_root_id(root), generation, + 0, NULL); if (!extent_buffer_uptodate(root->node)) { error("opening tree root failed"); close_ctree(root); @@ -1527,7 +1528,8 @@ static int cmd_restore(const struct cmd_struct *cmd, int argc, char **argv) if (fs_location != 0) { free_extent_buffer(root->node); - root->node = read_tree_block(root->fs_info, fs_location, 0); + root->node = read_tree_block(root->fs_info, fs_location, 0, 0, + 0, NULL); if (!extent_buffer_uptodate(root->node)) { error("failed to read fs location"); ret = 1; diff --git a/image/main.c b/image/main.c index ae7acb96..92b0dbfa 100644 --- a/image/main.c +++ b/image/main.c @@ -707,7 +707,8 @@ static int flush_pending(struct metadump_struct *md, int done) u64 this_read = min((u64)md->root->fs_info->nodesize, size); - eb = read_tree_block(md->root->fs_info, start, 0); + eb = read_tree_block(md->root->fs_info, start, 0, 0, 0, + NULL); if (!extent_buffer_uptodate(eb)) { free(async->buffer); free(async); @@ -811,7 +812,7 @@ static int copy_tree_blocks(struct btrfs_root *root, struct extent_buffer *eb, continue; ri = btrfs_item_ptr(eb, i, struct btrfs_root_item); bytenr = btrfs_disk_root_bytenr(eb, ri); - tmp = read_tree_block(fs_info, bytenr, 0); + tmp = read_tree_block(fs_info, bytenr, 0, 0, 0, NULL); if (!extent_buffer_uptodate(tmp)) { error("unable to read log root block"); return -EIO; @@ -822,7 +823,7 @@ static int copy_tree_blocks(struct btrfs_root *root, struct extent_buffer *eb, return ret; } else { bytenr = btrfs_node_blockptr(eb, i); - tmp = read_tree_block(fs_info, bytenr, 0); + tmp = read_tree_block(fs_info, bytenr, 0, 0, 0, NULL); if (!extent_buffer_uptodate(tmp)) { error("unable to read log root block"); return -EIO; @@ -2697,7 +2698,7 @@ static int iter_tree_blocks(struct btrfs_fs_info *fs_info, continue; ri = btrfs_item_ptr(eb, i, struct btrfs_root_item); bytenr = btrfs_disk_root_bytenr(eb, ri); - tmp = read_tree_block(fs_info, bytenr, 0); + tmp = read_tree_block(fs_info, bytenr, 0, 0, 0, NULL); if (!extent_buffer_uptodate(tmp)) { error("unable to read log root block"); return -EIO; @@ -2708,7 +2709,7 @@ static int iter_tree_blocks(struct btrfs_fs_info *fs_info, return ret; } else { bytenr = btrfs_node_blockptr(eb, i); - tmp = read_tree_block(fs_info, bytenr, 0); + tmp = read_tree_block(fs_info, bytenr, 0, 0, 0, NULL); if (!extent_buffer_uptodate(tmp)) { error("unable to read log root block"); return -EIO; diff --git a/kernel-shared/backref.c b/kernel-shared/backref.c index 897cd089..3b979430 100644 --- a/kernel-shared/backref.c +++ b/kernel-shared/backref.c @@ -461,7 +461,8 @@ static int __add_missing_keys(struct btrfs_fs_info *fs_info, ASSERT(!ref->parent); ASSERT(!ref->key_for_search.type); BUG_ON(!ref->wanted_disk_byte); - eb = read_tree_block(fs_info, ref->wanted_disk_byte, 0); + eb = read_tree_block(fs_info, ref->wanted_disk_byte, + ref->root_id, 0, ref->level - 1, NULL); if (!extent_buffer_uptodate(eb)) { free_extent_buffer(eb); return -EIO; @@ -823,7 +824,8 @@ static int find_parent_nodes(struct btrfs_trans_handle *trans, ref->level == 0) { struct extent_buffer *eb; - eb = read_tree_block(fs_info, ref->parent, 0); + eb = read_tree_block(fs_info, ref->parent, 0, + 0, ref->level, NULL); if (!extent_buffer_uptodate(eb)) { free_extent_buffer(eb); ret = -EIO; diff --git a/kernel-shared/ctree.c b/kernel-shared/ctree.c index c3e9830a..35133268 100644 --- a/kernel-shared/ctree.c +++ b/kernel-shared/ctree.c @@ -874,7 +874,9 @@ struct extent_buffer *read_node_slot(struct btrfs_fs_info *fs_info, return NULL; ret = read_tree_block(fs_info, btrfs_node_blockptr(parent, slot), - btrfs_node_ptr_generation(parent, slot)); + btrfs_header_owner(parent), + btrfs_node_ptr_generation(parent, slot), + level - 1, NULL); if (!extent_buffer_uptodate(ret)) return ERR_PTR(-EIO); diff --git a/kernel-shared/disk-io.c b/kernel-shared/disk-io.c index 9d93f331..688b1c8e 100644 --- a/kernel-shared/disk-io.c +++ b/kernel-shared/disk-io.c @@ -337,8 +337,9 @@ int read_whole_eb(struct btrfs_fs_info *info, struct extent_buffer *eb, int mirr return 0; } -struct extent_buffer* read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr, - u64 parent_transid) +struct extent_buffer *read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr, + u64 owner_root, u64 parent_transid, + int level, struct btrfs_key *first_key) { int ret; struct extent_buffer *eb; @@ -510,7 +511,8 @@ static int read_root_node(struct btrfs_fs_info *fs_info, struct btrfs_root *root, u64 bytenr, u64 gen, int level) { - root->node = read_tree_block(fs_info, bytenr, gen); + root->node = read_tree_block(fs_info, bytenr, btrfs_root_id(root), + gen, level, NULL); if (!extent_buffer_uptodate(root->node)) goto err; if (btrfs_header_level(root->node) != level) { diff --git a/kernel-shared/disk-io.h b/kernel-shared/disk-io.h index 2424060d..f349b3ef 100644 --- a/kernel-shared/disk-io.h +++ b/kernel-shared/disk-io.h @@ -138,8 +138,9 @@ static inline u64 btrfs_sb_offset(int mirror) struct btrfs_device; int read_whole_eb(struct btrfs_fs_info *info, struct extent_buffer *eb, int mirror); -struct extent_buffer* read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr, - u64 parent_transid); +struct extent_buffer *read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr, + u64 owner_root, u64 parent_transid, + int level, struct btrfs_key *first_key); void readahead_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr, u64 parent_transid); diff --git a/kernel-shared/print-tree.c b/kernel-shared/print-tree.c index d536b2ff..6cdfdef7 100644 --- a/kernel-shared/print-tree.c +++ b/kernel-shared/print-tree.c @@ -1557,7 +1557,9 @@ static void dfs_print_children(struct extent_buffer *root_eb, unsigned int mode) for (i = 0; i < nr; i++) { next = read_tree_block(fs_info, btrfs_node_blockptr(root_eb, i), - btrfs_node_ptr_generation(root_eb, i)); + btrfs_header_owner(root_eb), + btrfs_node_ptr_generation(root_eb, i), + root_eb_level, NULL); if (!extent_buffer_uptodate(next)) { fprintf(stderr, "failed to read %llu in tree %llu\n", btrfs_node_blockptr(root_eb, i), diff --git a/tune/change-uuid.c b/tune/change-uuid.c index 628a1bba..dae41056 100644 --- a/tune/change-uuid.c +++ b/tune/change-uuid.c @@ -111,7 +111,7 @@ static int change_extent_tree_uuid(struct btrfs_fs_info *fs_info, uuid_t new_fsi goto next; bytenr = key.objectid; - eb = read_tree_block(fs_info, bytenr, 0); + eb = read_tree_block(fs_info, bytenr, 0, 0, 0, NULL); if (IS_ERR(eb)) { error("failed to read tree block: %llu", bytenr); ret = PTR_ERR(eb); From patchwork Wed Apr 19 21:24:00 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13217430 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B2955C6FD18 for ; Wed, 19 Apr 2023 21:25:15 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232411AbjDSVZN (ORCPT ); Wed, 19 Apr 2023 17:25:13 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:47796 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232659AbjDSVY5 (ORCPT ); Wed, 19 Apr 2023 17:24:57 -0400 Received: from mail-qv1-xf34.google.com (mail-qv1-xf34.google.com [IPv6:2607:f8b0:4864:20::f34]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3346B5FE9 for ; Wed, 19 Apr 2023 14:24:27 -0700 (PDT) Received: by mail-qv1-xf34.google.com with SMTP id me15so1100039qvb.4 for ; Wed, 19 Apr 2023 14:24:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1681939465; x=1684531465; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=AYxJwfplDQ982XTUrmfS13Uhz8ITO+4fKZPwQuX5rag=; b=rA+gHAOYg7y+cvYFB3umqUzmu5uSXhhGVpnSqopNZ9hlgPBru07Q9x9+VDGHV1wcAU lu9SwXMtYdhhD1UF5MLs2iN1NTcAjg0clyqbpargFcB4uF7GNxraso1zBMcNwplgucVE evWAebmM+WGBU/d8oly+XgAL7Z4XQ440jVTas5o0J6dOcg1brlPW/7HpZday1WKHv+D2 78E59yZujCgPMpiz0hcv7IS2epNbmIjzxQiLYwQwjGnu2g0rw0unL4pkdSw+SE33/le+ 3MBEwU3Q+mm2oe2qL851uYqBuUpAw7NgVBmyClrbyqMeSCJYYIrVN/LpqiTwIf8p4tLS VRFQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1681939465; x=1684531465; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=AYxJwfplDQ982XTUrmfS13Uhz8ITO+4fKZPwQuX5rag=; b=TvG85PgUuwZMKInAOgi3dbz1jK7p6wWlfvLy7qYrIH/h8tHxT28zKRVtcerUmYmZWK D33zv/jL+Ccz9ICeiYvnQb0t41ti7l6+v29CPCjTweP5zANS+JxXTPTWpO2Z7RBLt/De lb/mtWnMPAYoYKICqIOIbzJzAFRJ0JbE5W8a56Mzau8TCpX535g37JaEQQ3Kfpo3VgJY smLZzbHlLx50ub18di57VX7atmPNcs8aL2cReF/qJ/E1nIW3jiNYUEkEIouZ68+mUy+d itx8kOGvxMim70lUo1Q4ctB5ZxwBwtAF17ihB1muWVcTp1mTVE/h6FjUj57BLdoO56Na U9yg== X-Gm-Message-State: AAQBX9cK5hMJPTmQh+YzDfKvC7BOJ23atfJYr+YGck0vRygDHOhrCiwy BXmH/fEK4QUdCOS/KuR8yQuA5f2NW6W8a9lV/WedHQ== X-Google-Smtp-Source: AKy350ZS/Qixy3j6JE0RK4fXDZQpxmTHqDvp0uewKqelxu1mYwgGxgsIroLPsvtAZXyZW7fgy9BiGg== X-Received: by 2002:a05:6214:409:b0:5c1:59b9:40b4 with SMTP id z9-20020a056214040900b005c159b940b4mr36316765qvx.48.1681939465169; Wed, 19 Apr 2023 14:24:25 -0700 (PDT) Received: from localhost (cpe-174-109-170-245.nc.res.rr.com. [174.109.170.245]) by smtp.gmail.com with ESMTPSA id y19-20020a0cd993000000b005f66296da7bsm208877qvj.94.2023.04.19.14.24.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Apr 2023 14:24:24 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 09/18] btrfs-progs: make reada_for_search static Date: Wed, 19 Apr 2023 17:24:00 -0400 Message-Id: <0bce8f5d59f15495ebee3491b7991296728cbef5.1681939316.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org We were using this in cmds/restore.c, however it only does anything if path->reada is set, and we don't set that in cmds/restore.c. Remove this usage of reada_for_search and make the function static. Signed-off-by: Josef Bacik --- cmds/restore.c | 5 ----- kernel-shared/ctree.c | 5 +++-- kernel-shared/ctree.h | 2 -- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/cmds/restore.c b/cmds/restore.c index 72fc7a07..9fe7b4d2 100644 --- a/cmds/restore.c +++ b/cmds/restore.c @@ -267,9 +267,6 @@ again: continue; } - if (path->reada) - reada_for_search(fs_info, path, level, slot, 0); - next = read_node_slot(fs_info, c, slot); if (extent_buffer_uptodate(next)) break; @@ -284,8 +281,6 @@ again: path->slots[level] = 0; if (!level) break; - if (path->reada) - reada_for_search(fs_info, path, level, 0, 0); next = read_node_slot(fs_info, next, 0); if (!extent_buffer_uptodate(next)) goto again; diff --git a/kernel-shared/ctree.c b/kernel-shared/ctree.c index 35133268..3e1085a0 100644 --- a/kernel-shared/ctree.c +++ b/kernel-shared/ctree.c @@ -1205,8 +1205,9 @@ static int noinline push_nodes_for_insert(struct btrfs_trans_handle *trans, /* * readahead one full node of leaves */ -void reada_for_search(struct btrfs_fs_info *fs_info, struct btrfs_path *path, - int level, int slot, u64 objectid) +static void reada_for_search(struct btrfs_fs_info *fs_info, + struct btrfs_path *path, int level, int slot, + u64 objectid) { struct extent_buffer *node; struct btrfs_disk_key disk_key; diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h index 50f97533..2237f3ef 100644 --- a/kernel-shared/ctree.h +++ b/kernel-shared/ctree.h @@ -929,8 +929,6 @@ int btrfs_del_ptr(struct btrfs_root *root, struct btrfs_path *path, int level, int slot); enum btrfs_tree_block_status btrfs_check_node(struct extent_buffer *buf); enum btrfs_tree_block_status btrfs_check_leaf(struct extent_buffer *buf); -void reada_for_search(struct btrfs_fs_info *fs_info, struct btrfs_path *path, - int level, int slot, u64 objectid); struct extent_buffer *read_node_slot(struct btrfs_fs_info *fs_info, struct extent_buffer *parent, int slot); int btrfs_previous_item(struct btrfs_root *root, From patchwork Wed Apr 19 21:24:01 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13217428 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 039B8C7EE20 for ; Wed, 19 Apr 2023 21:25:14 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232367AbjDSVZM (ORCPT ); Wed, 19 Apr 2023 17:25:12 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48676 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232716AbjDSVY5 (ORCPT ); Wed, 19 Apr 2023 17:24:57 -0400 Received: from mail-qv1-xf30.google.com (mail-qv1-xf30.google.com [IPv6:2607:f8b0:4864:20::f30]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 496738A53 for ; Wed, 19 Apr 2023 14:24:27 -0700 (PDT) Received: by mail-qv1-xf30.google.com with SMTP id js7so1059119qvb.5 for ; Wed, 19 Apr 2023 14:24:27 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1681939466; x=1684531466; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=KPi05GrOmULFBxsbJn21zlh/LOMtzj7Z7v+BilayxhY=; b=odBH9J1qrlYDTGvGhFNcaYtJFS8yUfH02LCQE6IuOHqCTH9V2CWyUOwc329GJtKznQ lazkULHdgnhI+2om1o55pHd4p/HlTW9sAE6HXK+ILiMtvHOmJLHnD5c4kbpr4yJ6/Din 5SqcedZdaw48MLQOy8Jdj/LXpkcKk7vd2nnVMNf2DIt7UlelNxKw2vA4ooXoSClgG70W wGhXVDLtaspX0SsJH/u277FGIAjvzg/A/bx0tWbLp1dZ9QvNp6YiibYBiw+JhGQzky3v AailR4IaQrvJdFd7u2QWDr6M2e7D39HgGlvaZX5JYUTdaV7QMVqCXnskms2FwBBZw/th znQg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1681939466; x=1684531466; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=KPi05GrOmULFBxsbJn21zlh/LOMtzj7Z7v+BilayxhY=; b=CxZQIqWo/qPN3Pco++7sCRA9j6/g90aPOMWuhZjlqOCTmfWQRpo9myanP064rUX47g wEG9LEY1yucHQNhZ8mKMEo7VH7Oh7TLtCaIuZRtR1QyKUc8M3WmrV+TTe26hKQDFAm1c iAqBFd83gq7aU7vVV49x4jNv/2qYifzWtoAvn3oyvzyBkrFRLRGMHRBxHoJ5dN0l+yjg f5Zc/Z5vCjmKbbMiOAbKcvln66YwDWCh2E+Lm8UYqcPZiuaABdoJ0ri6gDJjcxVpYW0S X1j25AF+G3s4gJ4NApCkihMdrxvh2gmnY1PT/qrtTCMuhELgYgWV0WoYCDoQtu51WAus XLjA== X-Gm-Message-State: AAQBX9fHmKxv/HPYNIEDu+61O8LfGbSAZaDWimSweaRxpQjTqCUUIvFL gwu4UrDu0yeaeANUMHl5Qp/3M/Q/UtyTTMQphbVqbQ== X-Google-Smtp-Source: AKy350ZlJmKjYw75kKwblNYIr3t9+7ZM+bHQ3YrVoN/5S1T55pY++RlibK+F+C5KSXa7wtARyCOCxQ== X-Received: by 2002:a05:6214:e4f:b0:5ef:8159:b9a9 with SMTP id o15-20020a0562140e4f00b005ef8159b9a9mr16084665qvc.21.1681939466429; Wed, 19 Apr 2023 14:24:26 -0700 (PDT) Received: from localhost (cpe-174-109-170-245.nc.res.rr.com. [174.109.170.245]) by smtp.gmail.com with ESMTPSA id i10-20020a0cab4a000000b005e5afa59f3dsm5933qvb.39.2023.04.19.14.24.25 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Apr 2023 14:24:26 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 10/18] btrfs-progs: sync btrfs_path fields with the kernel Date: Wed, 19 Apr 2023 17:24:01 -0400 Message-Id: X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org When we sync ctree.c into btrfs-progs we're going to need to have a bunch of flags and definitions that exist in btrfs_path in the kernel that do not exist in btrfs_progs. Sync these changes into btrfs-progs to enable us to sync ctree.c into btrfs-progs. Signed-off-by: Josef Bacik --- kernel-shared/ctree.h | 41 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 36 insertions(+), 5 deletions(-) diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h index 2237f3ef..20c9edc6 100644 --- a/kernel-shared/ctree.h +++ b/kernel-shared/ctree.h @@ -129,14 +129,32 @@ static inline u32 __BTRFS_LEAF_DATA_SIZE(u32 nodesize) * The slots array records the index of the item or block pointer * used while walking the tree. */ -enum { READA_NONE = 0, READA_BACK, READA_FORWARD }; +enum { + READA_NONE, + READA_BACK, + READA_FORWARD, + /* + * Similar to READA_FORWARD but unlike it: + * + * 1) It will trigger readahead even for leaves that are not close to + * each other on disk; + * 2) It also triggers readahead for nodes; + * 3) During a search, even when a node or leaf is already in memory, it + * will still trigger readahead for other nodes and leaves that follow + * it. + * + * This is meant to be used only when we know we are iterating over the + * entire tree or a very large part of it. + */ + READA_FORWARD_ALWAYS, +}; + struct btrfs_path { struct extent_buffer *nodes[BTRFS_MAX_LEVEL]; int slots[BTRFS_MAX_LEVEL]; -#if 0 /* The kernel locking scheme is not done in userspace. */ int locks[BTRFS_MAX_LEVEL]; -#endif + signed char reada; /* keep some upper locks as we walk down */ u8 lowest_level; @@ -145,8 +163,21 @@ struct btrfs_path { * set by btrfs_split_item, tells search_slot to keep all locks * and to force calls to keep space in the nodes */ - u8 search_for_split; - u8 skip_check_block; + unsigned int search_for_split:1; + unsigned int keep_locks:1; + unsigned int skip_locking:1; + unsigned int search_commit_root:1; + unsigned int need_commit_sem:1; + unsigned int skip_release_on_error:1; + /* + * Indicate that new item (btrfs_search_slot) is extending already + * existing item and ins_len contains only the data size and not item + * header (ie. sizeof(struct btrfs_item) is not included). + */ + unsigned int search_for_extension:1; + /* Stop search if any locks need to be taken (for read) */ + unsigned int nowait:1; + unsigned int skip_check_block:1; }; #define BTRFS_MAX_EXTENT_ITEM_SIZE(r) \ From patchwork Wed Apr 19 21:24:02 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13217431 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 10395C77B73 for ; Wed, 19 Apr 2023 21:25:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232165AbjDSVZP (ORCPT ); Wed, 19 Apr 2023 17:25:15 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48676 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232791AbjDSVY7 (ORCPT ); Wed, 19 Apr 2023 17:24:59 -0400 Received: from mail-qt1-x834.google.com (mail-qt1-x834.google.com [IPv6:2607:f8b0:4864:20::834]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 12CD693F4 for ; Wed, 19 Apr 2023 14:24:30 -0700 (PDT) Received: by mail-qt1-x834.google.com with SMTP id u37so614942qtc.10 for ; Wed, 19 Apr 2023 14:24:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1681939468; x=1684531468; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=NG7Dbkejip9+x4XlvwyLfvoLHh2Gff9UKUY/juBnKik=; b=FSOWDo3jD5kbkKqWHwGnj5nzFAh7SMVaYWlICaoHHtScyZTyTAsRfWAD16aG6AueYF G4xTacND379sU6abvLB+T1PjEDI2tY1oCkQ4xISAiWXK4pIZ8bqBV8Wcl1jL50A6KVyc z0MJ/n9Ne9ZHovhP29GCg8gHDq8NTJvSWZzvbQscxY2OKIPZrq6wCMGKngJVZG5tr3iH QtHDHMxQCaDiZaJGSlQjHSJ4hVvyFzhwrYN4S6SBlPfRbww82pF7sdQM6AlvD+Ej3tyf T0GqHP4xj9X/B4adlQ+4eHshmXCs4RTcrtDvLoyexZQkfz/8yerb9v8tIiRBh9wprtOd wlAQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1681939468; x=1684531468; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=NG7Dbkejip9+x4XlvwyLfvoLHh2Gff9UKUY/juBnKik=; b=aAyAR5wMIf5VQp4AM7UB/Ru79nTEZnt1OhHiNRC9zj3R1mDCz6PmVsN5dMLuhzwuSj B0mepzQU9mOrGcccI3keRafW8PrEM3VPMSRKBlZnwkY3/iJPJPtDDngaUwgbmmpOAizF Lwe0a5yNZfIoXokxFzKOXmffLmMlaBfWOctMnQugtb4zjPacVHA6fQt24mf2lYzkHuYW YSCHeB7GRTIef/9KJy14sPT3ZDfMpy0XD9nPP8+8Kum/67KFKcSieAK7PFHxHGYD72pg FvyBrO9AB9jHoLxj7atUfEYRHqHOlrqHlPsno751Us/ZE2TWPyEU2Nd7+7GwLYGPYRl8 Ykyw== X-Gm-Message-State: AAQBX9f2GY+ZI9MBvcSPWhsl/G2hmq9iB4N4yalXUv+lcjYGX1q07GoB HP2hIEYyECj3FvWgKZCG/E1f5NxxvfGSeuieb46WYw== X-Google-Smtp-Source: AKy350Yvx/v5Ma7FOIwS7CtVlhseVZetsx150euQ/2rMqx6sqQi/Lh5QcapbnSduToAbuoHDr+fG7w== X-Received: by 2002:ac8:7d52:0:b0:3e3:8bbc:d152 with SMTP id h18-20020ac87d52000000b003e38bbcd152mr8071341qtb.66.1681939467642; Wed, 19 Apr 2023 14:24:27 -0700 (PDT) Received: from localhost (cpe-174-109-170-245.nc.res.rr.com. [174.109.170.245]) by smtp.gmail.com with ESMTPSA id fu36-20020a05622a5da400b003ec4b2ca4f8sm42122qtb.35.2023.04.19.14.24.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Apr 2023 14:24:27 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 11/18] btrfs-progs: update arguments of find_extent_buffer Date: Wed, 19 Apr 2023 17:24:02 -0400 Message-Id: <919bf2d763a0caaaceaf00e0fc82b9ca3ca60b8d.1681939316.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org In the kernel we only take a bytenr for this as the extent buffer cache is indexed on bytenr. Since we're passing in the btrfs_fs_info we can simply use the ->nodesize for the blocksize, and drop the blocksize argument completely. This brings us into parity with the kernel, which will allow the syncing of ctree.c. Signed-off-by: Josef Bacik --- kernel-shared/disk-io.c | 2 +- kernel-shared/extent_io.c | 7 ++++--- kernel-shared/extent_io.h | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/kernel-shared/disk-io.c b/kernel-shared/disk-io.c index 688b1c8e..3b3188da 100644 --- a/kernel-shared/disk-io.c +++ b/kernel-shared/disk-io.c @@ -228,7 +228,7 @@ static int csum_tree_block(struct btrfs_fs_info *fs_info, struct extent_buffer *btrfs_find_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr, u32 blocksize) { - return find_extent_buffer(fs_info, bytenr, blocksize); + return find_extent_buffer(fs_info, bytenr); } struct extent_buffer* btrfs_find_create_tree_block( diff --git a/kernel-shared/extent_io.c b/kernel-shared/extent_io.c index 992b5f35..d6705e37 100644 --- a/kernel-shared/extent_io.c +++ b/kernel-shared/extent_io.c @@ -210,14 +210,15 @@ void free_extent_buffer_stale(struct extent_buffer *eb) } struct extent_buffer *find_extent_buffer(struct btrfs_fs_info *fs_info, - u64 bytenr, u32 blocksize) + u64 bytenr) { struct extent_buffer *eb = NULL; struct cache_extent *cache; - cache = lookup_cache_extent(&fs_info->extent_cache, bytenr, blocksize); + cache = lookup_cache_extent(&fs_info->extent_cache, bytenr, + fs_info->nodesize); if (cache && cache->start == bytenr && - cache->size == blocksize) { + cache->size == fs_info->nodesize) { eb = container_of(cache, struct extent_buffer, cache_node); list_move_tail(&eb->lru, &fs_info->lru); eb->refs++; diff --git a/kernel-shared/extent_io.h b/kernel-shared/extent_io.h index e4da3c57..b4c2ac97 100644 --- a/kernel-shared/extent_io.h +++ b/kernel-shared/extent_io.h @@ -94,7 +94,7 @@ static inline int extent_buffer_uptodate(struct extent_buffer *eb) } struct extent_buffer *find_extent_buffer(struct btrfs_fs_info *fs_info, - u64 bytenr, u32 blocksize); + u64 bytenr); struct extent_buffer *find_first_extent_buffer(struct btrfs_fs_info *fs_info, u64 start); struct extent_buffer *alloc_extent_buffer(struct btrfs_fs_info *fs_info, From patchwork Wed Apr 19 21:24:03 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13217432 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1A35BC6FD18 for ; Wed, 19 Apr 2023 21:25:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231473AbjDSVZR (ORCPT ); Wed, 19 Apr 2023 17:25:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48382 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232838AbjDSVZA (ORCPT ); Wed, 19 Apr 2023 17:25:00 -0400 Received: from mail-qt1-x834.google.com (mail-qt1-x834.google.com [IPv6:2607:f8b0:4864:20::834]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 3DD6E76B0 for ; Wed, 19 Apr 2023 14:24:31 -0700 (PDT) Received: by mail-qt1-x834.google.com with SMTP id z1so655962qti.5 for ; Wed, 19 Apr 2023 14:24:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1681939469; x=1684531469; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=XEL8Jvl2jhMW5AIP7diIZfQqZmWxcPA/o01KuBDKjfc=; b=l04eIrnUlaymQ63HD2M9IiM6SuI3QveXnijYi/tvaHgx9qjeJldxPGeNWTe9w5hppc KhU0dHUXaeyOLZ5Ig5BpyVdD2Qlyf8j50YACzfl0gcHYPf4Koq0pbgw8DNBDqBcaY2HV uw8qWwO867+Q4zcIUTgoTfjsPLPtEL9wJ+/q+xHAEYY9jcU8PBnOlA+G1FegbaM0adCY L4IR07mVwtAumAW4S+d/dhqY42Qp8S/iLSi8kRVwZueNtb4kq4TF7NJKVIwlpFFyE3jD 9DTjfwN3feJtE+0cTJn/RrQ6njWesQ0dtZDH6pncFFRaOoLCHR0jYQtCIZSpaUoyjodL xmzA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1681939469; x=1684531469; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=XEL8Jvl2jhMW5AIP7diIZfQqZmWxcPA/o01KuBDKjfc=; b=B0JuTOC3Ru7CZXy7aNWxQokG3XfgQ4zF+WZXVgCaGOOOc3fqgpcXRGm46K7g71qyUL Ucya8scW5SwlXwEnnyikzs7vVlzHd6M4i821oq863WiZCM0EA/Sc9ixqy47GhkmDpyDe fyPwS7+K0dW3hLqjFfqeU42kiVJCtcGlTvuz/aLFeePxrUWPBRLTnwEmm2cBdflaTMTD eLwXRcsOo+eMkFgCJ8vCL/rlqDkSZ7pxEotbJcdGqLnWStxeliqf6CxaAJrQalEtg/B3 JPuDaywNCm8nf3OrqA50OYCJTMDXYMsQIKHKgjXTh9/IwPW1nFBZ4o40pT1aIX9KAHbe yn7g== X-Gm-Message-State: AAQBX9esZRkmoDinQBYUKJVIe4AjLZTHWDKAFxJYM45jY0jV5hZJQ8nA wDgQpg9kwfofqSCz6hQG8wV6K+Gq4VGI0ZPz3ruabg== X-Google-Smtp-Source: AKy350Z3clPhl2J43pQfDy957YtdMbaqkcM2/6TaD75pGCCKgMrLkHGTSnK24J0JmIijJh7HqSOu2Q== X-Received: by 2002:ac8:5a96:0:b0:3ef:379c:71b9 with SMTP id c22-20020ac85a96000000b003ef379c71b9mr6634282qtc.30.1681939468865; Wed, 19 Apr 2023 14:24:28 -0700 (PDT) Received: from localhost (cpe-174-109-170-245.nc.res.rr.com. [174.109.170.245]) by smtp.gmail.com with ESMTPSA id he31-20020a05622a601f00b003e635f80e72sm38977qtb.48.2023.04.19.14.24.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Apr 2023 14:24:28 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 12/18] btrfs-progs: add btrfs_readahead_node_child helper Date: Wed, 19 Apr 2023 17:24:03 -0400 Message-Id: <6bbffaa00e20aac133463f344979e73283c4f404.1681939316.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org This exists in the kernel as a wrapper for readahead_tree_block, and is used extensively in ctree.c in the kernel. Sync this helper so that we can easily sync ctree.c Signed-off-by: Josef Bacik --- kernel-shared/extent_io.c | 14 ++++++++++++++ kernel-shared/extent_io.h | 1 + 2 files changed, 15 insertions(+) diff --git a/kernel-shared/extent_io.c b/kernel-shared/extent_io.c index d6705e37..105b5ec8 100644 --- a/kernel-shared/extent_io.c +++ b/kernel-shared/extent_io.c @@ -651,3 +651,17 @@ void write_extent_buffer_fsid(const struct extent_buffer *eb, const void *srcv) { write_extent_buffer(eb, srcv, btrfs_header_fsid(), BTRFS_FSID_SIZE); } + +/* + * btrfs_readahead_node_child - readahead a node's child block + * @node: parent node we're reading from + * @slot: slot in the parent node for the child we want to read + * + * A helper for readahead_tree_block, we simply read the bytenr pointed at the + * slot in the node provided. + */ +void btrfs_readahead_node_child(struct extent_buffer *node, int slot) +{ + readahead_tree_block(node->fs_info, btrfs_node_blockptr(node, slot), + btrfs_node_ptr_generation(node, slot)); +} diff --git a/kernel-shared/extent_io.h b/kernel-shared/extent_io.h index b4c2ac97..a1cda3a5 100644 --- a/kernel-shared/extent_io.h +++ b/kernel-shared/extent_io.h @@ -137,5 +137,6 @@ void extent_buffer_bitmap_set(struct extent_buffer *eb, unsigned long start, void extent_buffer_init_cache(struct btrfs_fs_info *fs_info); void extent_buffer_free_cache(struct btrfs_fs_info *fs_info); void write_extent_buffer_fsid(const struct extent_buffer *eb, const void *srcv); +void btrfs_readahead_node_child(struct extent_buffer *node, int slot); #endif From patchwork Wed Apr 19 21:24:04 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13217433 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 536F4C77B7A for ; Wed, 19 Apr 2023 21:25:18 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S231401AbjDSVZR (ORCPT ); Wed, 19 Apr 2023 17:25:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48664 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232846AbjDSVZA (ORCPT ); Wed, 19 Apr 2023 17:25:00 -0400 Received: from mail-qv1-xf30.google.com (mail-qv1-xf30.google.com [IPv6:2607:f8b0:4864:20::f30]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C656C61BE for ; Wed, 19 Apr 2023 14:24:31 -0700 (PDT) Received: by mail-qv1-xf30.google.com with SMTP id op30so1112319qvb.3 for ; Wed, 19 Apr 2023 14:24:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1681939470; x=1684531470; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=Xm2lhsMie+Od/1P9VjOhQGQvmSmj+F3rtAw8v4XruEI=; b=4e+kokLpL1YdbpdV9pQJvJHFuUieqOJsENRZFr8BsTf5wSlgdQXRK6Ii4kiifYA9R5 pD3eR8SH13GGjwerYaa7VXkf5RTbxPKB4o2987cNF9qRW9DH+9GKTzCpE9SD1nk65XwZ ztpmRyjqFitpGelgIYWRBlezZNmBRXeOdtsMY0sTYMI2M0dWxoZeFhJ1IJ9TIHEVcvTP Pbkqtq5NQoiSrqOmwJzu/6MkUIwhOIhxCuIVykuvEaNLCh/1/vzzUogW+/3dfL0KzdIN 8zrJhkJX63GskdTW+jKQcbv4pdnobCDLYkYuqnHKFVGQ5Uj+dvYLxTQu3aKL03O5Hxnx UA4Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1681939470; x=1684531470; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=Xm2lhsMie+Od/1P9VjOhQGQvmSmj+F3rtAw8v4XruEI=; b=BEcjMlyRL2zTT2Ee309Y0Ou/HJe3MDG1CbHW/2w0JCo+YaD1mZl0RKfcEU1WN6zxuu UOtq7EMk25MUaH86uSEPGqOAq2RszOJd6JcJsAH3I/G880qjgZ2zaTlnUyicLTjzr057 YJeQz3ZqhzCq8qSZXiS6b4KHl+tZXKYQlrU7yycORTZtcBTyXEW2pQ6u+17PD9WW0wxg AidHrY7ubNu0q/uQj7tl6ydOIoWirtwkoaQXXQWU+8dsWTLWuGy2B4c5aM3wN7E/qVFx gAgkP6XzNKTYBYUN4q2i4INCKm1i23xpjpysZRVzwJjJ8x1RX8WcW8pFMsiOqIjK73UV /1UQ== X-Gm-Message-State: AAQBX9eKU+vTz79U2mtKmkfpfQqfoDunToCeBFOIxkQK8DlljyZpkMwx 5k+mbi6JGifzmSi4Yi17zgahoWwo6gKxUed18Lz3WQ== X-Google-Smtp-Source: AKy350boAZGjEAx6JbMzoprlwTEcm/jgvD3LHdUMqdItibDlOU/24QZuWobQVD1JzPUJLnQ80vzG/w== X-Received: by 2002:a05:6214:e4f:b0:5ef:8159:b9a9 with SMTP id o15-20020a0562140e4f00b005ef8159b9a9mr16084935qvc.21.1681939470214; Wed, 19 Apr 2023 14:24:30 -0700 (PDT) Received: from localhost (cpe-174-109-170-245.nc.res.rr.com. [174.109.170.245]) by smtp.gmail.com with ESMTPSA id eb3-20020a05620a480300b0074b5219b63esm4023476qkb.121.2023.04.19.14.24.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Apr 2023 14:24:29 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 13/18] btrfs-progs: add an atomic arg to btrfs_buffer_uptodate Date: Wed, 19 Apr 2023 17:24:04 -0400 Message-Id: <51dfbda01b5de4ee153c1b34e22d9753d9dc389e.1681939316.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org We have this extra argument in the kernel to indicate if we are atomic and thus can't lock the io_tree when checking the transid for an extent buffer. This isn't necessary in btrfs-progs, but to allow for easier sync'ing of ctree.c add this argument to our copy of btrfs_buffer_uptodate. Signed-off-by: Josef Bacik --- check/main.c | 2 +- check/mode-lowmem.c | 2 +- kernel-shared/disk-io.c | 9 +++++---- kernel-shared/disk-io.h | 3 ++- kernel-shared/extent-tree.c | 2 +- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/check/main.c b/check/main.c index 610c3091..f15272bf 100644 --- a/check/main.c +++ b/check/main.c @@ -1895,7 +1895,7 @@ static int walk_down_tree(struct btrfs_root *root, struct btrfs_path *path, } next = btrfs_find_tree_block(gfs_info, bytenr, gfs_info->nodesize); - if (!next || !btrfs_buffer_uptodate(next, ptr_gen)) { + if (!next || !btrfs_buffer_uptodate(next, ptr_gen, 0)) { free_extent_buffer(next); reada_walk_down(root, cur, path->slots[*level]); next = read_tree_block(gfs_info, bytenr, diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c index 83b86e63..fb294c90 100644 --- a/check/mode-lowmem.c +++ b/check/mode-lowmem.c @@ -5043,7 +5043,7 @@ static int walk_down_tree(struct btrfs_root *root, struct btrfs_path *path, } next = btrfs_find_tree_block(gfs_info, bytenr, gfs_info->nodesize); - if (!next || !btrfs_buffer_uptodate(next, ptr_gen)) { + if (!next || !btrfs_buffer_uptodate(next, ptr_gen, 0)) { free_extent_buffer(next); reada_walk_down(root, cur, path->slots[*level]); next = read_tree_block(gfs_info, bytenr, diff --git a/kernel-shared/disk-io.c b/kernel-shared/disk-io.c index 3b3188da..29fe9027 100644 --- a/kernel-shared/disk-io.c +++ b/kernel-shared/disk-io.c @@ -246,7 +246,7 @@ void readahead_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr, struct btrfs_device *device; eb = btrfs_find_tree_block(fs_info, bytenr, fs_info->nodesize); - if (!(eb && btrfs_buffer_uptodate(eb, parent_transid)) && + if (!(eb && btrfs_buffer_uptodate(eb, parent_transid, 0)) && !btrfs_map_block(fs_info, READ, bytenr, &length, &multi, 0, NULL)) { device = multi->stripes[0].dev; @@ -367,7 +367,7 @@ struct extent_buffer *read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr, if (!eb) return ERR_PTR(-ENOMEM); - if (btrfs_buffer_uptodate(eb, parent_transid)) + if (btrfs_buffer_uptodate(eb, parent_transid, 0)) return eb; num_copies = btrfs_num_copies(fs_info, eb->start, eb->len); @@ -478,7 +478,7 @@ int write_tree_block(struct btrfs_trans_handle *trans, BUG(); } - if (trans && !btrfs_buffer_uptodate(eb, trans->transid)) + if (trans && !btrfs_buffer_uptodate(eb, trans->transid, 0)) BUG(); btrfs_clear_header_flag(eb, BTRFS_HEADER_FLAG_CSUM_NEW); @@ -2262,7 +2262,8 @@ void btrfs_mark_buffer_dirty(struct extent_buffer *eb) set_extent_buffer_dirty(eb); } -int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid) +int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid, + int atomic) { int ret; diff --git a/kernel-shared/disk-io.h b/kernel-shared/disk-io.h index f349b3ef..ed7f9259 100644 --- a/kernel-shared/disk-io.h +++ b/kernel-shared/disk-io.h @@ -201,7 +201,8 @@ struct btrfs_root *btrfs_read_fs_root_no_cache(struct btrfs_fs_info *fs_info, struct btrfs_key *location); int btrfs_free_fs_root(struct btrfs_root *root); void btrfs_mark_buffer_dirty(struct extent_buffer *buf); -int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid); +int btrfs_buffer_uptodate(struct extent_buffer *buf, u64 parent_transid, + int atomic); int btrfs_set_buffer_uptodate(struct extent_buffer *buf); int btrfs_csum_data(struct btrfs_fs_info *fs_info, u16 csum_type, const u8 *data, u8 *out, size_t len); diff --git a/kernel-shared/extent-tree.c b/kernel-shared/extent-tree.c index 5c33fd53..062ff4a7 100644 --- a/kernel-shared/extent-tree.c +++ b/kernel-shared/extent-tree.c @@ -1893,7 +1893,7 @@ static int pin_down_bytes(struct btrfs_trans_handle *trans, u64 bytenr, * reuse anything from the tree log root because * it has tiny sub-transactions. */ - if (btrfs_buffer_uptodate(buf, 0)) { + if (btrfs_buffer_uptodate(buf, 0, 0)) { u64 header_owner = btrfs_header_owner(buf); u64 header_transid = btrfs_header_generation(buf); if (header_owner != BTRFS_TREE_LOG_OBJECTID && From patchwork Wed Apr 19 21:24:05 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13217434 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 72C46C77B7E for ; Wed, 19 Apr 2023 21:25:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232545AbjDSVZT (ORCPT ); Wed, 19 Apr 2023 17:25:19 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48738 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232873AbjDSVZB (ORCPT ); Wed, 19 Apr 2023 17:25:01 -0400 Received: from mail-qk1-x72c.google.com (mail-qk1-x72c.google.com [IPv6:2607:f8b0:4864:20::72c]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 70ABE170E for ; Wed, 19 Apr 2023 14:24:33 -0700 (PDT) Received: by mail-qk1-x72c.google.com with SMTP id af79cd13be357-74d3c8843fbso230085a.1 for ; Wed, 19 Apr 2023 14:24:33 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1681939471; x=1684531471; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=FbZbfl1/3ybk58N1Zx+oexqaSHq9AlNN0cAebew9vgM=; b=BBhHSNhkMtYPX2RY81cOUnpuVkIPfjHlleBD0poERtjOdRt/aZttFmaJk0NQkSiTbX YHSwku+TIbsn0duSIW32XyoQ3eXqAWcz1iJayI7oRBrK2Ei/ZspH72C9pvYiVpaODu2O txXpu2c+j9c02sprKEUSc1gmGaSxeQnnAu9TzZKvnBSUXwdGBoBOkb/QiW4cbsw0QSeo ll4W4vO+M/SDnftcZOuLSj9uuOV4enNeQo2EblCiu6e5x67WlW5CAajgrF3LjXaECoYU z9xFIg6u1t6uYytdd4RfvMbnGoKbn5It8v5mcNuOfz8LPEYl5PrruZJa2IoMihSSjxfB 407Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1681939471; x=1684531471; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=FbZbfl1/3ybk58N1Zx+oexqaSHq9AlNN0cAebew9vgM=; b=TQ+i7+RhpMb2f5HLijMRtOLjmkQ0DksxuhMPt1z0EJ/3fTYrm/c3wxLo1tO6Fui+5m 1ZPdDu74coT49WFyW0g4QtY2OYVUz7kGuq6t7z7afUhhwHBN8seAPDOeO8Ls2KnOKnt2 ROw9FKGS9h/Obh+lDQaRp/wq5JKk6JFGqeiWa7ZNIWcB2YXohqI5ugG81QnghUDSSvm0 V6eWMyEL59CisdSnyOCsonQTBBWIpg/RnpNzv8yvexkv+Vkm+4Dbf+C0FoD4V59VmaDr GOwE/R3UESTVEcK3tV0vuG1KC1TR9W+/Det3UskQqWw9b5sczpP6gJ5bXb8tv/jCCWfl K3xw== X-Gm-Message-State: AAQBX9fX/ZhKOnc5ZqHHAcMPD+jPBEW+K65BusRbvEhN6IDnkNFBsOfA 2wiPHWk8cDeGMqazd++yirjNi+iJ1nKkQ8QJHuEECg== X-Google-Smtp-Source: AKy350aG0DXC0XXK2U/ZcFOjuRrsRBYEpRgU/twdTkVnxor2JXPJ76fwgC/PosLGLVx7+eYJWJJPYQ== X-Received: by 2002:ac8:5c45:0:b0:3ed:ac62:1039 with SMTP id j5-20020ac85c45000000b003edac621039mr37948qtj.8.1681939471457; Wed, 19 Apr 2023 14:24:31 -0700 (PDT) Received: from localhost (cpe-174-109-170-245.nc.res.rr.com. [174.109.170.245]) by smtp.gmail.com with ESMTPSA id dv22-20020a05620a1b9600b00746a7945d87sm4887056qkb.52.2023.04.19.14.24.31 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Apr 2023 14:24:31 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 14/18] btrfs-progs: add a btrfs_read_extent_buffer helper Date: Wed, 19 Apr 2023 17:24:05 -0400 Message-Id: X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org This exists in the kernel to do the read on an extent buffer we may have already looked up and initialized. Simply create this helper by extracting out the existing code from read_tree_block and make read_tree_block call this helper. This gives us the helper we need to sync ctree.c into btrfs-progs, and keeps the code the same in btrfs-progs. Signed-off-by: Josef Bacik --- kernel-shared/disk-io.c | 72 ++++++++++++++++++++++++----------------- kernel-shared/disk-io.h | 2 ++ 2 files changed, 45 insertions(+), 29 deletions(-) diff --git a/kernel-shared/disk-io.c b/kernel-shared/disk-io.c index 29fe9027..6e810bd1 100644 --- a/kernel-shared/disk-io.c +++ b/kernel-shared/disk-io.c @@ -337,39 +337,18 @@ int read_whole_eb(struct btrfs_fs_info *info, struct extent_buffer *eb, int mirr return 0; } -struct extent_buffer *read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr, - u64 owner_root, u64 parent_transid, - int level, struct btrfs_key *first_key) +int btrfs_read_extent_buffer(struct extent_buffer *eb, u64 parent_transid, + int level, struct btrfs_key *first_key) { + struct btrfs_fs_info *fs_info = eb->fs_info; int ret; - struct extent_buffer *eb; u64 best_transid = 0; - u32 sectorsize = fs_info->sectorsize; int mirror_num = 1; int good_mirror = 0; int candidate_mirror = 0; int num_copies; int ignore = 0; - /* - * Don't even try to create tree block for unaligned tree block - * bytenr. - * Such unaligned tree block will free overlapping extent buffer, - * causing use-after-free bugs for fuzzed images. - */ - if (bytenr < sectorsize || !IS_ALIGNED(bytenr, sectorsize)) { - error("tree block bytenr %llu is not aligned to sectorsize %u", - bytenr, sectorsize); - return ERR_PTR(-EIO); - } - - eb = btrfs_find_create_tree_block(fs_info, bytenr); - if (!eb) - return ERR_PTR(-ENOMEM); - - if (btrfs_buffer_uptodate(eb, parent_transid, 0)) - return eb; - num_copies = btrfs_num_copies(fs_info, eb->start, eb->len); while (1) { ret = read_whole_eb(fs_info, eb, mirror_num); @@ -396,7 +375,7 @@ struct extent_buffer *read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr, ret = btrfs_check_leaf(eb); if (!ret || candidate_mirror == mirror_num) { btrfs_set_buffer_uptodate(eb); - return eb; + return 0; } if (candidate_mirror <= 0) candidate_mirror = mirror_num; @@ -439,12 +418,47 @@ struct extent_buffer *read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr, continue; } } + return ret; +} + +struct extent_buffer *read_tree_block(struct btrfs_fs_info *fs_info, u64 bytenr, + u64 owner_root, u64 parent_transid, + int level, struct btrfs_key *first_key) +{ + int ret; + struct extent_buffer *eb; + u32 sectorsize = fs_info->sectorsize; + /* - * We failed to read this tree block, it be should deleted right now - * to avoid stale cache populate the cache. + * Don't even try to create tree block for unaligned tree block + * bytenr. + * Such unaligned tree block will free overlapping extent buffer, + * causing use-after-free bugs for fuzzed images. */ - free_extent_buffer_nocache(eb); - return ERR_PTR(ret); + if (bytenr < sectorsize || !IS_ALIGNED(bytenr, sectorsize)) { + error("tree block bytenr %llu is not aligned to sectorsize %u", + bytenr, sectorsize); + return ERR_PTR(-EIO); + } + + eb = btrfs_find_create_tree_block(fs_info, bytenr); + if (!eb) + return ERR_PTR(-ENOMEM); + + if (btrfs_buffer_uptodate(eb, parent_transid, 0)) + return eb; + + ret = btrfs_read_extent_buffer(eb, parent_transid, level, first_key); + if (ret) { + /* + * We failed to read this tree block, it be should deleted right + * now to avoid stale cache populate the cache. + */ + free_extent_buffer_nocache(eb); + return ERR_PTR(ret); + } + + return eb; } int write_and_map_eb(struct btrfs_fs_info *fs_info, struct extent_buffer *eb) diff --git a/kernel-shared/disk-io.h b/kernel-shared/disk-io.h index ed7f9259..4c63a4a8 100644 --- a/kernel-shared/disk-io.h +++ b/kernel-shared/disk-io.h @@ -233,6 +233,8 @@ int btrfs_global_root_insert(struct btrfs_fs_info *fs_info, int btrfs_find_and_setup_root(struct btrfs_root *tree_root, struct btrfs_fs_info *fs_info, u64 objectid, struct btrfs_root *root); +int btrfs_read_extent_buffer(struct extent_buffer *eb, u64 parent_transid, + int level, struct btrfs_key *first_key); static inline struct btrfs_root *btrfs_block_group_root( struct btrfs_fs_info *fs_info) From patchwork Wed Apr 19 21:24:06 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13217435 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id E32A1C77B73 for ; Wed, 19 Apr 2023 21:25:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232578AbjDSVZU (ORCPT ); Wed, 19 Apr 2023 17:25:20 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48760 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232907AbjDSVZC (ORCPT ); Wed, 19 Apr 2023 17:25:02 -0400 Received: from mail-qt1-x830.google.com (mail-qt1-x830.google.com [IPv6:2607:f8b0:4864:20::830]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 1A25683E2 for ; Wed, 19 Apr 2023 14:24:34 -0700 (PDT) Received: by mail-qt1-x830.google.com with SMTP id br19so639636qtb.7 for ; Wed, 19 Apr 2023 14:24:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1681939473; x=1684531473; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=tY/X5irnrKHcjd+q+bOmbN93LJUD4dQVn5bA9YCuDTI=; b=MIZNnriUnnrtUsnWJZCLtfus2Sf4aQSvl/ViTx0xeVsAJ2dgxU9c9lIUURD2B7pTx1 bNb6jAj3GirASFgEU8y+Ub9K53HSfJGECUdu+zcE2kIul0zis9PftfL8MqxjImszdo4p Q6X8HqAAuFAlzldzw3toref0QqNHblkCHygcUpXoaCBLIiHnXpu2DUbaGip2PojwTso5 SAiNzz70uSwhZwQ3r27rXPq6qTgk7M9hsN3gw7iMbhhiqaaUOYeiGDrSOYfEOgOr81mj opUtXaeVI4mALtULJUkTOTxvdvKAAJXpxsR/hOY/hNJ41hDx8T5q+ayuVXTD9VvGt9eV 7oUA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1681939473; x=1684531473; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=tY/X5irnrKHcjd+q+bOmbN93LJUD4dQVn5bA9YCuDTI=; b=SmrzFAPBV0eTaoPT2qrDysLM+WEszD19TfZUwpysWd+0ATZYf7mreYnd1SQ7nhs9In khTPe7i3Gq31ZpqwGUFt0V/5+Qaee5bos8lP7tHlcAnpaPmWuqApl1j/kkP1aXo70wfg OkSQolm9z13AEPxlMDArjD6zfQOYQlJYgoLwkEDf+sfpPAL6SWIXibKEwigT5B7M9ZUm LlKJUsRQFefZTDS33tfBQUmrB/Nqtt1rxP0xDuAL0b9Mf66xj8HFvC4zQG3Jk/68zKFZ lyZZ2s9sXOvo8ZXvYrtJ8OheSRybCxZxq/zR39V6OlHO34Oa+hvsVD0ZdoF1QaxQ6el5 O/nA== X-Gm-Message-State: AAQBX9cYe/ZtQfkXVMSs6xwi2BsfqNyEDr4ttdGkkSkF/36b4SpOt9P5 PWZwnZKXl6lxu8mv23Bbl8XnFU49bV5u3Vv7pI8wjQ== X-Google-Smtp-Source: AKy350YaRv/XwrOE7JxkKuoIP2lLIDH4A+Lpp7Y0mxTdcFo4TsNiw/THN52eCzbMALYg6IQTnaWuiw== X-Received: by 2002:ac8:7d52:0:b0:3e9:aa91:3627 with SMTP id h18-20020ac87d52000000b003e9aa913627mr8281013qtb.65.1681939472712; Wed, 19 Apr 2023 14:24:32 -0700 (PDT) Received: from localhost (cpe-174-109-170-245.nc.res.rr.com. [174.109.170.245]) by smtp.gmail.com with ESMTPSA id z39-20020a05620a262700b0074a293b1843sm4981567qko.19.2023.04.19.14.24.32 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Apr 2023 14:24:32 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 15/18] btrfs-progs: add BTRFS_STRIPE_LEN_SHIFT definition Date: Wed, 19 Apr 2023 17:24:06 -0400 Message-Id: <3e1522ac773660a2d1d287becf90b3c9d5efa013.1681939316.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org This is used by tree-checker.c, so sync this into volumes.h to make it easier to sync tree-checker.c. Signed-off-by: Josef Bacik --- kernel-shared/volumes.h | 1 + 1 file changed, 1 insertion(+) diff --git a/kernel-shared/volumes.h b/kernel-shared/volumes.h index 6e9103a9..206eab77 100644 --- a/kernel-shared/volumes.h +++ b/kernel-shared/volumes.h @@ -24,6 +24,7 @@ #include "kernel-lib/sizes.h" #define BTRFS_STRIPE_LEN SZ_64K +#define BTRFS_STRIPE_LEN_SHIFT (16) struct btrfs_device { struct list_head dev_list; From patchwork Wed Apr 19 21:24:07 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13217436 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id B82E6C77B78 for ; Wed, 19 Apr 2023 21:25:22 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232573AbjDSVZV (ORCPT ); Wed, 19 Apr 2023 17:25:21 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48790 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232999AbjDSVZF (ORCPT ); Wed, 19 Apr 2023 17:25:05 -0400 Received: from mail-qt1-x82e.google.com (mail-qt1-x82e.google.com [IPv6:2607:f8b0:4864:20::82e]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 07984768E for ; Wed, 19 Apr 2023 14:24:36 -0700 (PDT) Received: by mail-qt1-x82e.google.com with SMTP id bb13so606885qtb.11 for ; Wed, 19 Apr 2023 14:24:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1681939474; x=1684531474; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=5iOyL9zyZdNt4jjPi6AnYMEM8+V8Tn0R0+0ZUeZ5hRg=; b=5NdfFgFOsyxjNdLue6MW3qveGWc63/0EF15k+1BUtarKl9LMlcYJOi2MGKJu87LZc8 k5nG6Ug6UETTb6lKQ9tnq2SCOi6ms+X70PIuitEkkaAncCDo6PsID4RgFHxdotej97By yHDfC5HpBF+ZTm8LNnOd7/j76S7h5aEK0HlOFf0gOOQWVSfT3MD3M96UqQayHQAuTaAz ORAYYCRsnn6r59Rdc5mKWrcvbiSuYvQ5h/FgMn3upGliEbVVIQNPS4iyoGrkIEAj7/4Z 5SrYuEl2/AvVbrOkVSQj5wrjhkvk4KGEu18BHG0mbac4f+tqDAnNOQC9sy3AW8pIpjy1 pCmQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1681939474; x=1684531474; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=5iOyL9zyZdNt4jjPi6AnYMEM8+V8Tn0R0+0ZUeZ5hRg=; b=P9f6C6DvLRAPaad0ga01msLqVW42iwJht8EDR30ZSNmbnt1Q2YTaGMx9S+Xx5+d4BG VMrWSrY7x0omWhZMd3TiXkigSKHyr1H/UJCiBVS1sruB8v0f/dCBHGTEuQK3bsTC31fv h+3H/zEb+n2H9a9C1DVDRVmiQEhzzs3byIh4VFry/Bl2UEfJMjR02qSHbF64JZV8o6X+ +S+RvBp8Z8DoO6ZAfLjLqM94uoJWatzJmPCycCKsBsSf9zvPtHVRdpq8AgxSkbejR0+K 2thq7WJebDvx8u6VDDDzbuylZhyZcAwC5BQQYihl++QJJlZIukYYhnc6EuAIHKMyVUpa csag== X-Gm-Message-State: AAQBX9cgf32AfWmIcJzo7A1jLE7hV1qeWaMd9poz2b4H5MktIKNdK8D4 YR04TSqWoDYfDm/+DR+ly9oGx8yo+hgRtFcKo9JRcw== X-Google-Smtp-Source: AKy350a336j9Hj0hZNfSBdPjPJT/T+JDgmfTDJZdRDdo+okCIQMzqJ8PzRWOTvybVoB62xH+T1jkJw== X-Received: by 2002:ac8:5984:0:b0:3ef:437e:c824 with SMTP id e4-20020ac85984000000b003ef437ec824mr6356693qte.52.1681939473961; Wed, 19 Apr 2023 14:24:33 -0700 (PDT) Received: from localhost (cpe-174-109-170-245.nc.res.rr.com. [174.109.170.245]) by smtp.gmail.com with ESMTPSA id f20-20020a05620a20d400b0074d3233487dsm3255589qka.114.2023.04.19.14.24.33 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Apr 2023 14:24:33 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 16/18] btrfs-progs: rename btrfs_check_* to __btrfs_check_* Date: Wed, 19 Apr 2023 17:24:07 -0400 Message-Id: <303808c223f223704d0f06e8d9ff115a19a119c4.1681939316.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org These helpers are called __btrfs_check_* in the kernel as they return the special enum to indicate what part of the leaf/node failed. Rename the uses in btrfs-progs to match the kernel naming convention to make it easier to sync that code. Signed-off-by: Josef Bacik --- check/repair.c | 4 ++-- kernel-shared/ctree.c | 8 ++++---- kernel-shared/ctree.h | 4 ++-- kernel-shared/disk-io.c | 4 ++-- 4 files changed, 10 insertions(+), 10 deletions(-) diff --git a/check/repair.c b/check/repair.c index ec8b0196..b323ad3e 100644 --- a/check/repair.c +++ b/check/repair.c @@ -311,9 +311,9 @@ enum btrfs_tree_block_status btrfs_check_block_for_repair(struct extent_buffer * enum btrfs_tree_block_status status; if (btrfs_is_leaf(eb)) - status = btrfs_check_leaf(eb); + status = __btrfs_check_leaf(eb); else - status = btrfs_check_node(eb); + status = __btrfs_check_node(eb); if (status == BTRFS_TREE_BLOCK_CLEAN) return status; diff --git a/kernel-shared/ctree.c b/kernel-shared/ctree.c index 3e1085a0..66f44879 100644 --- a/kernel-shared/ctree.c +++ b/kernel-shared/ctree.c @@ -616,7 +616,7 @@ static void generic_err(const struct extent_buffer *buf, int slot, fprintf(stderr, "\n"); } -enum btrfs_tree_block_status btrfs_check_node(struct extent_buffer *node) +enum btrfs_tree_block_status __btrfs_check_node(struct extent_buffer *node) { struct btrfs_fs_info *fs_info = node->fs_info; unsigned long nr = btrfs_header_nritems(node); @@ -677,7 +677,7 @@ fail: return ret; } -enum btrfs_tree_block_status btrfs_check_leaf(struct extent_buffer *leaf) +enum btrfs_tree_block_status __btrfs_check_leaf(struct extent_buffer *leaf) { struct btrfs_fs_info *fs_info = leaf->fs_info; /* No valid key type is 0, so all key should be larger than this key */ @@ -789,9 +789,9 @@ static int noinline check_block(struct btrfs_fs_info *fs_info, if (path->skip_check_block) return 0; if (level == 0) - ret = btrfs_check_leaf(path->nodes[0]); + ret = __btrfs_check_leaf(path->nodes[0]); else - ret = btrfs_check_node(path->nodes[level]); + ret = __btrfs_check_node(path->nodes[level]); if (ret == BTRFS_TREE_BLOCK_CLEAN) return 0; return -EIO; diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h index 20c9edc6..237f530d 100644 --- a/kernel-shared/ctree.h +++ b/kernel-shared/ctree.h @@ -958,8 +958,8 @@ int btrfs_convert_one_bg(struct btrfs_trans_handle *trans, u64 bytenr); int btrfs_comp_cpu_keys(const struct btrfs_key *k1, const struct btrfs_key *k2); int btrfs_del_ptr(struct btrfs_root *root, struct btrfs_path *path, int level, int slot); -enum btrfs_tree_block_status btrfs_check_node(struct extent_buffer *buf); -enum btrfs_tree_block_status btrfs_check_leaf(struct extent_buffer *buf); +enum btrfs_tree_block_status __btrfs_check_node(struct extent_buffer *buf); +enum btrfs_tree_block_status __btrfs_check_leaf(struct extent_buffer *buf); struct extent_buffer *read_node_slot(struct btrfs_fs_info *fs_info, struct extent_buffer *parent, int slot); int btrfs_previous_item(struct btrfs_root *root, diff --git a/kernel-shared/disk-io.c b/kernel-shared/disk-io.c index 6e810bd1..4950c685 100644 --- a/kernel-shared/disk-io.c +++ b/kernel-shared/disk-io.c @@ -370,9 +370,9 @@ int btrfs_read_extent_buffer(struct extent_buffer *eb, u64 parent_transid, * btrfs ins dump-tree. */ if (btrfs_header_level(eb)) - ret = btrfs_check_node(eb); + ret = __btrfs_check_node(eb); else - ret = btrfs_check_leaf(eb); + ret = __btrfs_check_leaf(eb); if (!ret || candidate_mirror == mirror_num) { btrfs_set_buffer_uptodate(eb); return 0; From patchwork Wed Apr 19 21:24:08 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13217437 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id BFDCEC77B7A for ; Wed, 19 Apr 2023 21:25:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232589AbjDSVZW (ORCPT ); Wed, 19 Apr 2023 17:25:22 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48810 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S233034AbjDSVZH (ORCPT ); Wed, 19 Apr 2023 17:25:07 -0400 Received: from mail-qv1-xf35.google.com (mail-qv1-xf35.google.com [IPv6:2607:f8b0:4864:20::f35]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id C230483C3 for ; Wed, 19 Apr 2023 14:24:37 -0700 (PDT) Received: by mail-qv1-xf35.google.com with SMTP id qf26so1047032qvb.6 for ; Wed, 19 Apr 2023 14:24:37 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1681939475; x=1684531475; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=RcwIUXAM7suyt7Kjbk24uDH/3G+6OPD6fk/698QuRvk=; b=tDLy1i9tTirksm2IuPChHXM2/tpmNuzDrKMHgHMkVOHd/llBZELcYQkx9INuzOm3mL 43OimeWL3KYcPhycyiO2LphkoxvKuRat7WlA43kBhwxjU8QgdTVHfoOv3CvcBJiyLivy qJ771vqDJJqRRaBR2W7tihZ93t/xaB9F+jqvASFFMB8S0nfFC9LhZFDdiIZ7tD49LsRc jd8TRkzW13v0qYj6T3eosNOru5bxhDe1sZxly6NcxsxvaUAIsh3xFWHG7PPB1xr2+hec Vew9qsqKOtFMB2+oyuEW5dl/SOD2YzJ2Gp1gD6K/KVNhs8RVPe6GOcPd6419aXHmlZ1l rxjg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1681939475; x=1684531475; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=RcwIUXAM7suyt7Kjbk24uDH/3G+6OPD6fk/698QuRvk=; b=D4cxVPpAlg7A+vXkBL4O1q8XWYfyTJl5/IqGGE0K2dHxJC4e45A4dqqoA5CexUubLY 9z8434w87rdj31xDDykBzWx+UQdnsISIo8DI5udzfVFCzyq33/biI1B/aC0oGcc5kLPJ Ic8XjRa5FDWOBjcj7RcwDvRLw/4DZP4pzQkDqZqaMHGOs9Klc1E7x5QYdRhSkp3K8axO iNnqCNJAxBo3bXRwT/ncheUNlfg9svlAQys1LOwLFHwyC9I6Y5gkG8SqD8mzvpJYoAwO Ab5v6OPzNBirJW1oL03E5nGhbo4fbLfkpuNTXyF0SnTjSUtyPVh1TA+rFZyC78fAm14H 4bug== X-Gm-Message-State: AAQBX9fgQuTzzNlFKotP/lxk+d7BrrF9iWnzmtYI1SjUhszWvoEKMHZH N4nGwFQPghEv32HRAc+FHLCzmkdXGG0TlWI87cz1+g== X-Google-Smtp-Source: AKy350ZAPOeshyaOWro5Wl9rphaHpp2bhsrnlCKoviJpD0GojJy/Kyk4vKJW7ZkjV89IlRCsX4+IzQ== X-Received: by 2002:a05:6214:c8a:b0:5cb:ab2e:b15c with SMTP id r10-20020a0562140c8a00b005cbab2eb15cmr21499702qvr.30.1681939475163; Wed, 19 Apr 2023 14:24:35 -0700 (PDT) Received: from localhost (cpe-174-109-170-245.nc.res.rr.com. [174.109.170.245]) by smtp.gmail.com with ESMTPSA id i10-20020a0cab4a000000b005e5afa59f3dsm6000qvb.39.2023.04.19.14.24.34 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Apr 2023 14:24:34 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 17/18] btrfs-progs: change btrfs_check_chunk_valid to match the kernel version Date: Wed, 19 Apr 2023 17:24:08 -0400 Message-Id: <48c1bbd15ec096a559a5bd52dfc2d95d816919da.1681939316.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org In btrfs-progs we check the actual leaf pointers as well as the chunk itself in btrfs_check_chunk_valid. However in the kernel the leaf stuff is handled separately as part of the read, and then we have the chunk checker itself. Change the btrfs-progs version to match the in-kernel version temporarily so it makes syncing the in-kernel code easier. Signed-off-by: Josef Bacik --- check/main.c | 3 +-- check/mode-lowmem.c | 6 ++---- kernel-shared/volumes.c | 46 ++++------------------------------------- kernel-shared/volumes.h | 6 ++---- 4 files changed, 9 insertions(+), 52 deletions(-) diff --git a/check/main.c b/check/main.c index f15272bf..f9055f7a 100644 --- a/check/main.c +++ b/check/main.c @@ -5329,8 +5329,7 @@ static int process_chunk_item(struct cache_tree *chunk_cache, * wrong onwer(3) out of chunk tree, to pass both chunk tree check * and owner<->key_type check. */ - ret = btrfs_check_chunk_valid(gfs_info, eb, chunk, slot, - key->offset); + ret = btrfs_check_chunk_valid(eb, chunk, key->offset); if (ret < 0) { error("chunk(%llu, %llu) is not valid, ignore it", key->offset, btrfs_chunk_length(eb, chunk)); diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c index fb294c90..7a57f99a 100644 --- a/check/mode-lowmem.c +++ b/check/mode-lowmem.c @@ -4470,8 +4470,7 @@ static int check_dev_extent_item(struct extent_buffer *eb, int slot) l = path.nodes[0]; chunk = btrfs_item_ptr(l, path.slots[0], struct btrfs_chunk); - ret = btrfs_check_chunk_valid(gfs_info, l, chunk, path.slots[0], - chunk_key.offset); + ret = btrfs_check_chunk_valid(l, chunk, chunk_key.offset); if (ret < 0) goto out; @@ -4702,8 +4701,7 @@ static int check_chunk_item(struct extent_buffer *eb, int slot) chunk = btrfs_item_ptr(eb, slot, struct btrfs_chunk); length = btrfs_chunk_length(eb, chunk); chunk_end = chunk_key.offset + length; - ret = btrfs_check_chunk_valid(gfs_info, eb, chunk, slot, - chunk_key.offset); + ret = btrfs_check_chunk_valid(eb, chunk, chunk_key.offset); if (ret < 0) { error("chunk[%llu %llu) is invalid", chunk_key.offset, chunk_end); diff --git a/kernel-shared/volumes.c b/kernel-shared/volumes.c index 1e2c8895..14fcefee 100644 --- a/kernel-shared/volumes.c +++ b/kernel-shared/volumes.c @@ -2090,33 +2090,19 @@ static struct btrfs_device *fill_missing_device(u64 devid) * slot == -1: SYSTEM chunk * return -EIO on error, otherwise return 0 */ -int btrfs_check_chunk_valid(struct btrfs_fs_info *fs_info, - struct extent_buffer *leaf, - struct btrfs_chunk *chunk, - int slot, u64 logical) +int btrfs_check_chunk_valid(struct extent_buffer *leaf, + struct btrfs_chunk *chunk, u64 logical) { + struct btrfs_fs_info *fs_info = leaf->fs_info; u64 length; u64 stripe_len; u16 num_stripes; u16 sub_stripes; u64 type; - u32 chunk_ondisk_size; u32 sectorsize = fs_info->sectorsize; int min_devs; int table_sub_stripes; - /* - * Basic chunk item size check. Note that btrfs_chunk already contains - * one stripe, so no "==" check. - */ - if (slot >= 0 && - btrfs_item_size(leaf, slot) < sizeof(struct btrfs_chunk)) { - error("invalid chunk item size, have %u expect [%zu, %u)", - btrfs_item_size(leaf, slot), - sizeof(struct btrfs_chunk), - BTRFS_LEAF_DATA_SIZE(fs_info)); - return -EUCLEAN; - } length = btrfs_chunk_length(leaf, chunk); stripe_len = btrfs_chunk_stripe_len(leaf, chunk); num_stripes = btrfs_chunk_num_stripes(leaf, chunk); @@ -2128,13 +2114,6 @@ int btrfs_check_chunk_valid(struct btrfs_fs_info *fs_info, num_stripes); return -EUCLEAN; } - if (slot >= 0 && btrfs_chunk_item_size(num_stripes) != - btrfs_item_size(leaf, slot)) { - error("invalid chunk item size, have %u expect %lu", - btrfs_item_size(leaf, slot), - btrfs_chunk_item_size(num_stripes)); - return -EUCLEAN; - } /* * These valid checks may be insufficient to cover every corner cases. @@ -2156,11 +2135,6 @@ int btrfs_check_chunk_valid(struct btrfs_fs_info *fs_info, error("invalid chunk stripe length: %llu", stripe_len); return -EIO; } - /* Check on chunk item type */ - if (slot == -1 && (type & BTRFS_BLOCK_GROUP_SYSTEM) == 0) { - error("invalid chunk type %llu", type); - return -EIO; - } if (type & ~(BTRFS_BLOCK_GROUP_TYPE_MASK | BTRFS_BLOCK_GROUP_PROFILE_MASK)) { error("unrecognized chunk type: %llu", @@ -2183,18 +2157,6 @@ int btrfs_check_chunk_valid(struct btrfs_fs_info *fs_info, return -EIO; } - chunk_ondisk_size = btrfs_chunk_item_size(num_stripes); - /* - * Btrfs_chunk contains at least one stripe, and for sys_chunk - * it can't exceed the system chunk array size - * For normal chunk, it should match its chunk item size. - */ - if (num_stripes < 1 || - (slot == -1 && chunk_ondisk_size > BTRFS_SYSTEM_CHUNK_ARRAY_SIZE) || - (slot >= 0 && chunk_ondisk_size > btrfs_item_size(leaf, slot))) { - error("invalid num_stripes: %u", num_stripes); - return -EIO; - } /* * Device number check against profile */ @@ -2243,7 +2205,7 @@ static int read_one_chunk(struct btrfs_fs_info *fs_info, struct btrfs_key *key, length = btrfs_chunk_length(leaf, chunk); num_stripes = btrfs_chunk_num_stripes(leaf, chunk); /* Validation check */ - ret = btrfs_check_chunk_valid(fs_info, leaf, chunk, slot, logical); + ret = btrfs_check_chunk_valid(leaf, chunk, logical); if (ret) { error("%s checksums match, but it has an invalid chunk, %s", (slot == -1) ? "Superblock" : "Metadata", diff --git a/kernel-shared/volumes.h b/kernel-shared/volumes.h index 206eab77..84fd6617 100644 --- a/kernel-shared/volumes.h +++ b/kernel-shared/volumes.h @@ -294,10 +294,8 @@ int write_raid56_with_parity(struct btrfs_fs_info *info, struct extent_buffer *eb, struct btrfs_multi_bio *multi, u64 stripe_len, u64 *raid_map); -int btrfs_check_chunk_valid(struct btrfs_fs_info *fs_info, - struct extent_buffer *leaf, - struct btrfs_chunk *chunk, - int slot, u64 logical); +int btrfs_check_chunk_valid(struct extent_buffer *leaf, + struct btrfs_chunk *chunk, u64 logical); u64 btrfs_stripe_length(struct btrfs_fs_info *fs_info, struct extent_buffer *leaf, struct btrfs_chunk *chunk); From patchwork Wed Apr 19 21:24:09 2023 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Josef Bacik X-Patchwork-Id: 13217438 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 8C6EDC77B78 for ; Wed, 19 Apr 2023 21:25:25 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232580AbjDSVZY (ORCPT ); Wed, 19 Apr 2023 17:25:24 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:48972 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232095AbjDSVZL (ORCPT ); Wed, 19 Apr 2023 17:25:11 -0400 Received: from mail-qv1-xf30.google.com (mail-qv1-xf30.google.com [IPv6:2607:f8b0:4864:20::f30]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 156A38689 for ; Wed, 19 Apr 2023 14:24:39 -0700 (PDT) Received: by mail-qv1-xf30.google.com with SMTP id bo1so1028196qvb.8 for ; Wed, 19 Apr 2023 14:24:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=toxicpanda-com.20221208.gappssmtp.com; s=20221208; t=1681939478; x=1684531478; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=4d9dlI9QBPf0vLp3BaoKPS5RQinDkIAsHMQ8+cBNrNE=; b=vsYjhgLoNg7bbkJStgQZTF0a6oxGnUDnTPsm4YHrLW7890qgwAHltTyHrYSEfVfHgz Y4cJDVAZL4StTLpuI2/Xqq7ofcelmMBBTBWHHtNOhhy+iMFzmH3OcktkmNZ7k0eSiB2j 2NwHmdh5Zgre/y7bzDLbLAaEWRIOHVKUuLASauAkEGvIfWdW6lJFHl/7UCpm/d6vrgtR 4+gnoGKjAKnCRe9caSfQKkZPqG6DRcMhY6x03qXBbGIKnM1RwQxqRZIzifYEInIY2EE3 z27/iAYJ5PyG7Wfh4TzdxzeEm6Et0MtWzOv4u3vBfTWQjdu4dhDZuFrTAub3U8t4oBhZ b9QQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20221208; t=1681939478; x=1684531478; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=4d9dlI9QBPf0vLp3BaoKPS5RQinDkIAsHMQ8+cBNrNE=; b=fFsJS+AID0KUHS6m4+9LOjVFNny/Foll8kDTDdpQ76putRRPeByP1dZ9xzOmTQ+2q0 2lmq52Y/cRUfUOoKYv+4f2f5vDYx0/iCzKcqByj3AXMbJRhf2OEohA3Ob5UnVWf8x/Zp WeXkkpc+mu2DKSAXsvk9kRpnhisYFjnXdGBzN1vW7USVm0nPCBV8GiCxn7dC0FnpMplL IM2dJoWvTRJBZlDG/ZJoCLTnimfx4XXorgsZKEBQnP5VCqW9WnKOxNLVbol2I4foBgNE wnw9EDqDY/her1sKrRz2ZIlQ3aRJG/ifHDQg9FSlqbu2JgeeVVXhiKt2tb10n3beVzZg UxKA== X-Gm-Message-State: AAQBX9c7Bj6fq79dZCyYBOWhQUmAdMjBNlhuUFF5qdZ96WHkwNDfEHWm IR4/LbT/RnSvkC2kSVb4lMvuFz7FYwE2JMUizHapYg== X-Google-Smtp-Source: AKy350ZfNdmlPfF8lU60CpZt+c1A8l8JYiCK+wbuTNEo+ziZ0401COPlwUc9Dz9NjEfqWL7IogrRiw== X-Received: by 2002:a05:6214:b65:b0:5e8:f869:37fd with SMTP id ey5-20020a0562140b6500b005e8f86937fdmr8460469qvb.8.1681939476580; Wed, 19 Apr 2023 14:24:36 -0700 (PDT) Received: from localhost (cpe-174-109-170-245.nc.res.rr.com. [174.109.170.245]) by smtp.gmail.com with ESMTPSA id a29-20020a05620a439d00b0074de75f783fsm2940172qkp.26.2023.04.19.14.24.36 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 19 Apr 2023 14:24:36 -0700 (PDT) From: Josef Bacik To: linux-btrfs@vger.kernel.org, kernel-team@fb.com Subject: [PATCH 18/18] btrfs-progs: sync tree-checker.[ch] Date: Wed, 19 Apr 2023 17:24:09 -0400 Message-Id: <90a4fe241636c2170209bf94622c55bebfa9f533.1681939316.git.josef@toxicpanda.com> X-Mailer: git-send-email 2.40.0 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org This syncs tree-checker.c from the kernel. The main modification was to add a open ctree flag to skip the deeper leaf checks, and plumbing this through tree-checker.c. We need this for things like fsck or btrfs-image that need to work with slightly corrupted file systems, and these checks simply make us unable to look at the corrupted blocks. Signed-off-by: Josef Bacik --- Makefile | 1 + check/main.c | 4 +- check/mode-lowmem.c | 1 + check/repair.c | 1 + image/main.c | 14 +- include/kerncompat.h | 10 + kernel-shared/ctree.c | 180 +-- kernel-shared/ctree.h | 14 +- kernel-shared/disk-io.c | 3 + kernel-shared/disk-io.h | 6 + kernel-shared/tree-checker.c | 2064 ++++++++++++++++++++++++++++++++++ kernel-shared/tree-checker.h | 72 ++ kernel-shared/volumes.c | 96 +- kernel-shared/volumes.h | 2 - 14 files changed, 2173 insertions(+), 295 deletions(-) create mode 100644 kernel-shared/tree-checker.c create mode 100644 kernel-shared/tree-checker.h diff --git a/Makefile b/Makefile index 8001f46a..6806d347 100644 --- a/Makefile +++ b/Makefile @@ -187,6 +187,7 @@ objects = \ kernel-shared/print-tree.o \ kernel-shared/root-tree.o \ kernel-shared/transaction.o \ + kernel-shared/tree-checker.o \ kernel-shared/ulist.o \ kernel-shared/uuid-tree.o \ kernel-shared/volumes.o \ diff --git a/check/main.c b/check/main.c index f9055f7a..8714c213 100644 --- a/check/main.c +++ b/check/main.c @@ -64,6 +64,7 @@ #include "check/clear-cache.h" #include "kernel-shared/uapi/btrfs.h" #include "kernel-lib/bitops.h" +#include "kernel-shared/tree-checker.h" /* Global context variables */ struct btrfs_fs_info *gfs_info; @@ -9996,7 +9997,8 @@ static int cmd_check(const struct cmd_struct *cmd, int argc, char **argv) int qgroups_repaired = 0; int qgroup_verify_ret; unsigned ctree_flags = OPEN_CTREE_EXCLUSIVE | - OPEN_CTREE_ALLOW_TRANSID_MISMATCH; + OPEN_CTREE_ALLOW_TRANSID_MISMATCH | + OPEN_CTREE_SKIP_LEAF_ITEM_CHECKS; int force = 0; while(1) { diff --git a/check/mode-lowmem.c b/check/mode-lowmem.c index 7a57f99a..1614c065 100644 --- a/check/mode-lowmem.c +++ b/check/mode-lowmem.c @@ -38,6 +38,7 @@ #include "check/repair.h" #include "check/mode-common.h" #include "check/mode-lowmem.h" +#include "kernel-shared/tree-checker.h" static u64 last_allocated_chunk; static u64 total_used = 0; diff --git a/check/repair.c b/check/repair.c index b323ad3e..b73f9518 100644 --- a/check/repair.c +++ b/check/repair.c @@ -29,6 +29,7 @@ #include "kernel-shared/disk-io.h" #include "common/extent-cache.h" #include "check/repair.h" +#include "kernel-shared/tree-checker.h" int opt_check_repair = 0; diff --git a/image/main.c b/image/main.c index 92b0dbfa..856e313f 100644 --- a/image/main.c +++ b/image/main.c @@ -1025,7 +1025,8 @@ static int create_metadump(const char *input, FILE *out, int num_threads, int ret; int err = 0; - root = open_ctree(input, 0, OPEN_CTREE_ALLOW_TRANSID_MISMATCH); + root = open_ctree(input, 0, OPEN_CTREE_ALLOW_TRANSID_MISMATCH | + OPEN_CTREE_SKIP_LEAF_ITEM_CHECKS); if (!root) { error("open ctree failed"); return -EIO; @@ -2798,7 +2799,7 @@ static int restore_metadump(const char *input, FILE *out, int old_restore, ocf.filename = target; ocf.flags = OPEN_CTREE_WRITES | OPEN_CTREE_RESTORE | - OPEN_CTREE_PARTIAL; + OPEN_CTREE_PARTIAL | OPEN_CTREE_SKIP_LEAF_ITEM_CHECKS; info = open_ctree_fs_info(&ocf); if (!info) { error("open ctree failed"); @@ -2864,7 +2865,8 @@ static int restore_metadump(const char *input, FILE *out, int old_restore, OPEN_CTREE_PARTIAL | OPEN_CTREE_WRITES | OPEN_CTREE_NO_DEVICES | - OPEN_CTREE_ALLOW_TRANSID_MISMATCH); + OPEN_CTREE_ALLOW_TRANSID_MISMATCH | + OPEN_CTREE_SKIP_LEAF_ITEM_CHECKS); if (!root) { error("open ctree failed in %s", target); ret = -EIO; @@ -2883,7 +2885,8 @@ static int restore_metadump(const char *input, FILE *out, int old_restore, if (!info) { root = open_ctree_fd(fileno(out), target, 0, - OPEN_CTREE_ALLOW_TRANSID_MISMATCH); + OPEN_CTREE_ALLOW_TRANSID_MISMATCH | + OPEN_CTREE_SKIP_LEAF_ITEM_CHECKS); if (!root) { error("open ctree failed in %s", target); ret = -EIO; @@ -3226,7 +3229,8 @@ int BOX_MAIN(image)(int argc, char *argv[]) int i; ocf.filename = target; - ocf.flags = OPEN_CTREE_PARTIAL | OPEN_CTREE_RESTORE; + ocf.flags = OPEN_CTREE_PARTIAL | OPEN_CTREE_RESTORE | + OPEN_CTREE_SKIP_LEAF_ITEM_CHECKS; info = open_ctree_fs_info(&ocf); if (!info) { error("open ctree failed at %s", target); diff --git a/include/kerncompat.h b/include/kerncompat.h index 28e9f443..7472ff75 100644 --- a/include/kerncompat.h +++ b/include/kerncompat.h @@ -86,6 +86,7 @@ #define _RET_IP_ 0 #define TASK_UNINTERRUPTIBLE 0 #define SLAB_MEM_SPREAD 0 +#define ALLOW_ERROR_INJECTION(a, b) #ifndef ULONG_MAX #define ULONG_MAX (~0UL) @@ -418,6 +419,15 @@ do { \ __ret_warn_on; \ }) +#define WARN(c, msg...) ({ \ + int __ret_warn_on = !!(c); \ + if (__ret_warn_on) \ + printf(msg); \ + __ret_warn_on; \ +}) + +#define IS_ENABLED(c) 0 + #define container_of(ptr, type, member) ({ \ const typeof( ((type *)0)->member ) *__mptr = (ptr); \ (type *)( (char *)__mptr - offsetof(type,member) );}) diff --git a/kernel-shared/ctree.c b/kernel-shared/ctree.c index 66f44879..d5a1f90b 100644 --- a/kernel-shared/ctree.c +++ b/kernel-shared/ctree.c @@ -28,6 +28,7 @@ #include "kernel-lib/sizes.h" #include "kernel-shared/volumes.h" #include "check/repair.h" +#include "tree-checker.h" static int split_node(struct btrfs_trans_handle *trans, struct btrfs_root *root, struct btrfs_path *path, int level); @@ -602,185 +603,6 @@ static inline unsigned int leaf_data_end(const struct extent_buffer *leaf) return btrfs_item_offset(leaf, nr - 1); } -static void generic_err(const struct extent_buffer *buf, int slot, - const char *fmt, ...) -{ - va_list args; - - fprintf(stderr, "corrupt %s: root=%lld block=%llu slot=%d, ", - btrfs_header_level(buf) == 0 ? "leaf": "node", - btrfs_header_owner(buf), btrfs_header_bytenr(buf), slot); - va_start(args, fmt); - vfprintf(stderr, fmt, args); - va_end(args); - fprintf(stderr, "\n"); -} - -enum btrfs_tree_block_status __btrfs_check_node(struct extent_buffer *node) -{ - struct btrfs_fs_info *fs_info = node->fs_info; - unsigned long nr = btrfs_header_nritems(node); - struct btrfs_key key, next_key; - int slot; - int level = btrfs_header_level(node); - u64 bytenr; - enum btrfs_tree_block_status ret = BTRFS_TREE_BLOCK_INVALID_NRITEMS; - - if (level <= 0 || level >= BTRFS_MAX_LEVEL) { - generic_err(node, 0, - "invalid level for node, have %d expect [1, %d]", - level, BTRFS_MAX_LEVEL - 1); - ret = BTRFS_TREE_BLOCK_INVALID_LEVEL; - goto fail; - } - if (nr == 0 || nr > BTRFS_NODEPTRS_PER_BLOCK(fs_info)) { - generic_err(node, 0, -"corrupt node: root=%llu block=%llu, nritems too %s, have %lu expect range [1,%u]", - btrfs_header_owner(node), node->start, - nr == 0 ? "small" : "large", nr, - BTRFS_NODEPTRS_PER_BLOCK(fs_info)); - ret = BTRFS_TREE_BLOCK_INVALID_NRITEMS; - goto fail; - } - - for (slot = 0; slot < nr - 1; slot++) { - bytenr = btrfs_node_blockptr(node, slot); - btrfs_node_key_to_cpu(node, &key, slot); - btrfs_node_key_to_cpu(node, &next_key, slot + 1); - - if (!bytenr) { - generic_err(node, slot, - "invalid NULL node pointer"); - ret = BTRFS_TREE_BLOCK_INVALID_BLOCKPTR; - goto fail; - } - if (!IS_ALIGNED(bytenr, fs_info->sectorsize)) { - generic_err(node, slot, - "unaligned pointer, have %llu should be aligned to %u", - bytenr, fs_info->sectorsize); - ret = BTRFS_TREE_BLOCK_INVALID_BLOCKPTR; - goto fail; - } - - if (btrfs_comp_cpu_keys(&key, &next_key) >= 0) { - generic_err(node, slot, - "bad key order, current (%llu %u %llu) next (%llu %u %llu)", - key.objectid, key.type, key.offset, - next_key.objectid, next_key.type, - next_key.offset); - ret = BTRFS_TREE_BLOCK_BAD_KEY_ORDER; - goto fail; - } - } - ret = BTRFS_TREE_BLOCK_CLEAN; -fail: - return ret; -} - -enum btrfs_tree_block_status __btrfs_check_leaf(struct extent_buffer *leaf) -{ - struct btrfs_fs_info *fs_info = leaf->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; - u32 nritems = btrfs_header_nritems(leaf); - int slot; - int ret; - - if (btrfs_header_level(leaf) != 0) { - generic_err(leaf, 0, - "invalid level for leaf, have %d expect 0", - btrfs_header_level(leaf)); - ret = BTRFS_TREE_BLOCK_INVALID_LEVEL; - goto fail; - } - - if (nritems == 0) - return 0; - - /* - * Check the following things to make sure this is a good leaf, and - * leaf users won't need to bother with similar sanity checks: - * - * 1) key ordering - * 2) item offset and size - * No overlap, no hole, all inside the leaf. - * 3) item content - * If possible, do comprehensive sanity check. - * NOTE: All checks must only rely on the item data itself. - */ - for (slot = 0; slot < nritems; slot++) { - u32 item_end_expected; - u64 item_data_end; - - btrfs_item_key_to_cpu(leaf, &key, slot); - - /* Make sure the keys are in the right order */ - if (btrfs_comp_cpu_keys(&prev_key, &key) >= 0) { - generic_err(leaf, slot, - "bad key order, prev (%llu %u %llu) current (%llu %u %llu)", - prev_key.objectid, prev_key.type, - prev_key.offset, key.objectid, key.type, - key.offset); - ret = BTRFS_TREE_BLOCK_BAD_KEY_ORDER; - goto fail; - } - - item_data_end = (u64)btrfs_item_offset(leaf, slot) + - btrfs_item_size(leaf, slot); - /* - * Make sure the offset and ends are right, remember that the - * item data starts at the end of the leaf and grows towards the - * front. - */ - if (slot == 0) - item_end_expected = BTRFS_LEAF_DATA_SIZE(fs_info); - else - item_end_expected = btrfs_item_offset(leaf, - slot - 1); - if (item_data_end != item_end_expected) { - generic_err(leaf, slot, - "unexpected item end, have %llu expect %u", - item_data_end, item_end_expected); - ret = BTRFS_TREE_BLOCK_INVALID_OFFSETS; - goto fail; - } - - /* - * Check to make sure that we don't point outside of the leaf, - * just in case all the items are consistent to each other, but - * all point outside of the leaf. - */ - if (item_data_end > BTRFS_LEAF_DATA_SIZE(fs_info)) { - generic_err(leaf, slot, - "slot end outside of leaf, have %llu expect range [0, %u]", - item_data_end, BTRFS_LEAF_DATA_SIZE(fs_info)); - ret = BTRFS_TREE_BLOCK_INVALID_OFFSETS; - goto fail; - } - - /* Also check if the item pointer overlaps with btrfs item. */ - if (btrfs_item_ptr_offset(leaf, slot) < - btrfs_item_nr_offset(leaf, slot) + sizeof(struct btrfs_item)) { - generic_err(leaf, slot, - "slot overlaps with its data, item end %lu data start %lu", - btrfs_item_nr_offset(leaf, slot) + - sizeof(struct btrfs_item), - btrfs_item_ptr_offset(leaf, slot)); - ret = BTRFS_TREE_BLOCK_INVALID_OFFSETS; - goto fail; - } - - prev_key.objectid = key.objectid; - prev_key.type = key.type; - prev_key.offset = key.offset; - } - - ret = BTRFS_TREE_BLOCK_CLEAN; -fail: - return ret; -} - static int noinline check_block(struct btrfs_fs_info *fs_info, struct btrfs_path *path, int level) { diff --git a/kernel-shared/ctree.h b/kernel-shared/ctree.h index 237f530d..5eba9c14 100644 --- a/kernel-shared/ctree.h +++ b/kernel-shared/ctree.h @@ -185,17 +185,6 @@ struct btrfs_path { sizeof(struct btrfs_item)) #define BTRFS_MAX_EXTENT_SIZE 128UL * 1024 * 1024 -enum btrfs_tree_block_status { - BTRFS_TREE_BLOCK_CLEAN, - BTRFS_TREE_BLOCK_INVALID_NRITEMS, - BTRFS_TREE_BLOCK_INVALID_PARENT_KEY, - BTRFS_TREE_BLOCK_BAD_KEY_ORDER, - BTRFS_TREE_BLOCK_INVALID_LEVEL, - BTRFS_TREE_BLOCK_INVALID_FREE_SPACE, - BTRFS_TREE_BLOCK_INVALID_OFFSETS, - BTRFS_TREE_BLOCK_INVALID_BLOCKPTR, -}; - /* * We don't want to overwrite 1M at the beginning of device, even though * there is our 1st superblock at 64k. Some possible reasons: @@ -373,6 +362,7 @@ struct btrfs_fs_info { unsigned int finalize_on_close:1; unsigned int hide_names:1; unsigned int allow_transid_mismatch:1; + unsigned int skip_leaf_item_checks:1; int transaction_aborted; int force_csum_type; @@ -958,8 +948,6 @@ int btrfs_convert_one_bg(struct btrfs_trans_handle *trans, u64 bytenr); int btrfs_comp_cpu_keys(const struct btrfs_key *k1, const struct btrfs_key *k2); int btrfs_del_ptr(struct btrfs_root *root, struct btrfs_path *path, int level, int slot); -enum btrfs_tree_block_status __btrfs_check_node(struct extent_buffer *buf); -enum btrfs_tree_block_status __btrfs_check_leaf(struct extent_buffer *buf); struct extent_buffer *read_node_slot(struct btrfs_fs_info *fs_info, struct extent_buffer *parent, int slot); int btrfs_previous_item(struct btrfs_root *root, diff --git a/kernel-shared/disk-io.c b/kernel-shared/disk-io.c index 4950c685..536b7119 100644 --- a/kernel-shared/disk-io.c +++ b/kernel-shared/disk-io.c @@ -37,6 +37,7 @@ #include "common/device-scan.h" #include "common/device-utils.h" #include "crypto/hash.h" +#include "tree-checker.h" /* specified errno for check_tree_block */ #define BTRFS_BAD_BYTENR (-1) @@ -1503,6 +1504,8 @@ static struct btrfs_fs_info *__open_ctree_fd(int fp, struct open_ctree_flags *oc fs_info->hide_names = 1; if (flags & OPEN_CTREE_ALLOW_TRANSID_MISMATCH) fs_info->allow_transid_mismatch = 1; + if (flags & OPEN_CTREE_SKIP_LEAF_ITEM_CHECKS) + fs_info->skip_leaf_item_checks = 1; if ((flags & OPEN_CTREE_RECOVER_SUPER) && (flags & OPEN_CTREE_TEMPORARY_SUPER)) { diff --git a/kernel-shared/disk-io.h b/kernel-shared/disk-io.h index 4c63a4a8..6baa4a80 100644 --- a/kernel-shared/disk-io.h +++ b/kernel-shared/disk-io.h @@ -98,6 +98,12 @@ enum btrfs_open_ctree_flags { * stored in the csum tree during conversion. */ OPEN_CTREE_SKIP_CSUM_CHECK = (1U << 16), + + /* + * Allow certain commands like check/restore to ignore more structure + * specific checks and only do the superficial checks. + */ + OPEN_CTREE_SKIP_LEAF_ITEM_CHECKS = (1U << 17), }; /* diff --git a/kernel-shared/tree-checker.c b/kernel-shared/tree-checker.c new file mode 100644 index 00000000..4f38942a --- /dev/null +++ b/kernel-shared/tree-checker.c @@ -0,0 +1,2064 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Copyright (C) Qu Wenruo 2017. All rights reserved. + */ + +/* + * The module is used to catch unexpected/corrupted tree block data. + * Such behavior can be caused either by a fuzzed image or bugs. + * + * The objective is to do leaf/node validation checks when tree block is read + * from disk, and check *every* possible member, so other code won't + * need to checking them again. + * + * Due to the potential and unwanted damage, every checker needs to be + * carefully reviewed otherwise so it does not prevent mount of valid images. + */ + +#include "kerncompat.h" +#include "kernel-lib/overflow.h" +#include "kernel-lib/bitops.h" +#include "common/internal.h" +#include +#include +#include +#include "messages.h" +#include "ctree.h" +#include "tree-checker.h" +#include "disk-io.h" +#include "compression.h" +#include "volumes.h" +#include "misc.h" +#include "accessors.h" +#include "file-item.h" + +/* + * btrfs_inode_item stores flags in a u64, btrfs_inode stores them in two + * separate u32s. These two functions convert between the two representations. + * + * MODIFIED: + * - Declared these here since this is the only place they're used currently. + */ +static inline u64 btrfs_inode_combine_flags(u32 flags, u32 ro_flags) +{ + return (flags | ((u64)ro_flags << 32)); +} + +static inline void btrfs_inode_split_flags(u64 inode_item_flags, + u32 *flags, u32 *ro_flags) +{ + *flags = (u32)inode_item_flags; + *ro_flags = (u32)(inode_item_flags >> 32); +} + +/* + * Error message should follow the following format: + * corrupt : , [, ] + * + * @type: leaf or node + * @identifier: the necessary info to locate the leaf/node. + * It's recommended to decode key.objecitd/offset if it's + * meaningful. + * @reason: describe the error + * @bad_value: optional, it's recommended to output bad value and its + * expected value (range). + * + * Since comma is used to separate the components, only space is allowed + * inside each component. + */ + +/* + * Append generic "corrupt leaf/node root=%llu block=%llu slot=%d: " to @fmt. + * Allows callers to customize the output. + */ +__printf(3, 4) +__cold +static void generic_err(const struct extent_buffer *eb, int slot, + const char *fmt, ...) +{ + const struct btrfs_fs_info *fs_info = eb->fs_info; + struct va_format vaf; + va_list args; + + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + btrfs_crit(fs_info, + "corrupt %s: root=%llu block=%llu slot=%d, %pV", + btrfs_header_level(eb) == 0 ? "leaf" : "node", + btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot, &vaf); + va_end(args); +} + +/* + * Customized reporter for extent data item, since its key objectid and + * offset has its own meaning. + */ +__printf(3, 4) +__cold +static void file_extent_err(const struct extent_buffer *eb, int slot, + const char *fmt, ...) +{ + const struct btrfs_fs_info *fs_info = eb->fs_info; + struct btrfs_key key; + struct va_format vaf; + va_list args; + + btrfs_item_key_to_cpu(eb, &key, slot); + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + btrfs_crit(fs_info, + "corrupt %s: root=%llu block=%llu slot=%d ino=%llu file_offset=%llu, %pV", + btrfs_header_level(eb) == 0 ? "leaf" : "node", + btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot, + key.objectid, key.offset, &vaf); + va_end(args); +} + +/* + * Return 0 if the btrfs_file_extent_##name is aligned to @alignment + * Else return 1 + */ +#define CHECK_FE_ALIGNED(leaf, slot, fi, name, alignment) \ +({ \ + if (unlikely(!IS_ALIGNED(btrfs_file_extent_##name((leaf), (fi)), \ + (alignment)))) \ + file_extent_err((leaf), (slot), \ + "invalid %s for file extent, have %llu, should be aligned to %u", \ + (#name), btrfs_file_extent_##name((leaf), (fi)), \ + (alignment)); \ + (!IS_ALIGNED(btrfs_file_extent_##name((leaf), (fi)), (alignment))); \ +}) + +static u64 file_extent_end(struct extent_buffer *leaf, + struct btrfs_key *key, + struct btrfs_file_extent_item *extent) +{ + u64 end; + u64 len; + + if (btrfs_file_extent_type(leaf, extent) == BTRFS_FILE_EXTENT_INLINE) { + len = btrfs_file_extent_ram_bytes(leaf, extent); + end = ALIGN(key->offset + len, leaf->fs_info->sectorsize); + } else { + len = btrfs_file_extent_num_bytes(leaf, extent); + end = key->offset + len; + } + return end; +} + +/* + * Customized report for dir_item, the only new important information is + * key->objectid, which represents inode number + */ +__printf(3, 4) +__cold +static void dir_item_err(const struct extent_buffer *eb, int slot, + const char *fmt, ...) +{ + const struct btrfs_fs_info *fs_info = eb->fs_info; + struct btrfs_key key; + struct va_format vaf; + va_list args; + + btrfs_item_key_to_cpu(eb, &key, slot); + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + btrfs_crit(fs_info, + "corrupt %s: root=%llu block=%llu slot=%d ino=%llu, %pV", + btrfs_header_level(eb) == 0 ? "leaf" : "node", + btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot, + key.objectid, &vaf); + va_end(args); +} + +/* + * This functions checks prev_key->objectid, to ensure current key and prev_key + * share the same objectid as inode number. + * + * This is to detect missing INODE_ITEM in subvolume trees. + * + * Return true if everything is OK or we don't need to check. + * Return false if anything is wrong. + */ +static bool check_prev_ino(struct extent_buffer *leaf, + struct btrfs_key *key, int slot, + struct btrfs_key *prev_key) +{ + /* No prev key, skip check */ + if (slot == 0) + return true; + + /* Only these key->types needs to be checked */ + ASSERT(key->type == BTRFS_XATTR_ITEM_KEY || + key->type == BTRFS_INODE_REF_KEY || + key->type == BTRFS_DIR_INDEX_KEY || + key->type == BTRFS_DIR_ITEM_KEY || + key->type == BTRFS_EXTENT_DATA_KEY); + + /* + * Only subvolume trees along with their reloc trees need this check. + * Things like log tree doesn't follow this ino requirement. + */ + if (!is_fstree(btrfs_header_owner(leaf))) + return true; + + if (key->objectid == prev_key->objectid) + return true; + + /* Error found */ + dir_item_err(leaf, slot, + "invalid previous key objectid, have %llu expect %llu", + prev_key->objectid, key->objectid); + return false; +} +static int check_extent_data_item(struct extent_buffer *leaf, + struct btrfs_key *key, int slot, + struct btrfs_key *prev_key) +{ + struct btrfs_fs_info *fs_info = leaf->fs_info; + struct btrfs_file_extent_item *fi; + u32 sectorsize = fs_info->sectorsize; + u32 item_size = btrfs_item_size(leaf, slot); + u64 extent_end; + + if (unlikely(!IS_ALIGNED(key->offset, sectorsize))) { + file_extent_err(leaf, slot, +"unaligned file_offset for file extent, have %llu should be aligned to %u", + key->offset, sectorsize); + return -EUCLEAN; + } + + /* + * Previous key must have the same key->objectid (ino). + * It can be XATTR_ITEM, INODE_ITEM or just another EXTENT_DATA. + * But if objectids mismatch, it means we have a missing + * INODE_ITEM. + */ + if (unlikely(!check_prev_ino(leaf, key, slot, prev_key))) + return -EUCLEAN; + + fi = btrfs_item_ptr(leaf, slot, struct btrfs_file_extent_item); + + /* + * Make sure the item contains at least inline header, so the file + * extent type is not some garbage. + */ + if (unlikely(item_size < BTRFS_FILE_EXTENT_INLINE_DATA_START)) { + file_extent_err(leaf, slot, + "invalid item size, have %u expect [%zu, %u)", + item_size, BTRFS_FILE_EXTENT_INLINE_DATA_START, + SZ_4K); + return -EUCLEAN; + } + if (unlikely(btrfs_file_extent_type(leaf, fi) >= + BTRFS_NR_FILE_EXTENT_TYPES)) { + file_extent_err(leaf, slot, + "invalid type for file extent, have %u expect range [0, %u]", + btrfs_file_extent_type(leaf, fi), + BTRFS_NR_FILE_EXTENT_TYPES - 1); + return -EUCLEAN; + } + + /* + * Support for new compression/encryption must introduce incompat flag, + * and must be caught in open_ctree(). + */ + if (unlikely(btrfs_file_extent_compression(leaf, fi) >= + BTRFS_NR_COMPRESS_TYPES)) { + file_extent_err(leaf, slot, + "invalid compression for file extent, have %u expect range [0, %u]", + btrfs_file_extent_compression(leaf, fi), + BTRFS_NR_COMPRESS_TYPES - 1); + return -EUCLEAN; + } + if (unlikely(btrfs_file_extent_encryption(leaf, fi))) { + file_extent_err(leaf, slot, + "invalid encryption for file extent, have %u expect 0", + btrfs_file_extent_encryption(leaf, fi)); + return -EUCLEAN; + } + if (btrfs_file_extent_type(leaf, fi) == BTRFS_FILE_EXTENT_INLINE) { + /* Inline extent must have 0 as key offset */ + if (unlikely(key->offset)) { + file_extent_err(leaf, slot, + "invalid file_offset for inline file extent, have %llu expect 0", + key->offset); + return -EUCLEAN; + } + + /* Compressed inline extent has no on-disk size, skip it */ + if (btrfs_file_extent_compression(leaf, fi) != + BTRFS_COMPRESS_NONE) + return 0; + + /* Uncompressed inline extent size must match item size */ + if (unlikely(item_size != BTRFS_FILE_EXTENT_INLINE_DATA_START + + btrfs_file_extent_ram_bytes(leaf, fi))) { + file_extent_err(leaf, slot, + "invalid ram_bytes for uncompressed inline extent, have %u expect %llu", + item_size, BTRFS_FILE_EXTENT_INLINE_DATA_START + + btrfs_file_extent_ram_bytes(leaf, fi)); + return -EUCLEAN; + } + return 0; + } + + /* Regular or preallocated extent has fixed item size */ + if (unlikely(item_size != sizeof(*fi))) { + file_extent_err(leaf, slot, + "invalid item size for reg/prealloc file extent, have %u expect %zu", + item_size, sizeof(*fi)); + return -EUCLEAN; + } + if (unlikely(CHECK_FE_ALIGNED(leaf, slot, fi, ram_bytes, sectorsize) || + CHECK_FE_ALIGNED(leaf, slot, fi, disk_bytenr, sectorsize) || + CHECK_FE_ALIGNED(leaf, slot, fi, disk_num_bytes, sectorsize) || + CHECK_FE_ALIGNED(leaf, slot, fi, offset, sectorsize) || + CHECK_FE_ALIGNED(leaf, slot, fi, num_bytes, sectorsize))) + return -EUCLEAN; + + /* Catch extent end overflow */ + if (unlikely(check_add_overflow(btrfs_file_extent_num_bytes(leaf, fi), + key->offset, &extent_end))) { + file_extent_err(leaf, slot, + "extent end overflow, have file offset %llu extent num bytes %llu", + key->offset, + btrfs_file_extent_num_bytes(leaf, fi)); + return -EUCLEAN; + } + + /* + * Check that no two consecutive file extent items, in the same leaf, + * present ranges that overlap each other. + */ + if (slot > 0 && + prev_key->objectid == key->objectid && + prev_key->type == BTRFS_EXTENT_DATA_KEY) { + struct btrfs_file_extent_item *prev_fi; + u64 prev_end; + + prev_fi = btrfs_item_ptr(leaf, slot - 1, + struct btrfs_file_extent_item); + prev_end = file_extent_end(leaf, prev_key, prev_fi); + if (unlikely(prev_end > key->offset)) { + file_extent_err(leaf, slot - 1, +"file extent end range (%llu) goes beyond start offset (%llu) of the next file extent", + prev_end, key->offset); + return -EUCLEAN; + } + } + + return 0; +} + +static int check_csum_item(struct extent_buffer *leaf, struct btrfs_key *key, + int slot, struct btrfs_key *prev_key) +{ + struct btrfs_fs_info *fs_info = leaf->fs_info; + u32 sectorsize = fs_info->sectorsize; + const u32 csumsize = fs_info->csum_size; + + if (unlikely(key->objectid != BTRFS_EXTENT_CSUM_OBJECTID)) { + generic_err(leaf, slot, + "invalid key objectid for csum item, have %llu expect %llu", + key->objectid, BTRFS_EXTENT_CSUM_OBJECTID); + return -EUCLEAN; + } + if (unlikely(!IS_ALIGNED(key->offset, sectorsize))) { + generic_err(leaf, slot, + "unaligned key offset for csum item, have %llu should be aligned to %u", + key->offset, sectorsize); + return -EUCLEAN; + } + if (unlikely(!IS_ALIGNED(btrfs_item_size(leaf, slot), csumsize))) { + generic_err(leaf, slot, + "unaligned item size for csum item, have %u should be aligned to %u", + btrfs_item_size(leaf, slot), csumsize); + return -EUCLEAN; + } + if (slot > 0 && prev_key->type == BTRFS_EXTENT_CSUM_KEY) { + u64 prev_csum_end; + u32 prev_item_size; + + prev_item_size = btrfs_item_size(leaf, slot - 1); + prev_csum_end = (prev_item_size / csumsize) * sectorsize; + prev_csum_end += prev_key->offset; + if (unlikely(prev_csum_end > key->offset)) { + generic_err(leaf, slot - 1, +"csum end range (%llu) goes beyond the start range (%llu) of the next csum item", + prev_csum_end, key->offset); + return -EUCLEAN; + } + } + return 0; +} + +/* Inode item error output has the same format as dir_item_err() */ +#define inode_item_err(eb, slot, fmt, ...) \ + dir_item_err(eb, slot, fmt, __VA_ARGS__) + +static int check_inode_key(struct extent_buffer *leaf, struct btrfs_key *key, + int slot) +{ + struct btrfs_key item_key; + bool is_inode_item; + + btrfs_item_key_to_cpu(leaf, &item_key, slot); + is_inode_item = (item_key.type == BTRFS_INODE_ITEM_KEY); + + /* For XATTR_ITEM, location key should be all 0 */ + if (item_key.type == BTRFS_XATTR_ITEM_KEY) { + if (unlikely(key->objectid != 0 || key->type != 0 || + key->offset != 0)) + return -EUCLEAN; + return 0; + } + + if (unlikely((key->objectid < BTRFS_FIRST_FREE_OBJECTID || + key->objectid > BTRFS_LAST_FREE_OBJECTID) && + key->objectid != BTRFS_ROOT_TREE_DIR_OBJECTID && + key->objectid != BTRFS_FREE_INO_OBJECTID)) { + if (is_inode_item) { + generic_err(leaf, slot, + "invalid key objectid: has %llu expect %llu or [%llu, %llu] or %llu", + key->objectid, BTRFS_ROOT_TREE_DIR_OBJECTID, + BTRFS_FIRST_FREE_OBJECTID, + BTRFS_LAST_FREE_OBJECTID, + BTRFS_FREE_INO_OBJECTID); + } else { + dir_item_err(leaf, slot, +"invalid location key objectid: has %llu expect %llu or [%llu, %llu] or %llu", + key->objectid, BTRFS_ROOT_TREE_DIR_OBJECTID, + BTRFS_FIRST_FREE_OBJECTID, + BTRFS_LAST_FREE_OBJECTID, + BTRFS_FREE_INO_OBJECTID); + } + return -EUCLEAN; + } + if (unlikely(key->offset != 0)) { + if (is_inode_item) + inode_item_err(leaf, slot, + "invalid key offset: has %llu expect 0", + key->offset); + else + dir_item_err(leaf, slot, + "invalid location key offset:has %llu expect 0", + key->offset); + return -EUCLEAN; + } + return 0; +} + +static int check_root_key(struct extent_buffer *leaf, struct btrfs_key *key, + int slot) +{ + struct btrfs_key item_key; + bool is_root_item; + + btrfs_item_key_to_cpu(leaf, &item_key, slot); + is_root_item = (item_key.type == BTRFS_ROOT_ITEM_KEY); + + /* No such tree id */ + if (unlikely(key->objectid == 0)) { + if (is_root_item) + generic_err(leaf, slot, "invalid root id 0"); + else + dir_item_err(leaf, slot, + "invalid location key root id 0"); + return -EUCLEAN; + } + + /* DIR_ITEM/INDEX/INODE_REF is not allowed to point to non-fs trees */ + if (unlikely(!is_fstree(key->objectid) && !is_root_item)) { + dir_item_err(leaf, slot, + "invalid location key objectid, have %llu expect [%llu, %llu]", + key->objectid, BTRFS_FIRST_FREE_OBJECTID, + BTRFS_LAST_FREE_OBJECTID); + return -EUCLEAN; + } + + /* + * ROOT_ITEM with non-zero offset means this is a snapshot, created at + * @offset transid. + * Furthermore, for location key in DIR_ITEM, its offset is always -1. + * + * So here we only check offset for reloc tree whose key->offset must + * be a valid tree. + */ + if (unlikely(key->objectid == BTRFS_TREE_RELOC_OBJECTID && + key->offset == 0)) { + generic_err(leaf, slot, "invalid root id 0 for reloc tree"); + return -EUCLEAN; + } + return 0; +} + +static int check_dir_item(struct extent_buffer *leaf, + struct btrfs_key *key, struct btrfs_key *prev_key, + int slot) +{ + struct btrfs_fs_info *fs_info = leaf->fs_info; + struct btrfs_dir_item *di; + u32 item_size = btrfs_item_size(leaf, slot); + u32 cur = 0; + + if (unlikely(!check_prev_ino(leaf, key, slot, prev_key))) + return -EUCLEAN; + + di = btrfs_item_ptr(leaf, slot, struct btrfs_dir_item); + while (cur < item_size) { + struct btrfs_key location_key; + u32 name_len; + u32 data_len; + u32 max_name_len; + u32 total_size; + u32 name_hash; + u8 dir_type; + int ret; + + /* header itself should not cross item boundary */ + if (unlikely(cur + sizeof(*di) > item_size)) { + dir_item_err(leaf, slot, + "dir item header crosses item boundary, have %zu boundary %u", + cur + sizeof(*di), item_size); + return -EUCLEAN; + } + + /* Location key check */ + btrfs_dir_item_key_to_cpu(leaf, di, &location_key); + if (location_key.type == BTRFS_ROOT_ITEM_KEY) { + ret = check_root_key(leaf, &location_key, slot); + if (unlikely(ret < 0)) + return ret; + } else if (location_key.type == BTRFS_INODE_ITEM_KEY || + location_key.type == 0) { + ret = check_inode_key(leaf, &location_key, slot); + if (unlikely(ret < 0)) + return ret; + } else { + dir_item_err(leaf, slot, + "invalid location key type, have %u, expect %u or %u", + location_key.type, BTRFS_ROOT_ITEM_KEY, + BTRFS_INODE_ITEM_KEY); + return -EUCLEAN; + } + + /* dir type check */ + dir_type = btrfs_dir_ftype(leaf, di); + if (unlikely(dir_type >= BTRFS_FT_MAX)) { + dir_item_err(leaf, slot, + "invalid dir item type, have %u expect [0, %u)", + dir_type, BTRFS_FT_MAX); + return -EUCLEAN; + } + + if (unlikely(key->type == BTRFS_XATTR_ITEM_KEY && + dir_type != BTRFS_FT_XATTR)) { + dir_item_err(leaf, slot, + "invalid dir item type for XATTR key, have %u expect %u", + dir_type, BTRFS_FT_XATTR); + return -EUCLEAN; + } + if (unlikely(dir_type == BTRFS_FT_XATTR && + key->type != BTRFS_XATTR_ITEM_KEY)) { + dir_item_err(leaf, slot, + "xattr dir type found for non-XATTR key"); + return -EUCLEAN; + } + if (dir_type == BTRFS_FT_XATTR) + max_name_len = XATTR_NAME_MAX; + else + max_name_len = BTRFS_NAME_LEN; + + /* Name/data length check */ + name_len = btrfs_dir_name_len(leaf, di); + data_len = btrfs_dir_data_len(leaf, di); + if (unlikely(name_len > max_name_len)) { + dir_item_err(leaf, slot, + "dir item name len too long, have %u max %u", + name_len, max_name_len); + return -EUCLEAN; + } + if (unlikely(name_len + data_len > BTRFS_MAX_XATTR_SIZE(fs_info))) { + dir_item_err(leaf, slot, + "dir item name and data len too long, have %u max %u", + name_len + data_len, + BTRFS_MAX_XATTR_SIZE(fs_info)); + return -EUCLEAN; + } + + if (unlikely(data_len && dir_type != BTRFS_FT_XATTR)) { + dir_item_err(leaf, slot, + "dir item with invalid data len, have %u expect 0", + data_len); + return -EUCLEAN; + } + + total_size = sizeof(*di) + name_len + data_len; + + /* header and name/data should not cross item boundary */ + if (unlikely(cur + total_size > item_size)) { + dir_item_err(leaf, slot, + "dir item data crosses item boundary, have %u boundary %u", + cur + total_size, item_size); + return -EUCLEAN; + } + + /* + * Special check for XATTR/DIR_ITEM, as key->offset is name + * hash, should match its name + */ + if (key->type == BTRFS_DIR_ITEM_KEY || + key->type == BTRFS_XATTR_ITEM_KEY) { + char namebuf[max(BTRFS_NAME_LEN, XATTR_NAME_MAX)]; + + read_extent_buffer(leaf, namebuf, + (unsigned long)(di + 1), name_len); + name_hash = btrfs_name_hash(namebuf, name_len); + if (unlikely(key->offset != name_hash)) { + dir_item_err(leaf, slot, + "name hash mismatch with key, have 0x%016x expect 0x%016llx", + name_hash, key->offset); + return -EUCLEAN; + } + } + cur += total_size; + di = (struct btrfs_dir_item *)((void *)di + total_size); + } + return 0; +} + +__printf(3, 4) +__cold +static void block_group_err(const struct extent_buffer *eb, int slot, + const char *fmt, ...) +{ + const struct btrfs_fs_info *fs_info = eb->fs_info; + struct btrfs_key key; + struct va_format vaf; + va_list args; + + btrfs_item_key_to_cpu(eb, &key, slot); + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + btrfs_crit(fs_info, + "corrupt %s: root=%llu block=%llu slot=%d bg_start=%llu bg_len=%llu, %pV", + btrfs_header_level(eb) == 0 ? "leaf" : "node", + btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot, + key.objectid, key.offset, &vaf); + va_end(args); +} + +static int check_block_group_item(struct extent_buffer *leaf, + struct btrfs_key *key, int slot) +{ + struct btrfs_fs_info *fs_info = leaf->fs_info; + struct btrfs_block_group_item bgi; + u32 item_size = btrfs_item_size(leaf, slot); + u64 chunk_objectid; + u64 flags; + u64 type; + + /* + * Here we don't really care about alignment since extent allocator can + * handle it. We care more about the size. + */ + if (unlikely(key->offset == 0)) { + block_group_err(leaf, slot, + "invalid block group size 0"); + return -EUCLEAN; + } + + if (unlikely(item_size != sizeof(bgi))) { + block_group_err(leaf, slot, + "invalid item size, have %u expect %zu", + item_size, sizeof(bgi)); + return -EUCLEAN; + } + + read_extent_buffer(leaf, &bgi, btrfs_item_ptr_offset(leaf, slot), + sizeof(bgi)); + chunk_objectid = btrfs_stack_block_group_chunk_objectid(&bgi); + if (btrfs_fs_incompat(fs_info, EXTENT_TREE_V2)) { + /* + * We don't init the nr_global_roots until we load the global + * roots, so this could be 0 at mount time. If it's 0 we'll + * just assume we're fine, and later we'll check against our + * actual value. + */ + if (unlikely(fs_info->nr_global_roots && + chunk_objectid >= fs_info->nr_global_roots)) { + block_group_err(leaf, slot, + "invalid block group global root id, have %llu, needs to be <= %llu", + chunk_objectid, + fs_info->nr_global_roots); + return -EUCLEAN; + } + } else if (unlikely(chunk_objectid != BTRFS_FIRST_CHUNK_TREE_OBJECTID)) { + block_group_err(leaf, slot, + "invalid block group chunk objectid, have %llu expect %llu", + btrfs_stack_block_group_chunk_objectid(&bgi), + BTRFS_FIRST_CHUNK_TREE_OBJECTID); + return -EUCLEAN; + } + + if (unlikely(btrfs_stack_block_group_used(&bgi) > key->offset)) { + block_group_err(leaf, slot, + "invalid block group used, have %llu expect [0, %llu)", + btrfs_stack_block_group_used(&bgi), key->offset); + return -EUCLEAN; + } + + flags = btrfs_stack_block_group_flags(&bgi); + if (unlikely(hweight64(flags & BTRFS_BLOCK_GROUP_PROFILE_MASK) > 1)) { + block_group_err(leaf, slot, +"invalid profile flags, have 0x%llx (%lu bits set) expect no more than 1 bit set", + flags & BTRFS_BLOCK_GROUP_PROFILE_MASK, + hweight64(flags & BTRFS_BLOCK_GROUP_PROFILE_MASK)); + return -EUCLEAN; + } + + type = flags & BTRFS_BLOCK_GROUP_TYPE_MASK; + if (unlikely(type != BTRFS_BLOCK_GROUP_DATA && + type != BTRFS_BLOCK_GROUP_METADATA && + type != BTRFS_BLOCK_GROUP_SYSTEM && + type != (BTRFS_BLOCK_GROUP_METADATA | + BTRFS_BLOCK_GROUP_DATA))) { + block_group_err(leaf, slot, +"invalid type, have 0x%llx (%lu bits set) expect either 0x%llx, 0x%llx, 0x%llx or 0x%llx", + type, hweight64(type), + BTRFS_BLOCK_GROUP_DATA, BTRFS_BLOCK_GROUP_METADATA, + BTRFS_BLOCK_GROUP_SYSTEM, + BTRFS_BLOCK_GROUP_METADATA | BTRFS_BLOCK_GROUP_DATA); + return -EUCLEAN; + } + return 0; +} + +__printf(4, 5) +__cold +static void chunk_err(const struct extent_buffer *leaf, + const struct btrfs_chunk *chunk, u64 logical, + const char *fmt, ...) +{ + const struct btrfs_fs_info *fs_info = leaf->fs_info; + bool is_sb; + struct va_format vaf; + va_list args; + int i; + int slot = -1; + + /* Only superblock eb is able to have such small offset */ + is_sb = (leaf->start == BTRFS_SUPER_INFO_OFFSET); + + if (!is_sb) { + /* + * Get the slot number by iterating through all slots, this + * would provide better readability. + */ + for (i = 0; i < btrfs_header_nritems(leaf); i++) { + if (btrfs_item_ptr_offset(leaf, i) == + (unsigned long)chunk) { + slot = i; + break; + } + } + } + va_start(args, fmt); + vaf.fmt = fmt; + vaf.va = &args; + + if (is_sb) + btrfs_crit(fs_info, + "corrupt superblock syschunk array: chunk_start=%llu, %pV", + logical, &vaf); + else + btrfs_crit(fs_info, + "corrupt leaf: root=%llu block=%llu slot=%d chunk_start=%llu, %pV", + BTRFS_CHUNK_TREE_OBJECTID, leaf->start, slot, + logical, &vaf); + va_end(args); +} + +/* + * The common chunk check which could also work on super block sys chunk array. + * + * Return -EUCLEAN if anything is corrupted. + * Return 0 if everything is OK. + */ +int btrfs_check_chunk_valid(struct extent_buffer *leaf, + struct btrfs_chunk *chunk, u64 logical) +{ + struct btrfs_fs_info *fs_info = leaf->fs_info; + u64 length; + u64 chunk_end; + u64 stripe_len; + u16 num_stripes; + u16 sub_stripes; + u64 type; + u64 features; + bool mixed = false; + int raid_index; + int nparity; + int ncopies; + + length = btrfs_chunk_length(leaf, chunk); + stripe_len = btrfs_chunk_stripe_len(leaf, chunk); + num_stripes = btrfs_chunk_num_stripes(leaf, chunk); + sub_stripes = btrfs_chunk_sub_stripes(leaf, chunk); + type = btrfs_chunk_type(leaf, chunk); + raid_index = btrfs_bg_flags_to_raid_index(type); + ncopies = btrfs_raid_array[raid_index].ncopies; + nparity = btrfs_raid_array[raid_index].nparity; + + if (unlikely(!num_stripes)) { + chunk_err(leaf, chunk, logical, + "invalid chunk num_stripes, have %u", num_stripes); + return -EUCLEAN; + } + if (unlikely(num_stripes < ncopies)) { + chunk_err(leaf, chunk, logical, + "invalid chunk num_stripes < ncopies, have %u < %d", + num_stripes, ncopies); + return -EUCLEAN; + } + if (unlikely(nparity && num_stripes == nparity)) { + chunk_err(leaf, chunk, logical, + "invalid chunk num_stripes == nparity, have %u == %d", + num_stripes, nparity); + return -EUCLEAN; + } + if (unlikely(!IS_ALIGNED(logical, fs_info->sectorsize))) { + chunk_err(leaf, chunk, logical, + "invalid chunk logical, have %llu should aligned to %u", + logical, fs_info->sectorsize); + return -EUCLEAN; + } + if (unlikely(btrfs_chunk_sector_size(leaf, chunk) != fs_info->sectorsize)) { + chunk_err(leaf, chunk, logical, + "invalid chunk sectorsize, have %u expect %u", + btrfs_chunk_sector_size(leaf, chunk), + fs_info->sectorsize); + return -EUCLEAN; + } + if (unlikely(!length || !IS_ALIGNED(length, fs_info->sectorsize))) { + chunk_err(leaf, chunk, logical, + "invalid chunk length, have %llu", length); + return -EUCLEAN; + } + if (unlikely(check_add_overflow(logical, length, &chunk_end))) { + chunk_err(leaf, chunk, logical, +"invalid chunk logical start and length, have logical start %llu length %llu", + logical, length); + return -EUCLEAN; + } + if (unlikely(!is_power_of_2(stripe_len) || stripe_len != BTRFS_STRIPE_LEN)) { + chunk_err(leaf, chunk, logical, + "invalid chunk stripe length: %llu", + stripe_len); + return -EUCLEAN; + } + /* + * We artificially limit the chunk size, so that the number of stripes + * inside a chunk can be fit into a U32. The current limit (256G) is + * way too large for real world usage anyway, and it's also much larger + * than our existing limit (10G). + * + * Thus it should be a good way to catch obvious bitflips. + */ + if (unlikely(length >= ((u64)U32_MAX << BTRFS_STRIPE_LEN_SHIFT))) { + chunk_err(leaf, chunk, logical, + "chunk length too large: have %llu limit %llu", + length, (u64)U32_MAX << BTRFS_STRIPE_LEN_SHIFT); + return -EUCLEAN; + } + if (unlikely(type & ~(BTRFS_BLOCK_GROUP_TYPE_MASK | + BTRFS_BLOCK_GROUP_PROFILE_MASK))) { + chunk_err(leaf, chunk, logical, + "unrecognized chunk type: 0x%llx", + ~(BTRFS_BLOCK_GROUP_TYPE_MASK | + BTRFS_BLOCK_GROUP_PROFILE_MASK) & + btrfs_chunk_type(leaf, chunk)); + return -EUCLEAN; + } + + if (unlikely(!has_single_bit_set(type & BTRFS_BLOCK_GROUP_PROFILE_MASK) && + (type & BTRFS_BLOCK_GROUP_PROFILE_MASK) != 0)) { + chunk_err(leaf, chunk, logical, + "invalid chunk profile flag: 0x%llx, expect 0 or 1 bit set", + type & BTRFS_BLOCK_GROUP_PROFILE_MASK); + return -EUCLEAN; + } + if (unlikely((type & BTRFS_BLOCK_GROUP_TYPE_MASK) == 0)) { + chunk_err(leaf, chunk, logical, + "missing chunk type flag, have 0x%llx one bit must be set in 0x%llx", + type, BTRFS_BLOCK_GROUP_TYPE_MASK); + return -EUCLEAN; + } + + if (unlikely((type & BTRFS_BLOCK_GROUP_SYSTEM) && + (type & (BTRFS_BLOCK_GROUP_METADATA | + BTRFS_BLOCK_GROUP_DATA)))) { + chunk_err(leaf, chunk, logical, + "system chunk with data or metadata type: 0x%llx", + type); + return -EUCLEAN; + } + + features = btrfs_super_incompat_flags(fs_info->super_copy); + if (features & BTRFS_FEATURE_INCOMPAT_MIXED_GROUPS) + mixed = true; + + if (!mixed) { + if (unlikely((type & BTRFS_BLOCK_GROUP_METADATA) && + (type & BTRFS_BLOCK_GROUP_DATA))) { + chunk_err(leaf, chunk, logical, + "mixed chunk type in non-mixed mode: 0x%llx", type); + return -EUCLEAN; + } + } + + if (unlikely((type & BTRFS_BLOCK_GROUP_RAID10 && + sub_stripes != btrfs_raid_array[BTRFS_RAID_RAID10].sub_stripes) || + (type & BTRFS_BLOCK_GROUP_RAID1 && + num_stripes != btrfs_raid_array[BTRFS_RAID_RAID1].devs_min) || + (type & BTRFS_BLOCK_GROUP_RAID1C3 && + num_stripes != btrfs_raid_array[BTRFS_RAID_RAID1C3].devs_min) || + (type & BTRFS_BLOCK_GROUP_RAID1C4 && + num_stripes != btrfs_raid_array[BTRFS_RAID_RAID1C4].devs_min) || + (type & BTRFS_BLOCK_GROUP_RAID5 && + num_stripes < btrfs_raid_array[BTRFS_RAID_RAID5].devs_min) || + (type & BTRFS_BLOCK_GROUP_RAID6 && + num_stripes < btrfs_raid_array[BTRFS_RAID_RAID6].devs_min) || + (type & BTRFS_BLOCK_GROUP_DUP && + num_stripes != btrfs_raid_array[BTRFS_RAID_DUP].dev_stripes) || + ((type & BTRFS_BLOCK_GROUP_PROFILE_MASK) == 0 && + num_stripes != btrfs_raid_array[BTRFS_RAID_SINGLE].dev_stripes))) { + chunk_err(leaf, chunk, logical, + "invalid num_stripes:sub_stripes %u:%u for profile %llu", + num_stripes, sub_stripes, + type & BTRFS_BLOCK_GROUP_PROFILE_MASK); + return -EUCLEAN; + } + + return 0; +} + +/* + * Enhanced version of chunk item checker. + * + * The common btrfs_check_chunk_valid() doesn't check item size since it needs + * to work on super block sys_chunk_array which doesn't have full item ptr. + */ +static int check_leaf_chunk_item(struct extent_buffer *leaf, + struct btrfs_chunk *chunk, + struct btrfs_key *key, int slot) +{ + int num_stripes; + + if (unlikely(btrfs_item_size(leaf, slot) < sizeof(struct btrfs_chunk))) { + chunk_err(leaf, chunk, key->offset, + "invalid chunk item size: have %u expect [%zu, %u)", + btrfs_item_size(leaf, slot), + sizeof(struct btrfs_chunk), + BTRFS_LEAF_DATA_SIZE(leaf->fs_info)); + return -EUCLEAN; + } + + num_stripes = btrfs_chunk_num_stripes(leaf, chunk); + /* Let btrfs_check_chunk_valid() handle this error type */ + if (num_stripes == 0) + goto out; + + if (unlikely(btrfs_chunk_item_size(num_stripes) != + btrfs_item_size(leaf, slot))) { + chunk_err(leaf, chunk, key->offset, + "invalid chunk item size: have %u expect %lu", + btrfs_item_size(leaf, slot), + btrfs_chunk_item_size(num_stripes)); + return -EUCLEAN; + } +out: + return btrfs_check_chunk_valid(leaf, chunk, key->offset); +} + +__printf(3, 4) +__cold +static void dev_item_err(const struct extent_buffer *eb, int slot, + const char *fmt, ...) +{ + struct btrfs_key key; + struct va_format vaf; + va_list args; + + btrfs_item_key_to_cpu(eb, &key, slot); + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + btrfs_crit(eb->fs_info, + "corrupt %s: root=%llu block=%llu slot=%d devid=%llu %pV", + btrfs_header_level(eb) == 0 ? "leaf" : "node", + btrfs_header_owner(eb), btrfs_header_bytenr(eb), slot, + key.objectid, &vaf); + va_end(args); +} + +static int check_dev_item(struct extent_buffer *leaf, + struct btrfs_key *key, int slot) +{ + struct btrfs_dev_item *ditem; + const u32 item_size = btrfs_item_size(leaf, slot); + + if (unlikely(key->objectid != BTRFS_DEV_ITEMS_OBJECTID)) { + dev_item_err(leaf, slot, + "invalid objectid: has=%llu expect=%llu", + key->objectid, BTRFS_DEV_ITEMS_OBJECTID); + return -EUCLEAN; + } + + if (unlikely(item_size != sizeof(*ditem))) { + dev_item_err(leaf, slot, "invalid item size: has %u expect %zu", + item_size, sizeof(*ditem)); + return -EUCLEAN; + } + + ditem = btrfs_item_ptr(leaf, slot, struct btrfs_dev_item); + if (unlikely(btrfs_device_id(leaf, ditem) != key->offset)) { + dev_item_err(leaf, slot, + "devid mismatch: key has=%llu item has=%llu", + key->offset, btrfs_device_id(leaf, ditem)); + return -EUCLEAN; + } + + /* + * For device total_bytes, we don't have reliable way to check it, as + * it can be 0 for device removal. Device size check can only be done + * by dev extents check. + */ + if (unlikely(btrfs_device_bytes_used(leaf, ditem) > + btrfs_device_total_bytes(leaf, ditem))) { + dev_item_err(leaf, slot, + "invalid bytes used: have %llu expect [0, %llu]", + btrfs_device_bytes_used(leaf, ditem), + btrfs_device_total_bytes(leaf, ditem)); + return -EUCLEAN; + } + /* + * Remaining members like io_align/type/gen/dev_group aren't really + * utilized. Skip them to make later usage of them easier. + */ + return 0; +} + +static int check_inode_item(struct extent_buffer *leaf, + struct btrfs_key *key, int slot) +{ + struct btrfs_fs_info *fs_info = leaf->fs_info; + struct btrfs_inode_item *iitem; + u64 super_gen = btrfs_super_generation(fs_info->super_copy); + u32 valid_mask = (S_IFMT | S_ISUID | S_ISGID | S_ISVTX | 0777); + const u32 item_size = btrfs_item_size(leaf, slot); + u32 mode; + int ret; + u32 flags; + u32 ro_flags; + + ret = check_inode_key(leaf, key, slot); + if (unlikely(ret < 0)) + return ret; + + if (unlikely(item_size != sizeof(*iitem))) { + generic_err(leaf, slot, "invalid item size: has %u expect %zu", + item_size, sizeof(*iitem)); + return -EUCLEAN; + } + + iitem = btrfs_item_ptr(leaf, slot, struct btrfs_inode_item); + + /* Here we use super block generation + 1 to handle log tree */ + if (unlikely(btrfs_inode_generation(leaf, iitem) > super_gen + 1)) { + inode_item_err(leaf, slot, + "invalid inode generation: has %llu expect (0, %llu]", + btrfs_inode_generation(leaf, iitem), + super_gen + 1); + return -EUCLEAN; + } + /* Note for ROOT_TREE_DIR_ITEM, mkfs could set its transid 0 */ + if (unlikely(btrfs_inode_transid(leaf, iitem) > super_gen + 1)) { + inode_item_err(leaf, slot, + "invalid inode transid: has %llu expect [0, %llu]", + btrfs_inode_transid(leaf, iitem), super_gen + 1); + return -EUCLEAN; + } + + /* + * For size and nbytes it's better not to be too strict, as for dir + * item its size/nbytes can easily get wrong, but doesn't affect + * anything in the fs. So here we skip the check. + */ + mode = btrfs_inode_mode(leaf, iitem); + if (unlikely(mode & ~valid_mask)) { + inode_item_err(leaf, slot, + "unknown mode bit detected: 0x%x", + mode & ~valid_mask); + return -EUCLEAN; + } + + /* + * S_IFMT is not bit mapped so we can't completely rely on + * is_power_of_2/has_single_bit_set, but it can save us from checking + * FIFO/CHR/DIR/REG. Only needs to check BLK, LNK and SOCKS + */ + if (!has_single_bit_set(mode & S_IFMT)) { + if (unlikely(!S_ISLNK(mode) && !S_ISBLK(mode) && !S_ISSOCK(mode))) { + inode_item_err(leaf, slot, + "invalid mode: has 0%o expect valid S_IF* bit(s)", + mode & S_IFMT); + return -EUCLEAN; + } + } + if (unlikely(S_ISDIR(mode) && btrfs_inode_nlink(leaf, iitem) > 1)) { + inode_item_err(leaf, slot, + "invalid nlink: has %u expect no more than 1 for dir", + btrfs_inode_nlink(leaf, iitem)); + return -EUCLEAN; + } + btrfs_inode_split_flags(btrfs_inode_flags(leaf, iitem), &flags, &ro_flags); + if (unlikely(flags & ~BTRFS_INODE_FLAG_MASK)) { + inode_item_err(leaf, slot, + "unknown incompat flags detected: 0x%x", flags); + return -EUCLEAN; + } + if (unlikely(!sb_rdonly(fs_info->sb) && + (ro_flags & ~BTRFS_INODE_RO_FLAG_MASK))) { + inode_item_err(leaf, slot, + "unknown ro-compat flags detected on writeable mount: 0x%x", + ro_flags); + return -EUCLEAN; + } + return 0; +} + +static int check_root_item(struct extent_buffer *leaf, struct btrfs_key *key, + int slot) +{ + struct btrfs_fs_info *fs_info = leaf->fs_info; + struct btrfs_root_item ri = { 0 }; + const u64 valid_root_flags = BTRFS_ROOT_SUBVOL_RDONLY | + BTRFS_ROOT_SUBVOL_DEAD; + int ret; + + ret = check_root_key(leaf, key, slot); + if (unlikely(ret < 0)) + return ret; + + if (unlikely(btrfs_item_size(leaf, slot) != sizeof(ri) && + btrfs_item_size(leaf, slot) != + btrfs_legacy_root_item_size())) { + generic_err(leaf, slot, + "invalid root item size, have %u expect %zu or %u", + btrfs_item_size(leaf, slot), sizeof(ri), + btrfs_legacy_root_item_size()); + return -EUCLEAN; + } + + /* + * For legacy root item, the members starting at generation_v2 will be + * all filled with 0. + * And since we allow geneartion_v2 as 0, it will still pass the check. + */ + read_extent_buffer(leaf, &ri, btrfs_item_ptr_offset(leaf, slot), + btrfs_item_size(leaf, slot)); + + /* Generation related */ + if (unlikely(btrfs_root_generation(&ri) > + btrfs_super_generation(fs_info->super_copy) + 1)) { + generic_err(leaf, slot, + "invalid root generation, have %llu expect (0, %llu]", + btrfs_root_generation(&ri), + btrfs_super_generation(fs_info->super_copy) + 1); + return -EUCLEAN; + } + if (unlikely(btrfs_root_generation_v2(&ri) > + btrfs_super_generation(fs_info->super_copy) + 1)) { + generic_err(leaf, slot, + "invalid root v2 generation, have %llu expect (0, %llu]", + btrfs_root_generation_v2(&ri), + btrfs_super_generation(fs_info->super_copy) + 1); + return -EUCLEAN; + } + if (unlikely(btrfs_root_last_snapshot(&ri) > + btrfs_super_generation(fs_info->super_copy) + 1)) { + generic_err(leaf, slot, + "invalid root last_snapshot, have %llu expect (0, %llu]", + btrfs_root_last_snapshot(&ri), + btrfs_super_generation(fs_info->super_copy) + 1); + return -EUCLEAN; + } + + /* Alignment and level check */ + if (unlikely(!IS_ALIGNED(btrfs_root_bytenr(&ri), fs_info->sectorsize))) { + generic_err(leaf, slot, + "invalid root bytenr, have %llu expect to be aligned to %u", + btrfs_root_bytenr(&ri), fs_info->sectorsize); + return -EUCLEAN; + } + if (unlikely(btrfs_root_level(&ri) >= BTRFS_MAX_LEVEL)) { + generic_err(leaf, slot, + "invalid root level, have %u expect [0, %u]", + btrfs_root_level(&ri), BTRFS_MAX_LEVEL - 1); + return -EUCLEAN; + } + if (unlikely(btrfs_root_drop_level(&ri) >= BTRFS_MAX_LEVEL)) { + generic_err(leaf, slot, + "invalid root level, have %u expect [0, %u]", + btrfs_root_drop_level(&ri), BTRFS_MAX_LEVEL - 1); + return -EUCLEAN; + } + + /* Flags check */ + if (unlikely(btrfs_root_flags(&ri) & ~valid_root_flags)) { + generic_err(leaf, slot, + "invalid root flags, have 0x%llx expect mask 0x%llx", + btrfs_root_flags(&ri), valid_root_flags); + return -EUCLEAN; + } + return 0; +} + +__printf(3,4) +__cold +static void extent_err(const struct extent_buffer *eb, int slot, + const char *fmt, ...) +{ + struct btrfs_key key; + struct va_format vaf; + va_list args; + u64 bytenr; + u64 len; + + btrfs_item_key_to_cpu(eb, &key, slot); + bytenr = key.objectid; + if (key.type == BTRFS_METADATA_ITEM_KEY || + key.type == BTRFS_TREE_BLOCK_REF_KEY || + key.type == BTRFS_SHARED_BLOCK_REF_KEY) + len = eb->fs_info->nodesize; + else + len = key.offset; + va_start(args, fmt); + + vaf.fmt = fmt; + vaf.va = &args; + + btrfs_crit(eb->fs_info, + "corrupt %s: block=%llu slot=%d extent bytenr=%llu len=%llu %pV", + btrfs_header_level(eb) == 0 ? "leaf" : "node", + eb->start, slot, bytenr, len, &vaf); + va_end(args); +} + +static int check_extent_item(struct extent_buffer *leaf, + struct btrfs_key *key, int slot, + struct btrfs_key *prev_key) +{ + struct btrfs_fs_info *fs_info = leaf->fs_info; + struct btrfs_extent_item *ei; + bool is_tree_block = false; + unsigned long ptr; /* Current pointer inside inline refs */ + unsigned long end; /* Extent item end */ + const u32 item_size = btrfs_item_size(leaf, slot); + u64 flags; + u64 generation; + u64 total_refs; /* Total refs in btrfs_extent_item */ + u64 inline_refs = 0; /* found total inline refs */ + + if (unlikely(key->type == BTRFS_METADATA_ITEM_KEY && + !btrfs_fs_incompat(fs_info, SKINNY_METADATA))) { + generic_err(leaf, slot, +"invalid key type, METADATA_ITEM type invalid when SKINNY_METADATA feature disabled"); + return -EUCLEAN; + } + /* key->objectid is the bytenr for both key types */ + if (unlikely(!IS_ALIGNED(key->objectid, fs_info->sectorsize))) { + generic_err(leaf, slot, + "invalid key objectid, have %llu expect to be aligned to %u", + key->objectid, fs_info->sectorsize); + return -EUCLEAN; + } + + /* key->offset is tree level for METADATA_ITEM_KEY */ + if (unlikely(key->type == BTRFS_METADATA_ITEM_KEY && + key->offset >= BTRFS_MAX_LEVEL)) { + extent_err(leaf, slot, + "invalid tree level, have %llu expect [0, %u]", + key->offset, BTRFS_MAX_LEVEL - 1); + return -EUCLEAN; + } + + /* + * EXTENT/METADATA_ITEM consists of: + * 1) One btrfs_extent_item + * Records the total refs, type and generation of the extent. + * + * 2) One btrfs_tree_block_info (for EXTENT_ITEM and tree backref only) + * Records the first key and level of the tree block. + * + * 2) Zero or more btrfs_extent_inline_ref(s) + * Each inline ref has one btrfs_extent_inline_ref shows: + * 2.1) The ref type, one of the 4 + * TREE_BLOCK_REF Tree block only + * SHARED_BLOCK_REF Tree block only + * EXTENT_DATA_REF Data only + * SHARED_DATA_REF Data only + * 2.2) Ref type specific data + * Either using btrfs_extent_inline_ref::offset, or specific + * data structure. + */ + if (unlikely(item_size < sizeof(*ei))) { + extent_err(leaf, slot, + "invalid item size, have %u expect [%zu, %u)", + item_size, sizeof(*ei), + BTRFS_LEAF_DATA_SIZE(fs_info)); + return -EUCLEAN; + } + end = item_size + btrfs_item_ptr_offset(leaf, slot); + + /* Checks against extent_item */ + ei = btrfs_item_ptr(leaf, slot, struct btrfs_extent_item); + flags = btrfs_extent_flags(leaf, ei); + total_refs = btrfs_extent_refs(leaf, ei); + generation = btrfs_extent_generation(leaf, ei); + if (unlikely(generation > + btrfs_super_generation(fs_info->super_copy) + 1)) { + extent_err(leaf, slot, + "invalid generation, have %llu expect (0, %llu]", + generation, + btrfs_super_generation(fs_info->super_copy) + 1); + return -EUCLEAN; + } + if (unlikely(!has_single_bit_set(flags & (BTRFS_EXTENT_FLAG_DATA | + BTRFS_EXTENT_FLAG_TREE_BLOCK)))) { + extent_err(leaf, slot, + "invalid extent flag, have 0x%llx expect 1 bit set in 0x%llx", + flags, BTRFS_EXTENT_FLAG_DATA | + BTRFS_EXTENT_FLAG_TREE_BLOCK); + return -EUCLEAN; + } + is_tree_block = !!(flags & BTRFS_EXTENT_FLAG_TREE_BLOCK); + if (is_tree_block) { + if (unlikely(key->type == BTRFS_EXTENT_ITEM_KEY && + key->offset != fs_info->nodesize)) { + extent_err(leaf, slot, + "invalid extent length, have %llu expect %u", + key->offset, fs_info->nodesize); + return -EUCLEAN; + } + } else { + if (unlikely(key->type != BTRFS_EXTENT_ITEM_KEY)) { + extent_err(leaf, slot, + "invalid key type, have %u expect %u for data backref", + key->type, BTRFS_EXTENT_ITEM_KEY); + return -EUCLEAN; + } + if (unlikely(!IS_ALIGNED(key->offset, fs_info->sectorsize))) { + extent_err(leaf, slot, + "invalid extent length, have %llu expect aligned to %u", + key->offset, fs_info->sectorsize); + return -EUCLEAN; + } + if (unlikely(flags & BTRFS_BLOCK_FLAG_FULL_BACKREF)) { + extent_err(leaf, slot, + "invalid extent flag, data has full backref set"); + return -EUCLEAN; + } + } + ptr = (unsigned long)(struct btrfs_extent_item *)(ei + 1); + + /* Check the special case of btrfs_tree_block_info */ + if (is_tree_block && key->type != BTRFS_METADATA_ITEM_KEY) { + struct btrfs_tree_block_info *info; + + info = (struct btrfs_tree_block_info *)ptr; + if (unlikely(btrfs_tree_block_level(leaf, info) >= BTRFS_MAX_LEVEL)) { + extent_err(leaf, slot, + "invalid tree block info level, have %u expect [0, %u]", + btrfs_tree_block_level(leaf, info), + BTRFS_MAX_LEVEL - 1); + return -EUCLEAN; + } + ptr = (unsigned long)(struct btrfs_tree_block_info *)(info + 1); + } + + /* Check inline refs */ + while (ptr < end) { + struct btrfs_extent_inline_ref *iref; + struct btrfs_extent_data_ref *dref; + struct btrfs_shared_data_ref *sref; + u64 dref_offset; + u64 inline_offset; + u8 inline_type; + + if (unlikely(ptr + sizeof(*iref) > end)) { + extent_err(leaf, slot, +"inline ref item overflows extent item, ptr %lu iref size %zu end %lu", + ptr, sizeof(*iref), end); + return -EUCLEAN; + } + iref = (struct btrfs_extent_inline_ref *)ptr; + inline_type = btrfs_extent_inline_ref_type(leaf, iref); + inline_offset = btrfs_extent_inline_ref_offset(leaf, iref); + if (unlikely(ptr + btrfs_extent_inline_ref_size(inline_type) > end)) { + extent_err(leaf, slot, +"inline ref item overflows extent item, ptr %lu iref size %u end %lu", + ptr, inline_type, end); + return -EUCLEAN; + } + + switch (inline_type) { + /* inline_offset is subvolid of the owner, no need to check */ + case BTRFS_TREE_BLOCK_REF_KEY: + inline_refs++; + break; + /* Contains parent bytenr */ + case BTRFS_SHARED_BLOCK_REF_KEY: + if (unlikely(!IS_ALIGNED(inline_offset, + fs_info->sectorsize))) { + extent_err(leaf, slot, + "invalid tree parent bytenr, have %llu expect aligned to %u", + inline_offset, fs_info->sectorsize); + return -EUCLEAN; + } + inline_refs++; + break; + /* + * Contains owner subvolid, owner key objectid, adjusted offset. + * The only obvious corruption can happen in that offset. + */ + case BTRFS_EXTENT_DATA_REF_KEY: + dref = (struct btrfs_extent_data_ref *)(&iref->offset); + dref_offset = btrfs_extent_data_ref_offset(leaf, dref); + if (unlikely(!IS_ALIGNED(dref_offset, + fs_info->sectorsize))) { + extent_err(leaf, slot, + "invalid data ref offset, have %llu expect aligned to %u", + dref_offset, fs_info->sectorsize); + return -EUCLEAN; + } + inline_refs += btrfs_extent_data_ref_count(leaf, dref); + break; + /* Contains parent bytenr and ref count */ + case BTRFS_SHARED_DATA_REF_KEY: + sref = (struct btrfs_shared_data_ref *)(iref + 1); + if (unlikely(!IS_ALIGNED(inline_offset, + fs_info->sectorsize))) { + extent_err(leaf, slot, + "invalid data parent bytenr, have %llu expect aligned to %u", + inline_offset, fs_info->sectorsize); + return -EUCLEAN; + } + inline_refs += btrfs_shared_data_ref_count(leaf, sref); + break; + default: + extent_err(leaf, slot, "unknown inline ref type: %u", + inline_type); + return -EUCLEAN; + } + ptr += btrfs_extent_inline_ref_size(inline_type); + } + /* No padding is allowed */ + if (unlikely(ptr != end)) { + extent_err(leaf, slot, + "invalid extent item size, padding bytes found"); + return -EUCLEAN; + } + + /* Finally, check the inline refs against total refs */ + if (unlikely(inline_refs > total_refs)) { + extent_err(leaf, slot, + "invalid extent refs, have %llu expect >= inline %llu", + total_refs, inline_refs); + return -EUCLEAN; + } + + if ((prev_key->type == BTRFS_EXTENT_ITEM_KEY) || + (prev_key->type == BTRFS_METADATA_ITEM_KEY)) { + u64 prev_end = prev_key->objectid; + + if (prev_key->type == BTRFS_METADATA_ITEM_KEY) + prev_end += fs_info->nodesize; + else + prev_end += prev_key->offset; + + if (unlikely(prev_end > key->objectid)) { + extent_err(leaf, slot, + "previous extent [%llu %u %llu] overlaps current extent [%llu %u %llu]", + prev_key->objectid, prev_key->type, + prev_key->offset, key->objectid, key->type, + key->offset); + return -EUCLEAN; + } + } + + return 0; +} + +static int check_simple_keyed_refs(struct extent_buffer *leaf, + struct btrfs_key *key, int slot) +{ + u32 expect_item_size = 0; + + if (key->type == BTRFS_SHARED_DATA_REF_KEY) + expect_item_size = sizeof(struct btrfs_shared_data_ref); + + if (unlikely(btrfs_item_size(leaf, slot) != expect_item_size)) { + generic_err(leaf, slot, + "invalid item size, have %u expect %u for key type %u", + btrfs_item_size(leaf, slot), + expect_item_size, key->type); + return -EUCLEAN; + } + if (unlikely(!IS_ALIGNED(key->objectid, leaf->fs_info->sectorsize))) { + generic_err(leaf, slot, +"invalid key objectid for shared block ref, have %llu expect aligned to %u", + key->objectid, leaf->fs_info->sectorsize); + return -EUCLEAN; + } + if (unlikely(key->type != BTRFS_TREE_BLOCK_REF_KEY && + !IS_ALIGNED(key->offset, leaf->fs_info->sectorsize))) { + extent_err(leaf, slot, + "invalid tree parent bytenr, have %llu expect aligned to %u", + key->offset, leaf->fs_info->sectorsize); + return -EUCLEAN; + } + return 0; +} + +static int check_extent_data_ref(struct extent_buffer *leaf, + struct btrfs_key *key, int slot) +{ + struct btrfs_extent_data_ref *dref; + unsigned long ptr = btrfs_item_ptr_offset(leaf, slot); + const unsigned long end = ptr + btrfs_item_size(leaf, slot); + + if (unlikely(btrfs_item_size(leaf, slot) % sizeof(*dref) != 0)) { + generic_err(leaf, slot, + "invalid item size, have %u expect aligned to %zu for key type %u", + btrfs_item_size(leaf, slot), + sizeof(*dref), key->type); + return -EUCLEAN; + } + if (unlikely(!IS_ALIGNED(key->objectid, leaf->fs_info->sectorsize))) { + generic_err(leaf, slot, +"invalid key objectid for shared block ref, have %llu expect aligned to %u", + key->objectid, leaf->fs_info->sectorsize); + return -EUCLEAN; + } + for (; ptr < end; ptr += sizeof(*dref)) { + u64 offset; + + /* + * We cannot check the extent_data_ref hash due to possible + * overflow from the leaf due to hash collisions. + */ + dref = (struct btrfs_extent_data_ref *)ptr; + offset = btrfs_extent_data_ref_offset(leaf, dref); + if (unlikely(!IS_ALIGNED(offset, leaf->fs_info->sectorsize))) { + extent_err(leaf, slot, + "invalid extent data backref offset, have %llu expect aligned to %u", + offset, leaf->fs_info->sectorsize); + return -EUCLEAN; + } + } + return 0; +} + +#define inode_ref_err(eb, slot, fmt, args...) \ + inode_item_err(eb, slot, fmt, ##args) +static int check_inode_ref(struct extent_buffer *leaf, + struct btrfs_key *key, struct btrfs_key *prev_key, + int slot) +{ + struct btrfs_inode_ref *iref; + unsigned long ptr; + unsigned long end; + + if (unlikely(!check_prev_ino(leaf, key, slot, prev_key))) + return -EUCLEAN; + /* namelen can't be 0, so item_size == sizeof() is also invalid */ + if (unlikely(btrfs_item_size(leaf, slot) <= sizeof(*iref))) { + inode_ref_err(leaf, slot, + "invalid item size, have %u expect (%zu, %u)", + btrfs_item_size(leaf, slot), + sizeof(*iref), BTRFS_LEAF_DATA_SIZE(leaf->fs_info)); + return -EUCLEAN; + } + + ptr = btrfs_item_ptr_offset(leaf, slot); + end = ptr + btrfs_item_size(leaf, slot); + while (ptr < end) { + u16 namelen; + + if (unlikely(ptr + sizeof(iref) > end)) { + inode_ref_err(leaf, slot, + "inode ref overflow, ptr %lu end %lu inode_ref_size %zu", + ptr, end, sizeof(iref)); + return -EUCLEAN; + } + + iref = (struct btrfs_inode_ref *)ptr; + namelen = btrfs_inode_ref_name_len(leaf, iref); + if (unlikely(ptr + sizeof(*iref) + namelen > end)) { + inode_ref_err(leaf, slot, + "inode ref overflow, ptr %lu end %lu namelen %u", + ptr, end, namelen); + return -EUCLEAN; + } + + /* + * NOTE: In theory we should record all found index numbers + * to find any duplicated indexes, but that will be too time + * consuming for inodes with too many hard links. + */ + ptr += sizeof(*iref) + namelen; + } + return 0; +} + +/* + * Common point to switch the item-specific validation. + */ +static enum btrfs_tree_block_status check_leaf_item(struct extent_buffer *leaf, + struct btrfs_key *key, + int slot, + struct btrfs_key *prev_key) +{ + struct btrfs_fs_info *fs_info = leaf->fs_info; + struct btrfs_chunk *chunk; + int ret = 0; + + if (fs_info->skip_leaf_item_checks) + return 0; + + switch (key->type) { + case BTRFS_EXTENT_DATA_KEY: + ret = check_extent_data_item(leaf, key, slot, prev_key); + break; + case BTRFS_EXTENT_CSUM_KEY: + ret = check_csum_item(leaf, key, slot, prev_key); + break; + case BTRFS_DIR_ITEM_KEY: + case BTRFS_DIR_INDEX_KEY: + case BTRFS_XATTR_ITEM_KEY: + ret = check_dir_item(leaf, key, prev_key, slot); + break; + case BTRFS_INODE_REF_KEY: + ret = check_inode_ref(leaf, key, prev_key, slot); + break; + case BTRFS_BLOCK_GROUP_ITEM_KEY: + ret = check_block_group_item(leaf, key, slot); + break; + case BTRFS_CHUNK_ITEM_KEY: + chunk = btrfs_item_ptr(leaf, slot, struct btrfs_chunk); + ret = check_leaf_chunk_item(leaf, chunk, key, slot); + break; + case BTRFS_DEV_ITEM_KEY: + ret = check_dev_item(leaf, key, slot); + break; + case BTRFS_INODE_ITEM_KEY: + ret = check_inode_item(leaf, key, slot); + break; + case BTRFS_ROOT_ITEM_KEY: + ret = check_root_item(leaf, key, slot); + break; + case BTRFS_EXTENT_ITEM_KEY: + case BTRFS_METADATA_ITEM_KEY: + ret = check_extent_item(leaf, key, slot, prev_key); + break; + case BTRFS_TREE_BLOCK_REF_KEY: + case BTRFS_SHARED_DATA_REF_KEY: + case BTRFS_SHARED_BLOCK_REF_KEY: + ret = check_simple_keyed_refs(leaf, key, slot); + break; + case BTRFS_EXTENT_DATA_REF_KEY: + ret = check_extent_data_ref(leaf, key, slot); + break; + } + + if (ret) + return BTRFS_TREE_BLOCK_INVALID_ITEM; + return BTRFS_TREE_BLOCK_CLEAN; +} + +enum btrfs_tree_block_status __btrfs_check_leaf(struct extent_buffer *leaf) +{ + struct btrfs_fs_info *fs_info = leaf->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; + u32 nritems = btrfs_header_nritems(leaf); + int slot; + bool check_item_data = btrfs_header_flag(leaf, BTRFS_HEADER_FLAG_WRITTEN); + + if (unlikely(btrfs_header_level(leaf) != 0)) { + generic_err(leaf, 0, + "invalid level for leaf, have %d expect 0", + btrfs_header_level(leaf)); + return BTRFS_TREE_BLOCK_INVALID_LEVEL; + } + + /* + * MODIFIED: + * - We need to skip the below checks for the temporary fs state during + * mkfs or --init-extent-tree. + */ + if (nritems == 0 && + (btrfs_super_magic(fs_info->super_copy) == BTRFS_MAGIC_TEMPORARY || + fs_info->skip_leaf_item_checks)) + return BTRFS_TREE_BLOCK_CLEAN; + + /* + * Extent buffers from a relocation tree have a owner field that + * corresponds to the subvolume tree they are based on. So just from an + * extent buffer alone we can not find out what is the id of the + * corresponding subvolume tree, so we can not figure out if the extent + * buffer corresponds to the root of the relocation tree or not. So + * skip this check for relocation trees. + */ + if (nritems == 0 && !btrfs_header_flag(leaf, BTRFS_HEADER_FLAG_RELOC)) { + u64 owner = btrfs_header_owner(leaf); + + /* These trees must never be empty */ + if (unlikely(owner == BTRFS_ROOT_TREE_OBJECTID || + owner == BTRFS_CHUNK_TREE_OBJECTID || + owner == BTRFS_DEV_TREE_OBJECTID || + owner == BTRFS_FS_TREE_OBJECTID || + owner == BTRFS_DATA_RELOC_TREE_OBJECTID)) { + generic_err(leaf, 0, + "invalid root, root %llu must never be empty", + owner); + return BTRFS_TREE_BLOCK_INVALID_NRITEMS; + } + + /* Unknown tree */ + if (unlikely(owner == 0)) { + generic_err(leaf, 0, + "invalid owner, root 0 is not defined"); + return BTRFS_TREE_BLOCK_INVALID_OWNER; + } + + /* EXTENT_TREE_V2 can have empty extent trees. */ + if (btrfs_fs_incompat(fs_info, EXTENT_TREE_V2)) + return BTRFS_TREE_BLOCK_CLEAN; + + if (unlikely(owner == BTRFS_EXTENT_TREE_OBJECTID)) { + generic_err(leaf, 0, + "invalid root, root %llu must never be empty", + owner); + return BTRFS_TREE_BLOCK_INVALID_NRITEMS; + } + + return BTRFS_TREE_BLOCK_CLEAN; + } + + if (unlikely(nritems == 0)) + return BTRFS_TREE_BLOCK_CLEAN; + + /* + * Check the following things to make sure this is a good leaf, and + * leaf users won't need to bother with similar sanity checks: + * + * 1) key ordering + * 2) item offset and size + * No overlap, no hole, all inside the leaf. + * 3) item content + * If possible, do comprehensive sanity check. + * NOTE: All checks must only rely on the item data itself. + */ + for (slot = 0; slot < nritems; slot++) { + u32 item_end_expected; + u64 item_data_end; + + btrfs_item_key_to_cpu(leaf, &key, slot); + + /* Make sure the keys are in the right order */ + if (unlikely(btrfs_comp_cpu_keys(&prev_key, &key) >= 0)) { + generic_err(leaf, slot, + "bad key order, prev (%llu %u %llu) current (%llu %u %llu)", + prev_key.objectid, prev_key.type, + prev_key.offset, key.objectid, key.type, + key.offset); + return BTRFS_TREE_BLOCK_BAD_KEY_ORDER; + } + + item_data_end = (u64)btrfs_item_offset(leaf, slot) + + btrfs_item_size(leaf, slot); + /* + * Make sure the offset and ends are right, remember that the + * item data starts at the end of the leaf and grows towards the + * front. + */ + if (slot == 0) + item_end_expected = BTRFS_LEAF_DATA_SIZE(fs_info); + else + item_end_expected = btrfs_item_offset(leaf, + slot - 1); + if (unlikely(item_data_end != item_end_expected)) { + generic_err(leaf, slot, + "unexpected item end, have %llu expect %u", + item_data_end, item_end_expected); + return BTRFS_TREE_BLOCK_INVALID_OFFSETS; + } + + /* + * Check to make sure that we don't point outside of the leaf, + * just in case all the items are consistent to each other, but + * all point outside of the leaf. + */ + if (unlikely(item_data_end > BTRFS_LEAF_DATA_SIZE(fs_info))) { + generic_err(leaf, slot, + "slot end outside of leaf, have %llu expect range [0, %u]", + item_data_end, BTRFS_LEAF_DATA_SIZE(fs_info)); + return BTRFS_TREE_BLOCK_INVALID_OFFSETS; + } + + /* Also check if the item pointer overlaps with btrfs item. */ + if (unlikely(btrfs_item_ptr_offset(leaf, slot) < + btrfs_item_nr_offset(leaf, slot) + sizeof(struct btrfs_item))) { + generic_err(leaf, slot, + "slot overlaps with its data, item end %lu data start %lu", + btrfs_item_nr_offset(leaf, slot) + + sizeof(struct btrfs_item), + btrfs_item_ptr_offset(leaf, slot)); + return BTRFS_TREE_BLOCK_INVALID_OFFSETS; + } + + /* + * We only want to do this if WRITTEN is set, otherwise the leaf + * may be in some intermediate state and won't appear valid. + */ + if (check_item_data) { + enum btrfs_tree_block_status ret; + + /* + * Check if the item size and content meet other + * criteria + */ + ret = check_leaf_item(leaf, &key, slot, &prev_key); + if (unlikely(ret != BTRFS_TREE_BLOCK_CLEAN)) + return ret; + } + + prev_key.objectid = key.objectid; + prev_key.type = key.type; + prev_key.offset = key.offset; + } + + return BTRFS_TREE_BLOCK_CLEAN; +} + +int btrfs_check_leaf(struct extent_buffer *leaf) +{ + enum btrfs_tree_block_status ret; + + ret = __btrfs_check_leaf(leaf); + if (unlikely(ret != BTRFS_TREE_BLOCK_CLEAN)) + return -EUCLEAN; + return 0; +} +ALLOW_ERROR_INJECTION(btrfs_check_leaf, ERRNO); + +enum btrfs_tree_block_status __btrfs_check_node(struct extent_buffer *node) +{ + struct btrfs_fs_info *fs_info = node->fs_info; + unsigned long nr = btrfs_header_nritems(node); + struct btrfs_key key, next_key; + int slot; + int level = btrfs_header_level(node); + u64 bytenr; + + if (unlikely(level <= 0 || level >= BTRFS_MAX_LEVEL)) { + generic_err(node, 0, + "invalid level for node, have %d expect [1, %d]", + level, BTRFS_MAX_LEVEL - 1); + return BTRFS_TREE_BLOCK_INVALID_LEVEL; + } + if (unlikely(nr == 0 || nr > BTRFS_NODEPTRS_PER_BLOCK(fs_info))) { + btrfs_crit(fs_info, +"corrupt node: root=%llu block=%llu, nritems too %s, have %lu expect range [1,%u]", + btrfs_header_owner(node), node->start, + nr == 0 ? "small" : "large", nr, + BTRFS_NODEPTRS_PER_BLOCK(fs_info)); + return BTRFS_TREE_BLOCK_INVALID_NRITEMS; + } + + for (slot = 0; slot < nr - 1; slot++) { + bytenr = btrfs_node_blockptr(node, slot); + btrfs_node_key_to_cpu(node, &key, slot); + btrfs_node_key_to_cpu(node, &next_key, slot + 1); + + if (unlikely(!bytenr)) { + generic_err(node, slot, + "invalid NULL node pointer"); + return BTRFS_TREE_BLOCK_INVALID_BLOCKPTR; + } + if (unlikely(!IS_ALIGNED(bytenr, fs_info->sectorsize))) { + generic_err(node, slot, + "unaligned pointer, have %llu should be aligned to %u", + bytenr, fs_info->sectorsize); + return BTRFS_TREE_BLOCK_INVALID_BLOCKPTR; + } + + if (unlikely(btrfs_comp_cpu_keys(&key, &next_key) >= 0)) { + generic_err(node, slot, + "bad key order, current (%llu %u %llu) next (%llu %u %llu)", + key.objectid, key.type, key.offset, + next_key.objectid, next_key.type, + next_key.offset); + return BTRFS_TREE_BLOCK_BAD_KEY_ORDER; + } + } + return BTRFS_TREE_BLOCK_CLEAN; +} + +int btrfs_check_node(struct extent_buffer *node) +{ + enum btrfs_tree_block_status ret; + + ret = __btrfs_check_node(node); + if (unlikely(ret != BTRFS_TREE_BLOCK_CLEAN)) + return -EUCLEAN; + return 0; +} +ALLOW_ERROR_INJECTION(btrfs_check_node, ERRNO); + +int btrfs_check_eb_owner(const struct extent_buffer *eb, u64 root_owner) +{ + const bool is_subvol = is_fstree(root_owner); + const u64 eb_owner = btrfs_header_owner(eb); + + /* + * Skip dummy fs, as selftests don't create unique ebs for each dummy + * root. + * + * MODIFIED: + * - The ->fs_state member doesn't exist in btrfs-progs yet. + * + if (test_bit(BTRFS_FS_STATE_DUMMY_FS_INFO, &eb->fs_info->fs_state)) + return 0; + */ + + /* + * There are several call sites (backref walking, qgroup, and data + * reloc) passing 0 as @root_owner, as they are not holding the + * tree root. In that case, we can not do a reliable ownership check, + * so just exit. + */ + if (root_owner == 0) + return 0; + /* + * These trees use key.offset as their owner, our callers don't have + * the extra capacity to pass key.offset here. So we just skip them. + */ + if (root_owner == BTRFS_TREE_LOG_OBJECTID || + root_owner == BTRFS_TREE_RELOC_OBJECTID) + return 0; + + if (!is_subvol) { + /* For non-subvolume trees, the eb owner should match root owner */ + if (unlikely(root_owner != eb_owner)) { + btrfs_crit(eb->fs_info, +"corrupted %s, root=%llu block=%llu owner mismatch, have %llu expect %llu", + btrfs_header_level(eb) == 0 ? "leaf" : "node", + root_owner, btrfs_header_bytenr(eb), eb_owner, + root_owner); + return -EUCLEAN; + } + return 0; + } + + /* + * For subvolume trees, owners can mismatch, but they should all belong + * to subvolume trees. + */ + if (unlikely(is_subvol != is_fstree(eb_owner))) { + btrfs_crit(eb->fs_info, +"corrupted %s, root=%llu block=%llu owner mismatch, have %llu expect [%llu, %llu]", + btrfs_header_level(eb) == 0 ? "leaf" : "node", + root_owner, btrfs_header_bytenr(eb), eb_owner, + BTRFS_FIRST_FREE_OBJECTID, BTRFS_LAST_FREE_OBJECTID); + return -EUCLEAN; + } + return 0; +} + +int btrfs_verify_level_key(struct extent_buffer *eb, int level, + struct btrfs_key *first_key, u64 parent_transid) +{ + struct btrfs_fs_info *fs_info = eb->fs_info; + int found_level; + struct btrfs_key found_key; + int ret; + + found_level = btrfs_header_level(eb); + if (found_level != level) { + WARN(IS_ENABLED(CONFIG_BTRFS_DEBUG), + KERN_ERR "BTRFS: tree level check failed\n"); + btrfs_err(fs_info, +"tree level mismatch detected, bytenr=%llu level expected=%u has=%u", + eb->start, level, found_level); + return -EIO; + } + + if (!first_key) + return 0; + + /* + * For live tree block (new tree blocks in current transaction), + * we need proper lock context to avoid race, which is impossible here. + * So we only checks tree blocks which is read from disk, whose + * generation <= fs_info->last_trans_committed. + */ + if (btrfs_header_generation(eb) > fs_info->last_trans_committed) + return 0; + + /* We have @first_key, so this @eb must have at least one item */ + if (btrfs_header_nritems(eb) == 0) { + btrfs_err(fs_info, + "invalid tree nritems, bytenr=%llu nritems=0 expect >0", + eb->start); + WARN_ON(IS_ENABLED(CONFIG_BTRFS_DEBUG)); + return -EUCLEAN; + } + + if (found_level) + btrfs_node_key_to_cpu(eb, &found_key, 0); + else + btrfs_item_key_to_cpu(eb, &found_key, 0); + ret = btrfs_comp_cpu_keys(first_key, &found_key); + + if (ret) { + WARN(IS_ENABLED(CONFIG_BTRFS_DEBUG), + KERN_ERR "BTRFS: tree first key check failed\n"); + btrfs_err(fs_info, +"tree first key mismatch detected, bytenr=%llu parent_transid=%llu key expected=(%llu,%u,%llu) has=(%llu,%u,%llu)", + eb->start, parent_transid, first_key->objectid, + first_key->type, first_key->offset, + found_key.objectid, found_key.type, + found_key.offset); + } + return ret; +} diff --git a/kernel-shared/tree-checker.h b/kernel-shared/tree-checker.h new file mode 100644 index 00000000..9c4ba01a --- /dev/null +++ b/kernel-shared/tree-checker.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) Qu Wenruo 2017. All rights reserved. + */ + +#ifndef BTRFS_TREE_CHECKER_H +#define BTRFS_TREE_CHECKER_H + +#include "uapi/btrfs_tree.h" + +struct extent_buffer; +struct btrfs_chunk; + +/* All the extra info needed to verify the parentness of a tree block. */ +struct btrfs_tree_parent_check { + /* + * The owner check against the tree block. + * + * Can be 0 to skip the owner check. + */ + u64 owner_root; + + /* + * Expected transid, can be 0 to skip the check, but such skip + * should only be utlized for backref walk related code. + */ + u64 transid; + + /* + * The expected first key. + * + * This check can be skipped if @has_first_key is false, such skip + * can happen for case where we don't have the parent node key, + * e.g. reading the tree root, doing backref walk. + */ + struct btrfs_key first_key; + bool has_first_key; + + /* The expected level. Should always be set. */ + u8 level; +}; + +enum btrfs_tree_block_status { + BTRFS_TREE_BLOCK_CLEAN, + BTRFS_TREE_BLOCK_INVALID_NRITEMS, + BTRFS_TREE_BLOCK_INVALID_PARENT_KEY, + BTRFS_TREE_BLOCK_BAD_KEY_ORDER, + BTRFS_TREE_BLOCK_INVALID_LEVEL, + BTRFS_TREE_BLOCK_INVALID_FREE_SPACE, + BTRFS_TREE_BLOCK_INVALID_OFFSETS, + BTRFS_TREE_BLOCK_INVALID_BLOCKPTR, + BTRFS_TREE_BLOCK_INVALID_ITEM, + BTRFS_TREE_BLOCK_INVALID_OWNER, +}; + +/* + * Exported simply for btrfs-progs which wants to have the + * btrfs_tree_block_status return codes. + */ +enum btrfs_tree_block_status __btrfs_check_leaf(struct extent_buffer *leaf); +enum btrfs_tree_block_status __btrfs_check_node(struct extent_buffer *node); + +int btrfs_check_leaf(struct extent_buffer *leaf); +int btrfs_check_node(struct extent_buffer *node); + +int btrfs_check_chunk_valid(struct extent_buffer *leaf, + struct btrfs_chunk *chunk, u64 logical); +int btrfs_check_eb_owner(const struct extent_buffer *eb, u64 root_owner); +int btrfs_verify_level_key(struct extent_buffer *eb, int level, + struct btrfs_key *first_key, u64 parent_transid); + +#endif diff --git a/kernel-shared/volumes.c b/kernel-shared/volumes.c index 14fcefee..fff49a06 100644 --- a/kernel-shared/volumes.c +++ b/kernel-shared/volumes.c @@ -32,6 +32,7 @@ #include "common/utils.h" #include "common/device-utils.h" #include "kernel-lib/raid56.h" +#include "tree-checker.h" const struct btrfs_raid_attr btrfs_raid_array[BTRFS_NR_RAID_TYPES] = { [BTRFS_RAID_RAID10] = { @@ -2086,101 +2087,6 @@ static struct btrfs_device *fill_missing_device(u64 devid) return device; } -/* - * slot == -1: SYSTEM chunk - * return -EIO on error, otherwise return 0 - */ -int btrfs_check_chunk_valid(struct extent_buffer *leaf, - struct btrfs_chunk *chunk, u64 logical) -{ - struct btrfs_fs_info *fs_info = leaf->fs_info; - u64 length; - u64 stripe_len; - u16 num_stripes; - u16 sub_stripes; - u64 type; - u32 sectorsize = fs_info->sectorsize; - int min_devs; - int table_sub_stripes; - - length = btrfs_chunk_length(leaf, chunk); - stripe_len = btrfs_chunk_stripe_len(leaf, chunk); - num_stripes = btrfs_chunk_num_stripes(leaf, chunk); - sub_stripes = btrfs_chunk_sub_stripes(leaf, chunk); - type = btrfs_chunk_type(leaf, chunk); - - if (num_stripes == 0) { - error("invalid num_stripes, have %u expect non-zero", - num_stripes); - return -EUCLEAN; - } - - /* - * These valid checks may be insufficient to cover every corner cases. - */ - if (!IS_ALIGNED(logical, sectorsize)) { - error("invalid chunk logical %llu", logical); - return -EIO; - } - if (btrfs_chunk_sector_size(leaf, chunk) != sectorsize) { - error("invalid chunk sectorsize %llu", - (unsigned long long)btrfs_chunk_sector_size(leaf, chunk)); - return -EIO; - } - if (!length || !IS_ALIGNED(length, sectorsize)) { - error("invalid chunk length %llu", length); - return -EIO; - } - if (stripe_len != BTRFS_STRIPE_LEN) { - error("invalid chunk stripe length: %llu", stripe_len); - return -EIO; - } - if (type & ~(BTRFS_BLOCK_GROUP_TYPE_MASK | - BTRFS_BLOCK_GROUP_PROFILE_MASK)) { - error("unrecognized chunk type: %llu", - ~(BTRFS_BLOCK_GROUP_TYPE_MASK | - BTRFS_BLOCK_GROUP_PROFILE_MASK) & type); - return -EIO; - } - if (!(type & BTRFS_BLOCK_GROUP_TYPE_MASK)) { - error("missing chunk type flag: %llu", type); - return -EIO; - } - if (!(is_power_of_2(type & BTRFS_BLOCK_GROUP_PROFILE_MASK) || - (type & BTRFS_BLOCK_GROUP_PROFILE_MASK) == 0)) { - error("conflicting chunk type detected: %llu", type); - return -EIO; - } - if ((type & BTRFS_BLOCK_GROUP_PROFILE_MASK) && - !is_power_of_2(type & BTRFS_BLOCK_GROUP_PROFILE_MASK)) { - error("conflicting chunk profile detected: %llu", type); - return -EIO; - } - - /* - * Device number check against profile - */ - min_devs = btrfs_bg_type_to_devs_min(type); - table_sub_stripes = btrfs_bg_type_to_sub_stripes(type); - if ((type & BTRFS_BLOCK_GROUP_RAID10 && (sub_stripes != table_sub_stripes || - !IS_ALIGNED(num_stripes, sub_stripes))) || - (type & BTRFS_BLOCK_GROUP_RAID1 && num_stripes < min_devs) || - (type & BTRFS_BLOCK_GROUP_RAID1C3 && num_stripes < min_devs) || - (type & BTRFS_BLOCK_GROUP_RAID1C4 && num_stripes < min_devs) || - (type & BTRFS_BLOCK_GROUP_RAID5 && num_stripes < min_devs) || - (type & BTRFS_BLOCK_GROUP_RAID6 && num_stripes < min_devs) || - (type & BTRFS_BLOCK_GROUP_DUP && num_stripes > 2) || - ((type & BTRFS_BLOCK_GROUP_PROFILE_MASK) == 0 && - num_stripes != 1)) { - error("Invalid num_stripes:sub_stripes %u:%u for profile %llu", - num_stripes, sub_stripes, - type & BTRFS_BLOCK_GROUP_PROFILE_MASK); - return -EIO; - } - - return 0; -} - /* * Slot is used to verify the chunk item is valid * diff --git a/kernel-shared/volumes.h b/kernel-shared/volumes.h index 84fd6617..ab5ac402 100644 --- a/kernel-shared/volumes.h +++ b/kernel-shared/volumes.h @@ -294,8 +294,6 @@ int write_raid56_with_parity(struct btrfs_fs_info *info, struct extent_buffer *eb, struct btrfs_multi_bio *multi, u64 stripe_len, u64 *raid_map); -int btrfs_check_chunk_valid(struct extent_buffer *leaf, - struct btrfs_chunk *chunk, u64 logical); u64 btrfs_stripe_length(struct btrfs_fs_info *fs_info, struct extent_buffer *leaf, struct btrfs_chunk *chunk);