From patchwork Thu Oct 13 11:09:49 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: ethanwu X-Patchwork-Id: 9374833 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id F069960487 for ; Thu, 13 Oct 2016 11:27:32 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id E221529FDE for ; Thu, 13 Oct 2016 11:27:32 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id D746129FE1; Thu, 13 Oct 2016 11:27:32 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID 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 6262529FDE for ; Thu, 13 Oct 2016 11:27:32 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754618AbcJML11 (ORCPT ); Thu, 13 Oct 2016 07:27:27 -0400 Received: from synology.com ([59.124.61.242]:48530 "EHLO synology.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753901AbcJML1X (ORCPT ); Thu, 13 Oct 2016 07:27:23 -0400 X-Greylist: delayed 1033 seconds by postgrey-1.27 at vger.kernel.org; Thu, 13 Oct 2016 07:27:23 EDT Received: from localhost.localdomain (unknown [10.12.12.49]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-SHA256 (128/128 bits)) (No client certificate requested) (Authenticated sender: ethanwu@synology.com) by synology.com (Postfix) with ESMTPSA id A6F2BF7746B4; Thu, 13 Oct 2016 19:10:13 +0800 (CST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=synology.com; s=123; t=1476357013; bh=E5bOivzgXvCcts4e37Yg6MbvsL2cIsHW9SZ+9Mvnj2o=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=GD7gOwvWaxDdvjYNdZBQfmCZGpqf3tFg0AIE/Fc212Vqss4jBwWYYHL9CBct8L1v3 PUIEXCMgZckCRZ/Rkt1ffH9y9lA2R66n2hUHIdt+sdnBBYPN1tVuXGhRrMElZlOyz9 i+YBXj/zF8u/2pLwqwKXixZairZdNzCZbldc80Ps= From: ethanwu To: linux-btrfs@vger.kernel.org Cc: ethanwu Subject: [PATCH 2/2] btrfs-progs: check: add drop key to relocation tree Date: Thu, 13 Oct 2016 19:09:49 +0800 Message-Id: <1476356989-23131-3-git-send-email-ethanwu@synology.com> X-Mailer: git-send-email 1.9.1 In-Reply-To: <1476356989-23131-1-git-send-email-ethanwu@synology.com> References: <1476356989-23131-1-git-send-email-ethanwu@synology.com> X-MailScanner-ID: A6F2BF7746B4.AE73D X-MailScanner: Found to be clean X-MailScanner-MCPCheck: MCP-Clean, MCP-Checker (score=0, required 80) X-MailScanner-SpamCheck: not spam (whitelisted), SpamAssassin (not cached, score=-0.891, required 4.5, ALL_TRUSTED -1.00, BAYES_40 -0.00, DKIM_SIGNED 0.10, T_DKIM_INVALID 0.01) X-MailScanner-From: ethanwu@synology.com Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP If subvolume is deleted, we add drop_key into the corresponding root item, so we know where to start processing the deleted subvolume. However, we don't skip the keys prior to the drop_key in corresponding relocation tree of the deleted subvolume. As a result, we might run into block that is freed and being used again. This cause btrfs check to report false alarm. Fix this by adding drop_key for deleted subvolume to its corresponding relocation tree. Signed-off-by: ethanwu --- cmds-check.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 51 insertions(+), 1 deletion(-) diff --git a/cmds-check.c b/cmds-check.c index bf6398d..4d7cb68 100644 --- a/cmds-check.c +++ b/cmds-check.c @@ -92,6 +92,13 @@ struct extent_backref { unsigned int broken:1; }; +static int add_root_item_to_list(struct list_head *head, + u64 objectid, u64 bytenr, u64 last_snapshot, + u8 level, u8 drop_level, + int level_size, struct btrfs_key *drop_key); + +static void free_root_item_list(struct list_head *list); + static inline struct extent_backref* to_extent_backref(struct list_head *entry) { return list_entry(entry, struct extent_backref, list); @@ -3761,6 +3768,10 @@ static int check_fs_roots(struct btrfs_root *root, struct btrfs_root *tree_root = root->fs_info->tree_root; int ret; int err = 0; + struct list_head dropping_trees; + struct btrfs_disk_key *drop_progress; + + INIT_LIST_HEAD(&dropping_trees); if (ctx.progress_enabled) { ctx.tp = TASK_FS_ROOTS; @@ -3818,6 +3829,32 @@ again: err = 1; goto next; } + + drop_progress = &tmp_root->root_item.drop_progress; + if (btrfs_disk_key_objectid(drop_progress) != 0) { + struct btrfs_key drop_key; + + btrfs_disk_key_to_cpu(&drop_key, drop_progress); + ret = add_root_item_to_list(&dropping_trees, + tmp_root->root_key.objectid, + 0, 0, 0, tmp_root->root_item.drop_level, + 0, &drop_key); + if (ret < 0) { + err = 1; + goto out; + } + } else if (key.objectid == BTRFS_TREE_RELOC_OBJECTID) { + struct root_item_record *ri_rec; + + list_for_each_entry(ri_rec, &dropping_trees, list) { + if (ri_rec->objectid == key.offset) { + btrfs_cpu_key_to_disk(drop_progress, &ri_rec->drop_key); + tmp_root->root_item.drop_level = ri_rec->drop_level; + break; + } + } + } + ret = check_fs_root(tmp_root, root_cache, &wc); if (ret == -EAGAIN) { free_root_recs_tree(root_cache); @@ -3837,6 +3874,7 @@ next: path.slots[0]++; } out: + free_root_item_list(&dropping_trees); btrfs_release_path(&path); if (err) free_extent_cache_tree(&wc.shared); @@ -8536,6 +8574,9 @@ again: if (found_key.type == BTRFS_ROOT_ITEM_KEY) { unsigned long offset; u64 last_snapshot; + struct root_item_record *ri_rec; + struct btrfs_key drop_key = {0}; + u8 drop_level = 0; offset = btrfs_item_ptr_offset(leaf, path.slots[0]); read_extent_buffer(leaf, &ri, offset, sizeof(ri)); @@ -8543,11 +8584,20 @@ again: if (btrfs_disk_key_objectid(&ri.drop_progress) == 0) { level = btrfs_root_level(&ri); level_size = root->nodesize; + if (found_key.objectid == BTRFS_TREE_RELOC_OBJECTID) { + list_for_each_entry(ri_rec, &dropping_trees, list) { + if (ri_rec->objectid == found_key.offset) { + drop_key = ri_rec->drop_key; + drop_level = ri_rec->drop_level; + break; + } + } + } ret = add_root_item_to_list(&normal_trees, found_key.objectid, btrfs_root_bytenr(&ri), last_snapshot, level, - 0, level_size, NULL); + drop_level, level_size, &drop_key); if (ret < 0) goto out; } else {