linux-btrfs.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] Btrfs-progs: fix unresolved refs bug of btrfsck
@ 2012-06-21 12:17 Liu Bo
  0 siblings, 0 replies; only message in thread
From: Liu Bo @ 2012-06-21 12:17 UTC (permalink / raw)
  To: linux-btrfs

$ btrfs sub snap /mnt/ /mnt/s1
$ btrfs sub snap /mnt/ /mnt/s2
$ btrfsck disk

then we'll get several "unresolved ref" info, which is not expected.

The cause is that when we make a snapshot, we won't insert root ref/backref
for the snapshot, and btrfsck will report errors.

This is a btrfsck bug, since our metadata is all right, so we make such a rule:
When the src has the ref/backref on A, src's snapshot also has the ref/backref
on A.

Signed-off-by: Liu Bo <liubo2009@cn.fujitsu.com>
---
 btrfsck.c |   82 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 82 insertions(+), 0 deletions(-)

diff --git a/btrfsck.c b/btrfsck.c
index 7aac736..3a2b4ec 100644
--- a/btrfsck.c
+++ b/btrfsck.c
@@ -1439,6 +1439,76 @@ static int merge_root_recs(struct btrfs_root *root,
 	return 0;
 }
 
+/*
+ * 1: a snapshot,
+ * 0: not.
+ */
+static int check_snapshot(struct btrfs_root *root, u64 ref_root, u64 *root_ret)
+{
+	struct btrfs_root *tree_root = root->fs_info->tree_root;
+	struct btrfs_key key;
+	struct btrfs_path path;
+	struct extent_buffer *leaf;
+	int ret = 0;
+
+	*root_ret = 0;
+
+	btrfs_init_path(&path);
+
+	key.offset = 0;
+	key.objectid = ref_root;
+	key.type = BTRFS_ROOT_ITEM_KEY;
+	ret = btrfs_search_slot(NULL, tree_root, &key, &path, 0, 0);
+	BUG_ON(ret < 0);
+
+	leaf = path.nodes[0];
+	btrfs_item_key_to_cpu(leaf, &key, path.slots[0]);
+	if (key.type != BTRFS_ROOT_ITEM_KEY) {
+		ret = -ENOENT;
+		goto out;
+	}
+	if (key.offset == 0) {
+		ret = 0;
+		goto out;
+	}
+
+	/* key.offset is non-zero, a snapshot */
+	path.slots[0]++;
+	while (1) {
+		leaf = path.nodes[0];
+		if (path.slots[0] >= btrfs_header_nritems(leaf)) {
+			ret = btrfs_next_leaf(tree_root, &path);
+			if (ret != 0)
+				break;
+			leaf = path.nodes[0];
+		}
+		btrfs_item_key_to_cpu(leaf, &key, path.slots[0]);
+		if (key.type == BTRFS_ROOT_BACKREF_KEY) {
+			*root_ret = key.offset;
+			break;
+		}
+		path.slots[0]++;
+	}
+
+out:
+	btrfs_release_path(tree_root, &path);
+	return ret;
+}
+
+static void update_backref(struct root_record *rec, struct root_backref *ref,
+			u64 ref_root)
+{
+	struct root_backref *backref;
+
+	list_for_each_entry(backref, &rec->backrefs, list) {
+		if (backref->ref_root == ref_root) {
+			ref->found_back_ref = backref->found_back_ref;
+			ref->found_forward_ref = backref->found_forward_ref;
+			break;
+		}
+	}
+}
+
 static int check_root_refs(struct btrfs_root *root,
 			   struct cache_tree *root_cache)
 {
@@ -1511,6 +1581,18 @@ static int check_root_refs(struct btrfs_root *root,
 				backref->errors |= REF_ERR_NO_DIR_ITEM;
 			if (!backref->found_dir_index)
 				backref->errors |= REF_ERR_NO_DIR_INDEX;
+			if (!backref->found_back_ref &&
+			    !backref->found_forward_ref) {
+				u64 ref_root_objectid = 0;
+				int is_snap = 0;
+
+				is_snap = check_snapshot(root,
+							 backref->ref_root,
+							 &ref_root_objectid);
+				if (is_snap && ref_root_objectid)
+					update_backref(rec, backref,
+						       ref_root_objectid);
+			}
 			if (!backref->found_back_ref)
 				backref->errors |= REF_ERR_NO_ROOT_BACKREF;
 			if (!backref->found_forward_ref)
-- 
1.6.5.2


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2012-06-21 12:09 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-06-21 12:17 [PATCH] Btrfs-progs: fix unresolved refs bug of btrfsck Liu Bo

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).