From patchwork Thu Oct 17 06:25:29 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Gui Hecheng X-Patchwork-Id: 3058831 Return-Path: X-Original-To: patchwork-linux-btrfs@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 580829F243 for ; Thu, 17 Oct 2013 06:27:33 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 652BB2039F for ; Thu, 17 Oct 2013 06:27:32 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 9E0F0201BF for ; Thu, 17 Oct 2013 06:27:30 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751073Ab3JQG11 (ORCPT ); Thu, 17 Oct 2013 02:27:27 -0400 Received: from cn.fujitsu.com ([222.73.24.84]:30805 "EHLO song.cn.fujitsu.com" rhost-flags-OK-FAIL-OK-OK) by vger.kernel.org with ESMTP id S1750889Ab3JQG10 (ORCPT ); Thu, 17 Oct 2013 02:27:26 -0400 X-IronPort-AV: E=Sophos;i="4.93,512,1378828800"; d="scan'208";a="8781121" Received: from unknown (HELO tang.cn.fujitsu.com) ([10.167.250.3]) by song.cn.fujitsu.com with ESMTP; 17 Oct 2013 14:24:06 +0800 Received: from fnstmail02.fnst.cn.fujitsu.com (tang.cn.fujitsu.com [127.0.0.1]) by tang.cn.fujitsu.com (8.14.3/8.13.1) with ESMTP id r9H6RL7C004155; Thu, 17 Oct 2013 14:27:21 +0800 Received: from localhost.localdomain ([10.167.226.111]) by fnstmail02.fnst.cn.fujitsu.com (Lotus Domino Release 8.5.3) with ESMTP id 2013101714250141-2339815 ; Thu, 17 Oct 2013 14:25:01 +0800 From: Gui Hecheng To: linux-btrfs@vger.kernel.org Cc: jbacik@fusionio.com, Gui Hecheng Subject: [PATCH] Btrfs-progs: fix btrfsck improper prompt on dropping snapshots Date: Thu, 17 Oct 2013 14:25:29 +0800 Message-Id: <1381991129-2341-1-git-send-email-guihc.fnst@cn.fujitsu.com> X-Mailer: git-send-email 1.8.0.1 X-MIMETrack: Itemize by SMTP Server on mailserver/fnst(Release 8.5.3|September 15, 2011) at 2013/10/17 14:25:01, Serialize by Router on mailserver/fnst(Release 8.5.3|September 15, 2011) at 2013/10/17 14:25:03, Serialize complete at 2013/10/17 14:25:03 Sender: linux-btrfs-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-btrfs@vger.kernel.org X-Spam-Status: No, score=-7.3 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Exec btrfsck on btrfs with snapshots that are under a dropping progress will cause prompt on "ref mismatch". However we do not want this kind of prompt, since an remount operation will continue the dropping progress. Here the prompt is nonsense. Signed-off-by: Gui Hecheng --- cmds-check.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 91 insertions(+), 10 deletions(-) diff --git a/cmds-check.c b/cmds-check.c index 668af15..268cc64 100644 --- a/cmds-check.c +++ b/cmds-check.c @@ -119,6 +119,12 @@ struct inode_backref { char name[0]; }; +struct dropping_root_item_record { + struct list_head list; + struct btrfs_root_item ri; + struct btrfs_key found_key; +}; + #define REF_ERR_NO_DIR_ITEM (1 << 0) #define REF_ERR_NO_DIR_INDEX (1 << 1) #define REF_ERR_NO_INODE_REF (1 << 2) @@ -3600,6 +3606,21 @@ static int check_csums(struct btrfs_root *root) return errors; } +static int is_dropped_key(struct btrfs_key *key, + struct btrfs_key *drop_key) { + if (key->objectid < drop_key->objectid) + return 1; + else if (key->objectid == drop_key->objectid) { + if (key->type < drop_key->type) + return 1; + else if (key->type == drop_key->type) { + if (key->offset < drop_key->offset) + return 1; + } + } + return 0; +} + static int run_next_block(struct btrfs_root *root, struct block_info *bits, int bits_nr, @@ -3612,7 +3633,8 @@ static int run_next_block(struct btrfs_root *root, struct cache_tree *chunk_cache, struct rb_root *dev_cache, struct block_group_tree *block_group_cache, - struct device_extent_tree *dev_extent_cache) + struct device_extent_tree *dev_extent_cache, + struct btrfs_root_item *ri) { struct extent_buffer *buf; u64 bytenr; @@ -3817,6 +3839,15 @@ static int run_next_block(struct btrfs_root *root, ptr = btrfs_node_blockptr(buf, i); size = btrfs_level_size(root, level - 1); btrfs_node_key_to_cpu(buf, &key, i); + if (ri != NULL) { + struct btrfs_key drop_key; + btrfs_disk_key_to_cpu(&drop_key, + &ri->drop_progress); + if ((level == ri->drop_level) + && is_dropped_key(&key, &drop_key)) { + continue; + } + } ret = add_extent_rec(extent_cache, &key, ptr, size, 0, 0, 1, 0, 1, 0, size); @@ -5449,6 +5480,7 @@ static int check_chunks_and_extents(struct btrfs_root *root) struct btrfs_trans_handle *trans = NULL; int slot; struct btrfs_root_item ri; + struct list_head dropping_trees; dev_cache = RB_ROOT; cache_tree_init(&chunk_cache); @@ -5461,6 +5493,7 @@ static int check_chunks_and_extents(struct btrfs_root *root) cache_tree_init(&nodes); cache_tree_init(&reada); cache_tree_init(&corrupt_blocks); + INIT_LIST_HEAD(&dropping_trees); if (repair) { trans = btrfs_start_transaction(root, 1); @@ -5513,26 +5546,74 @@ again: offset = btrfs_item_ptr_offset(leaf, path.slots[0]); read_extent_buffer(leaf, &ri, offset, sizeof(ri)); - buf = read_tree_block(root->fs_info->tree_root, - btrfs_root_bytenr(&ri), - btrfs_level_size(root, - btrfs_root_level(&ri)), 0); - add_root_to_pending(buf, &extent_cache, &pending, - &seen, &nodes, &found_key); - free_extent_buffer(buf); + if (btrfs_disk_key_objectid(&ri.drop_progress) == 0) { + buf = read_tree_block(root->fs_info->tree_root, + btrfs_root_bytenr(&ri), + btrfs_level_size(root, + btrfs_root_level(&ri)), + 0); + add_root_to_pending(buf, &extent_cache, + &pending, &seen, &nodes, + &found_key); + free_extent_buffer(buf); + } else { + struct dropping_root_item_record *dri_rec; + dri_rec = malloc(sizeof(*dri_rec)); + if (!dri_rec) { + perror("malloc"); + exit(1); + } + memcpy(&dri_rec->ri, &ri, sizeof(ri)); + memcpy(&dri_rec->found_key, &found_key, + sizeof(found_key)); + list_add_tail(&dri_rec->list, &dropping_trees); + } } path.slots[0]++; } btrfs_release_path(&path); - while(1) { + while (1) { ret = run_next_block(root, bits, bits_nr, &last, &pending, &seen, &reada, &nodes, &extent_cache, &chunk_cache, &dev_cache, - &block_group_cache, &dev_extent_cache); + &block_group_cache, &dev_extent_cache, + NULL); if (ret != 0) break; } + while (!list_empty(&dropping_trees)) { + struct dropping_root_item_record *rec; + struct extent_buffer *buf; + rec = list_entry(dropping_trees.next, + struct dropping_root_item_record, list); + last = 0; + if (!bits) { + perror("realloc"); + exit(1); + } + buf = read_tree_block(root->fs_info->tree_root, + btrfs_root_bytenr(&rec->ri), + btrfs_level_size(root, + btrfs_root_level(&rec->ri)), 0); + add_root_to_pending(buf, &extent_cache, &pending, + &seen, &nodes, &rec->found_key); + while (1) { + ret = run_next_block(root, bits, bits_nr, &last, + &pending, &seen, &reada, + &nodes, &extent_cache, + &chunk_cache, &dev_cache, + &block_group_cache, + &dev_extent_cache, + &rec->ri); + if (ret != 0) + break; + } + free_extent_buffer(buf); + list_del(&rec->list); + free(rec); + } + ret = check_extent_refs(trans, root, &extent_cache); if (ret == -EAGAIN) { ret = btrfs_commit_transaction(trans, root);