From patchwork Mon Feb 18 16:57:26 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Filipe Manana X-Patchwork-Id: 10818469 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id A9E0D922 for ; Mon, 18 Feb 2019 16:57:35 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 94F74285B6 for ; Mon, 18 Feb 2019 16:57:35 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 8946028749; Mon, 18 Feb 2019 16:57:35 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 24F01285B6 for ; Mon, 18 Feb 2019 16:57:35 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2390586AbfBRQ5e (ORCPT ); Mon, 18 Feb 2019 11:57:34 -0500 Received: from mail.kernel.org ([198.145.29.99]:50604 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1733069AbfBRQ5d (ORCPT ); Mon, 18 Feb 2019 11:57:33 -0500 Received: from localhost.localdomain (bl8-197-74.dsl.telepac.pt [85.241.197.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 3D996217D9 for ; Mon, 18 Feb 2019 16:57:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1550509052; bh=833AhtYNEdCN5QHN4RhPLemCXmIQpROEAaIvtSTmo+8=; h=From:To:Subject:Date:From; b=hGq7jebukOfwfZMpIOHTXfr5qP9EkgGNoyI2DI8KGcjeeevIacFqqFjtCAdBskCpM ld+QPUKqcYPXZdkQkTjN3vGs7cE6xfMpbW05ofboEwi/8thn72nVGCftmGVg7MIJzJ beuY6AxqxBtGnMvQIwR2+HEzgi3ZJ06e0qGo3AI4= From: fdmanana@kernel.org To: linux-btrfs@vger.kernel.org Subject: [PATCH 1/2] Btrfs: add missing error handling after doing leaf/node binary search Date: Mon, 18 Feb 2019 16:57:26 +0000 Message-Id: <20190218165726.22884-1-fdmanana@kernel.org> X-Mailer: git-send-email 2.11.0 Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Filipe Manana The function map_private_extent_buffer() can return an -EINVAL error, and it is called by generic_bin_search() which will return back the error. The btrfs_bin_search() function in turn calls generic_bin_search() and the key_search() function calls btrfs_bin_search(), so both can return the -EINVAL error coming from the map_private_extent_buffer() function. Some callers of these functions were ignoring that these functions can return an error, so fix them to deal with error return values. Signed-off-by: Filipe Manana --- fs/btrfs/ctree.c | 6 ++++++ fs/btrfs/relocation.c | 6 ++++++ fs/btrfs/tree-log.c | 2 ++ 3 files changed, 14 insertions(+) diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 5a6c39b44c84..5b9f602fb9e2 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -3005,6 +3005,8 @@ int btrfs_search_old_slot(struct btrfs_root *root, const struct btrfs_key *key, */ prev_cmp = -1; ret = key_search(b, key, level, &prev_cmp, &slot); + if (ret < 0) + goto done; if (level != 0) { int dec = 0; @@ -5156,6 +5158,10 @@ int btrfs_search_forward(struct btrfs_root *root, struct btrfs_key *min_key, nritems = btrfs_header_nritems(cur); level = btrfs_header_level(cur); sret = btrfs_bin_search(cur, min_key, level, &slot); + if (sret < 0) { + ret = sret; + goto out; + } /* at the lowest level, we're done, setup the path and exit */ if (level == path->lowest_level) { diff --git a/fs/btrfs/relocation.c b/fs/btrfs/relocation.c index 272b287f8cf0..434a5b159b65 100644 --- a/fs/btrfs/relocation.c +++ b/fs/btrfs/relocation.c @@ -1802,6 +1802,8 @@ int replace_path(struct btrfs_trans_handle *trans, struct reloc_control *rc, BUG_ON(level < lowest_level); ret = btrfs_bin_search(parent, &key, level, &slot); + if (ret < 0) + break; if (ret && slot > 0) slot--; @@ -2685,6 +2687,8 @@ static int do_relocation(struct btrfs_trans_handle *trans, if (!lowest) { ret = btrfs_bin_search(upper->eb, key, upper->level, &slot); + if (ret < 0) + break; BUG_ON(ret); bytenr = btrfs_node_blockptr(upper->eb, slot); if (node->eb->start == bytenr) @@ -2720,6 +2724,8 @@ static int do_relocation(struct btrfs_trans_handle *trans, } else { ret = btrfs_bin_search(upper->eb, key, upper->level, &slot); + if (ret < 0) + break; BUG_ON(ret); } diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c index 8c9e87f5ec58..81a357a32837 100644 --- a/fs/btrfs/tree-log.c +++ b/fs/btrfs/tree-log.c @@ -3772,6 +3772,8 @@ static int drop_objectid_items(struct btrfs_trans_handle *trans, found_key.type = 0; ret = btrfs_bin_search(path->nodes[0], &found_key, 0, &start_slot); + if (ret < 0) + break; ret = btrfs_del_items(trans, log, path, start_slot, path->slots[0] - start_slot + 1); From patchwork Mon Feb 18 16:58:26 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Filipe Manana X-Patchwork-Id: 10818471 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 39CE5139A for ; Mon, 18 Feb 2019 16:58:33 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2707E2B482 for ; Mon, 18 Feb 2019 16:58:33 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 1B9AE2B4A2; Mon, 18 Feb 2019 16:58:33 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A6B732B493 for ; Mon, 18 Feb 2019 16:58:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2390667AbfBRQ6b (ORCPT ); Mon, 18 Feb 2019 11:58:31 -0500 Received: from mail.kernel.org ([198.145.29.99]:51270 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1733096AbfBRQ6a (ORCPT ); Mon, 18 Feb 2019 11:58:30 -0500 Received: from localhost.localdomain (bl8-197-74.dsl.telepac.pt [85.241.197.74]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 6187F217D9 for ; Mon, 18 Feb 2019 16:58:29 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1550509109; bh=tYoBjZ88Er6kjw7d8Zy9+mgR8Lhr6r0h7dMWYr3k4nM=; h=From:To:Subject:Date:From; b=nlZ6XfkP1lfkpidRWwxBiHSWmPvMqAP4Y5sY+rkufRo+ZoBbHZf41Sb8Jevgnfmmx q13IT7AjtwXp6LOa2powO0GDKiMElcHjM6zoaIh+3peuI0QTVPcn5QINEKHJ5uu8Cn yEXfQYNRfYJkqr6020v2s7U43Xc/sEfMBZQsy2v4= From: fdmanana@kernel.org To: linux-btrfs@vger.kernel.org Subject: [PATCH 2/2] Btrfs: report and handle error on unexpected first key on extent buffer Date: Mon, 18 Feb 2019 16:58:26 +0000 Message-Id: <20190218165826.23549-1-fdmanana@kernel.org> X-Mailer: git-send-email 2.11.0 Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Filipe Manana When there is a kind of corruption in an extent buffer such that its first key does not match the key at the respective parent slot, one of two things happens: 1) When assertions are enabled, we effectively hit a BUG_ON() which requires rebooting the machine later. This also does not tell any information about which extent buffer is affected, from which root, the expected and found keys, etc. 2) When assertions are disabled, we just ignore the mismatch and assume everything is ok, which can potentially lead to all sorts of unexpected problems later after a tree search (in the worst case, could lead to further silent corruption). So improve this by always checking if the first key of an extent buffer is what it's supposed to be, when doing a key search at key_search(), and report and return an appropriate error. The overhead is just comparing one key, which is minimal and is anyway just done in a special case where we skip the more expensive binary search (the binary search in the parent node returned 0, exact key match). Signed-off-by: Filipe Manana --- fs/btrfs/ctree.c | 38 +++++++++++++++++--------------------- 1 file changed, 17 insertions(+), 21 deletions(-) diff --git a/fs/btrfs/ctree.c b/fs/btrfs/ctree.c index 5b9f602fb9e2..a0bd0278208d 100644 --- a/fs/btrfs/ctree.c +++ b/fs/btrfs/ctree.c @@ -2529,35 +2529,31 @@ setup_nodes_for_search(struct btrfs_trans_handle *trans, return ret; } -static void key_search_validate(struct extent_buffer *b, - const struct btrfs_key *key, - int level) -{ -#ifdef CONFIG_BTRFS_ASSERT - struct btrfs_disk_key disk_key; - - btrfs_cpu_key_to_disk(&disk_key, key); - - if (level == 0) - ASSERT(!memcmp_extent_buffer(b, &disk_key, - offsetof(struct btrfs_leaf, items[0].key), - sizeof(disk_key))); - else - ASSERT(!memcmp_extent_buffer(b, &disk_key, - offsetof(struct btrfs_node, ptrs[0].key), - sizeof(disk_key))); -#endif -} - static int key_search(struct extent_buffer *b, const struct btrfs_key *key, int level, int *prev_cmp, int *slot) { + struct btrfs_key found_key; + if (*prev_cmp != 0) { *prev_cmp = btrfs_bin_search(b, key, level, slot); return *prev_cmp; } - key_search_validate(b, key, level); + if (level == 0) + btrfs_item_key_to_cpu(b, &found_key, 0); + else + btrfs_node_key_to_cpu(b, &found_key, 0); + + if (btrfs_comp_cpu_keys(&found_key, key) != 0) { + btrfs_crit(b->fs_info, +"unexpected first key for extent buffer: bytenr=%llu level=%d root=%llu expected key=(%llu %u %llu) found key=(%llu %u %llu)", + btrfs_header_bytenr(b), level, btrfs_header_owner(b), + key->objectid, key->type, key->offset, + found_key.objectid, found_key.type, + found_key.offset); + return -EUCLEAN; + } + *slot = 0; return 0;