All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 1/5] btrfs-progs: Record orphan data extent ref to corresponding root.
@ 2015-01-02  7:12 Qu Wenruo
  2015-01-02  7:12 ` [PATCH v2 2/5] btrfs-progs: Add btrfs_get_extent() and btrfs_punch_hole() Qu Wenruo
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: Qu Wenruo @ 2015-01-02  7:12 UTC (permalink / raw)
  To: linux-btrfs

Before this patch, when a extent's data ref points to a invalid key in
fs tree, this happens if a leaf/node of fs tree is corrupted, btrfsck
can't do any repair and just exit.

In fact, such problem can be handled in fs tree repair routines, rebuild
the inode item(if missing) and add back the extent data (with some
assumption).

So this patch records such data extent refs for later fs tree recovery
routine.

TODO:
    Restore orphan data extent refs into btrfs_root is not the best
    method. It's best to directly restore it into inode_record, however
    current extent tree and fs tree can't cooperate together, so use
    btrfs_root as a temporary storage until inode_cache is built.

Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
---
Changelog:
v2:
   Do not record file extent if the file extent pointed by the data
   backref exists but only bytenr mismatch.
   This fix a regression bug causing fsck-test 001 fail.
---
 cmds-check.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---
 ctree.h      |  10 ++++
 disk-io.c    |   1 +
 3 files changed, 158 insertions(+), 8 deletions(-)

diff --git a/cmds-check.c b/cmds-check.c
index d2d218a..20a6ac2 100644
--- a/cmds-check.c
+++ b/cmds-check.c
@@ -83,6 +83,20 @@ struct data_backref {
 	u32 found_ref;
 };
 
+/*
+ * Much like data_backref, just removed the undetermined members
+ * and change it to use list_head.
+ * Stored in the root->orphan_data_extents list
+ */
+struct orphan_data_extent {
+	struct list_head list;
+	u64 root;
+	u64 objectid;
+	u64 offset;
+	u64 disk_bytenr;
+	u64 disk_len;
+};
+
 struct tree_backref {
 	struct extent_backref node;
 	union {
@@ -2901,6 +2915,34 @@ out_free_path:
 	return ret;
 }
 
+static void print_orphan_data_extents(struct list_head *orphan_extents,
+				      u64 objectid)
+{
+	struct orphan_data_extent *orphan;
+
+	if (list_empty(orphan_extents))
+		return;
+	printf("The following data extent is lost in tree %llu:\n",
+	       objectid);
+	list_for_each_entry(orphan, orphan_extents, list) {
+		printf("\tinode: %llu, offset:%llu, disk_bytenr: %llu, disk_len: %llu\n",
+		       orphan->objectid, orphan->offset, orphan->disk_bytenr,
+		       orphan->disk_len);
+	}
+}
+
+static void free_orphan_data_extents(struct list_head *orphan_extents)
+{
+	struct orphan_data_extent *orphan;
+
+	while (!list_empty(orphan_extents)) {
+		orphan = list_entry(orphan_extents->next,
+				    struct orphan_data_extent, list);
+		list_del(&orphan->list);
+		free(orphan);
+	}
+}
+
 static int check_fs_root(struct btrfs_root *root,
 			 struct cache_tree *root_cache,
 			 struct walk_control *wc)
@@ -3032,6 +3074,8 @@ skip_walking:
 
 	free_corrupt_blocks_tree(&corrupt_blocks);
 	root->fs_info->corrupt_blocks = NULL;
+	print_orphan_data_extents(&root->orphan_data_extents, root->objectid);
+	free_orphan_data_extents(&root->orphan_data_extents);
 	return ret;
 }
 
@@ -6544,6 +6588,88 @@ static int find_possible_backrefs(struct btrfs_trans_handle *trans,
 }
 
 /*
+ * Record orphan data ref into corresponding root.
+ *
+ * Return 0 if the extent item contains data ref and recorded.
+ * Return 1 if the extent item contains no useful data ref
+ *   On that case, it may contains only shared_dataref or metadata backref
+ *   or the file extent exists(this should be handled by the extent bytenr
+ *   recovery routine)
+ * Return <0 if something goes wrong.
+ */
+static int record_orphan_data_extents(struct btrfs_fs_info *fs_info,
+				      struct extent_record *rec)
+{
+	struct btrfs_key key;
+	struct btrfs_root *dest_root;
+	struct extent_backref *back;
+	struct data_backref *dback;
+	struct orphan_data_extent *orphan;
+	struct btrfs_path *path;
+	int recorded_data_ref = 0;
+	int ret = 0;
+
+	if (rec->metadata)
+		return 1;
+	path = btrfs_alloc_path();
+	if (!path)
+		return -ENOMEM;
+	list_for_each_entry(back, &rec->backrefs, list) {
+		if (back->full_backref || !back->is_data ||
+		    !back->found_extent_tree)
+			continue;
+		dback = (struct data_backref *)back;
+		if (dback->found_ref)
+			continue;
+		key.objectid = dback->root;
+		key.type = BTRFS_ROOT_ITEM_KEY;
+		key.offset = (u64)-1;
+
+		dest_root = btrfs_read_fs_root(fs_info, &key);
+
+		/* For non-exist root we just skip it */
+		if (IS_ERR(dest_root) || !dest_root)
+			continue;
+
+		key.objectid = dback->owner;
+		key.type = BTRFS_EXTENT_DATA_KEY;
+		key.offset = dback->offset;
+
+		ret = btrfs_search_slot(NULL, dest_root, &key, path, 0, 0);
+		/*
+		 * For ret < 0, it's OK since the fs-tree may be corrupted,
+		 * we need to record it for inode/file extent rebuild.
+		 * For ret > 0, we record it only for file extent rebuild.
+		 * For ret == 0, the file extent exists but only bytenr
+		 * mismatch, let the original bytenr fix routine to handle,
+		 * don't record it.
+		 */
+		if (ret == 0)
+			continue;
+		ret = 0;
+		orphan = malloc(sizeof(*orphan));
+		if (!orphan) {
+			ret = -ENOMEM;
+			goto out;
+		}
+		INIT_LIST_HEAD(&orphan->list);
+		orphan->root = dback->root;
+		orphan->objectid = dback->owner;
+		orphan->offset = dback->offset;
+		orphan->disk_bytenr = rec->cache.start;
+		orphan->disk_len = rec->cache.size;
+		list_add(&dest_root->orphan_data_extents, &orphan->list);
+		recorded_data_ref = 1;
+	}
+out:
+	btrfs_free_path(path);
+	if (!ret)
+		return !recorded_data_ref;
+	else
+		return ret;
+}
+
+/*
  * when an incorrect extent item is found, this will delete
  * all of the existing entries for it and recreate them
  * based on what the tree scan found.
@@ -6760,6 +6886,7 @@ static int check_extent_refs(struct btrfs_trans_handle *trans,
 	int ret = 0;
 	int fixed = 0;
 	int had_dups = 0;
+	int recorded = 0;
 
 	if (repair) {
 		/*
@@ -6823,6 +6950,7 @@ static int check_extent_refs(struct btrfs_trans_handle *trans,
 
 	while(1) {
 		fixed = 0;
+		recorded = 0;
 		cache = search_cache_extent(extent_cache, 0);
 		if (!cache)
 			break;
@@ -6840,12 +6968,24 @@ static int check_extent_refs(struct btrfs_trans_handle *trans,
 			fprintf(stderr, "extent item %llu, found %llu\n",
 				(unsigned long long)rec->extent_item_refs,
 				(unsigned long long)rec->refs);
-			if (!fixed && repair) {
-				ret = fixup_extent_refs(trans, root->fs_info,
+			ret = record_orphan_data_extents(root->fs_info, rec);
+			if (ret < 0)
+				goto repair_abort;
+			if (ret == 0) {
+				recorded = 1;
+			} else {
+				/*
+				 * we can't use the extent to repair file
+				 * extent, let the fallback method handle it.
+				 */
+				if (!fixed && repair) {
+					ret = fixup_extent_refs(trans,
+							root->fs_info,
 							extent_cache, rec);
-				if (ret)
-					goto repair_abort;
-				fixed = 1;
+					if (ret)
+						goto repair_abort;
+					fixed = 1;
+				}
 			}
 			err = 1;
 
@@ -6855,21 +6995,20 @@ static int check_extent_refs(struct btrfs_trans_handle *trans,
 				(unsigned long long)rec->start,
 				(unsigned long long)rec->nr);
 
-			if (!fixed && repair) {
+			if (!fixed && !recorded && repair) {
 				ret = fixup_extent_refs(trans, root->fs_info,
 							extent_cache, rec);
 				if (ret)
 					goto repair_abort;
 				fixed = 1;
 			}
-
 			err = 1;
 		}
 		if (!rec->owner_ref_checked) {
 			fprintf(stderr, "owner ref check failed [%llu %llu]\n",
 				(unsigned long long)rec->start,
 				(unsigned long long)rec->nr);
-			if (!fixed && repair) {
+			if (!fixed && !recorded && repair) {
 				ret = fixup_extent_refs(trans, root->fs_info,
 							extent_cache, rec);
 				if (ret)
diff --git a/ctree.h b/ctree.h
index 7861940..0963fc0 100644
--- a/ctree.h
+++ b/ctree.h
@@ -1039,6 +1039,16 @@ struct btrfs_root {
 	u64 highest_inode;
 	u64 last_inode_alloc;
 
+	/*
+	 * Record orphan data extent ref
+	 *
+	 * TODO: Don't restore things in btrfs_root.
+	 * Directly record it into inode_record, which needs a lot of
+	 * infrastructure change to allow cooperation between extent
+	 * and fs tree scan.
+	 */
+	struct list_head orphan_data_extents;
+
 	/* the dirty list is only used by non-reference counted roots */
 	struct list_head dirty_list;
 	struct rb_node rb_node;
diff --git a/disk-io.c b/disk-io.c
index 2bf8586..521e1bd 100644
--- a/disk-io.c
+++ b/disk-io.c
@@ -377,6 +377,7 @@ int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
 	root->last_inode_alloc = 0;
 
 	INIT_LIST_HEAD(&root->dirty_list);
+	INIT_LIST_HEAD(&root->orphan_data_extents);
 	memset(&root->root_key, 0, sizeof(root->root_key));
 	memset(&root->root_item, 0, sizeof(root->root_item));
 	root->root_key.objectid = objectid;
-- 
2.2.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v2 2/5] btrfs-progs: Add btrfs_get_extent() and btrfs_punch_hole().
  2015-01-02  7:12 [PATCH v2 1/5] btrfs-progs: Record orphan data extent ref to corresponding root Qu Wenruo
@ 2015-01-02  7:12 ` Qu Wenruo
  2015-01-02  7:12 ` [PATCH v2 3/5] btrfs-progs: Record and report every file extent hole Qu Wenruo
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: Qu Wenruo @ 2015-01-02  7:12 UTC (permalink / raw)
  To: linux-btrfs

Add btrfs_get_extent() and btrfs_punch_hole() for btrfs-progs.

Btrfs_get_extent() will act much like kernel one, return the first
extent that covers the given range.
The difference will be that progs btrfs_get_extent() can't handle
no-holes feature, which means caller should handle it carefully.

Btrfs_punch_hole() will punch a hole in given range of given inode,
however it differs from kernel one since it won't zero any page or drop
any extents if there is any extent in the hole range.

These functions are mainly used for later I_ERR_FILE_EXTENT_DISCOUNT
repair function.

Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
---
Changelog:
v2:
   None
---
 Makefile |   2 +-
 ctree.h  |   9 ++++
 file.c   | 162 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 172 insertions(+), 1 deletion(-)
 create mode 100644 file.c

diff --git a/Makefile b/Makefile
index 8b843bb..e14959e 100644
--- a/Makefile
+++ b/Makefile
@@ -12,7 +12,7 @@ objects = ctree.o disk-io.o radix-tree.o extent-tree.o print-tree.o \
 	  extent-cache.o extent_io.o volumes.o utils.o repair.o \
 	  qgroup.o raid6.o free-space-cache.o list_sort.o props.o \
 	  ulist.o qgroup-verify.o backref.o string-table.o task-utils.o \
-	  inode.o
+	  inode.o file.o
 cmds_objects = cmds-subvolume.o cmds-filesystem.o cmds-device.o cmds-scrub.o \
 	       cmds-inspect.o cmds-balance.o cmds-send.o cmds-receive.o \
 	       cmds-quota.o cmds-qgroup.o cmds-replace.o cmds-check.o \
diff --git a/ctree.h b/ctree.h
index 0963fc0..5dbc767 100644
--- a/ctree.h
+++ b/ctree.h
@@ -2468,4 +2468,13 @@ int btrfs_add_orphan_item(struct btrfs_trans_handle *trans,
 			  u64 ino);
 int btrfs_mkdir(struct btrfs_trans_handle *trans, struct btrfs_root *root,
 		char *name, int namelen, u64 parent_ino, u64 *ino, int mode);
+
+/* file.c */
+int btrfs_get_extent(struct btrfs_trans_handle *trans,
+		     struct btrfs_root *root,
+		     struct btrfs_path *path,
+		     u64 ino, u64 offset, u64 len, int ins_len);
+int btrfs_punch_hole(struct btrfs_trans_handle *trans,
+		     struct btrfs_root *root,
+		     u64 ino, u64 offset, u64 len);
 #endif
diff --git a/file.c b/file.c
new file mode 100644
index 0000000..0e9253e
--- /dev/null
+++ b/file.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2014 Fujitsu.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License v2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public
+ * License along with this program; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ */
+
+#include <sys/stat.h>
+#include "ctree.h"
+#include "transaction.h"
+#include "kerncompat.h"
+
+/*
+ * Get the first file extent that covers (part of) the given range
+ * Unlike kernel using extent_map to handle hole even no-hole is enabled,
+ * progs don't have such infrastructure, so caller should do extra care
+ * for no-hole.
+ *
+ * return 0 for found, and path points to the file extent.
+ * return >0 for not found, and path points to the insert position.
+ * return <0 for error.
+ */
+int btrfs_get_extent(struct btrfs_trans_handle *trans,
+		     struct btrfs_root *root,
+		     struct btrfs_path *path,
+		     u64 ino, u64 offset, u64 len, int ins_len)
+{
+	struct btrfs_key key;
+	struct btrfs_key found_key;
+	struct btrfs_file_extent_item *fi_item;
+	u64 end = 0;
+	int ret = 0;
+	int not_found = 1;
+
+	key.objectid = ino;
+	key.type = BTRFS_EXTENT_DATA_KEY;
+	key.offset = offset;
+
+	ret = btrfs_search_slot(trans, root, &key, path, ins_len,
+				ins_len ? 1 : 0);
+	if (ret <= 0)
+		goto out;
+	if (ret > 0) {
+		/* Check preivous file extent */
+		ret = btrfs_previous_item(root, path, ino,
+					  BTRFS_EXTENT_DATA_KEY);
+		if (ret < 0)
+			goto out;
+		if (ret > 0)
+			goto check_next;
+	}
+	btrfs_item_key_to_cpu(path->nodes[0], &found_key, path->slots[0]);
+	if (found_key.objectid != ino ||
+	    found_key.type != BTRFS_EXTENT_DATA_KEY)
+		goto check_next;
+
+	fi_item = btrfs_item_ptr(path->nodes[0], path->slots[0],
+				 struct btrfs_file_extent_item);
+	end = found_key.offset +
+	      btrfs_file_extent_ram_bytes(path->nodes[0], fi_item);
+	/*
+	 * existing file extent
+	 * |--------|	  |----|
+	 *      |-------|
+	 *      offset + len
+	 * OR
+	 * |---------------|
+	 *	|-------|
+	 */
+	if (end > offset) {
+		not_found = 0;
+		goto out;
+	}
+check_next:
+	ret = btrfs_next_item(root, path);
+	if (ret)
+		goto out;
+
+	btrfs_item_key_to_cpu(path->nodes[0], &found_key, path->slots[0]);
+	if (found_key.objectid != ino ||
+	    found_key.type != BTRFS_EXTENT_DATA_KEY) {
+		ret = 1;
+		goto out;
+	}
+	if (found_key.offset < offset + len)
+		/*
+		 * existing file extent
+		 * |---|	|------|
+		 *	|-------|
+		 *	offset + len
+		 */
+		not_found = 0;
+	else
+		/*
+		 * existing file extent
+		 * |----|		|----|
+		 *		|----|
+		 *		offset + len
+		 */
+		not_found = 1;
+
+	/*
+	 * To keep the search hehavior consistent with search_slot(),
+	 * we need to go back to the prev leaf's nritem slot if
+	 * we are at the first slot of the leaf.
+	 */
+	if (path->slots[0] == 0) {
+		ret = btrfs_prev_leaf(root, path);
+		/* Not possible */
+		if (ret)
+			goto out;
+		path->slots[0] = btrfs_header_nritems(path->nodes[0]);
+	}
+
+out:
+	if (ret == 0)
+		ret = not_found;
+	return ret;
+}
+
+/*
+ * Punch hole ranged [offset,len) for the file given by ino and root.
+ *
+ * Unlink kernel punch_hole, which will not zero/free existing extent,
+ * instead it will return -EEXIST if there is any extents in the hole
+ * range.
+ */
+int btrfs_punch_hole(struct btrfs_trans_handle *trans,
+		     struct btrfs_root *root,
+		     u64 ino, u64 offset, u64 len)
+{
+	struct btrfs_path *path;
+	int ret = 0;
+
+	path = btrfs_alloc_path();
+	if (!path)
+		return -ENOMEM;
+
+	ret = btrfs_get_extent(NULL, root, path, ino, offset, len, 0);
+	if (ret < 0)
+		goto out;
+	if (ret == 0) {
+		ret = -EEXIST;
+		goto out;
+	}
+
+	ret = btrfs_insert_file_extent(trans, root, ino, offset, 0, 0, len);
+out:
+	btrfs_free_path(path);
+	return ret;
+}
-- 
2.2.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v2 3/5] btrfs-progs: Record and report every file extent hole.
  2015-01-02  7:12 [PATCH v2 1/5] btrfs-progs: Record orphan data extent ref to corresponding root Qu Wenruo
  2015-01-02  7:12 ` [PATCH v2 2/5] btrfs-progs: Add btrfs_get_extent() and btrfs_punch_hole() Qu Wenruo
@ 2015-01-02  7:12 ` Qu Wenruo
  2015-03-25  3:05   ` Eric Sandeen
  2015-01-02  7:12 ` [PATCH v2 4/5] btrfs-progs: Add repair and report function for orphan file extent Qu Wenruo
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 10+ messages in thread
From: Qu Wenruo @ 2015-01-02  7:12 UTC (permalink / raw)
  To: linux-btrfs

Record every file extent discontinuous hole in inode_record using a
rb_tree member.

Before the patch, btrfsck will only record the first file extent hole by
using first_extent_gap, that's good for detecting error, but not
suitable for fixing it.

This patch provides the ability to record every file extent hole and
report it.

Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
---
Changelog:
v2:
   None
---
 cmds-check.c | 244 +++++++++++++++++++++++++++++++++++++++++++++++++++++++----
 1 file changed, 231 insertions(+), 13 deletions(-)

diff --git a/cmds-check.c b/cmds-check.c
index 20a6ac2..76216c5 100644
--- a/cmds-check.c
+++ b/cmds-check.c
@@ -167,6 +167,202 @@ struct root_item_record {
 #define REF_ERR_DUP_ROOT_REF		(1 << 11)
 #define REF_ERR_DUP_ROOT_BACKREF	(1 << 12)
 
+struct file_extent_hole {
+	struct rb_node node;
+	u64 start;
+	u64 len;
+};
+
+/* Compatible function to allow reuse of old codes */
+static u64 first_extent_gap(struct rb_root *holes)
+{
+	struct file_extent_hole *hole;
+
+	if (RB_EMPTY_ROOT(holes))
+		return (u64)-1;
+
+	hole = rb_entry(rb_first(holes), struct file_extent_hole, node);
+	return hole->start;
+}
+
+int compare_hole(struct rb_node *node1, struct rb_node *node2)
+{
+	struct file_extent_hole *hole1;
+	struct file_extent_hole *hole2;
+
+	hole1 = rb_entry(node1, struct file_extent_hole, node);
+	hole2 = rb_entry(node2, struct file_extent_hole, node);
+
+	if (hole1->start > hole2->start)
+		return -1;
+	if (hole1->start < hole2->start)
+		return 1;
+	/* Now hole1->start == hole2->start */
+	if (hole1->len >= hole2->len)
+		/*
+		 * Hole 1 will be merge center
+		 * Same hole will be merged later
+		 */
+		return -1;
+	/* Hole 2 will be merge center */
+	return 1;
+}
+
+/*
+ * Add a hole to the record
+ *
+ * This will do hole merge for copy_file_extent_holes(),
+ * which will ensure there won't be continuous holes.
+ */
+static int add_file_extent_hole(struct rb_root *holes,
+				u64 start, u64 len)
+{
+	struct file_extent_hole *hole;
+	struct file_extent_hole *prev = NULL;
+	struct file_extent_hole *next = NULL;
+
+	hole = malloc(sizeof(*hole));
+	if (!hole)
+		return -ENOMEM;
+	hole->start = start;
+	hole->len = len;
+	/* Since compare will not return 0, no -EEXIST will happen */
+	rb_insert(holes, &hole->node, compare_hole);
+
+	/* simple merge with previous hole */
+	if (rb_prev(&hole->node))
+		prev = rb_entry(rb_prev(&hole->node), struct file_extent_hole,
+				node);
+	if (prev && prev->start + prev->len >= hole->start) {
+		hole->len = hole->start + hole->len - prev->start;
+		hole->start = prev->start;
+		rb_erase(&prev->node, holes);
+		free(prev);
+		prev = NULL;
+	}
+
+	/* iterate merge with next holes */
+	while (1) {
+		if (!rb_next(&hole->node))
+			break;
+		next = rb_entry(rb_next(&hole->node), struct file_extent_hole,
+					node);
+		if (hole->start + hole->len >= next->start) {
+			if (hole->start + hole->len <= next->start + next->len)
+				hole->len = next->start + next->len -
+					    hole->start;
+			rb_erase(&next->node, holes);
+			free(next);
+			next = NULL;
+		} else
+			break;
+	}
+	return 0;
+}
+
+static int compare_hole_range(struct rb_node *node, void *data)
+{
+	struct file_extent_hole *hole;
+	u64 start;
+
+	hole = (struct file_extent_hole *)data;
+	start = hole->start;
+
+	hole = rb_entry(node, struct file_extent_hole, node);
+	if (start < hole->start)
+		return -1;
+	if (start >= hole->start && start < hole->start + hole->len)
+		return 0;
+	return 1;
+}
+
+/*
+ * Delete a hole in the record
+ *
+ * This will do the hole split and is much restrict than add.
+ */
+static int del_file_extent_hole(struct rb_root *holes,
+				u64 start, u64 len)
+{
+	struct file_extent_hole *hole;
+	struct file_extent_hole tmp;
+	struct file_extent_hole prev;
+	struct file_extent_hole next;
+	struct rb_node *node;
+	int have_prev = 0;
+	int have_next = 0;
+	int ret = 0;
+
+	tmp.start = start;
+	tmp.len = len;
+	node = rb_search(holes, &tmp, compare_hole_range, NULL);
+	if (!node)
+		return -EEXIST;
+	hole = rb_entry(node, struct file_extent_hole, node);
+	if (start + len > hole->start + hole->len)
+		return -EEXIST;
+
+	/*
+	 * Now there will be no overflap, delete the hole and re-add the
+	 * split(s) if they exists.
+	 */
+	if (start > hole->start) {
+		prev.start = hole->start;
+		prev.len = start - hole->start;
+		have_prev = 1;
+	}
+	if (hole->start + hole->len > start + len) {
+		next.start = start + len;
+		next.len = hole->start + hole->len - start - len;
+		have_next = 1;
+	}
+	rb_erase(node, holes);
+	free(hole);
+	if (have_prev) {
+		ret = add_file_extent_hole(holes, prev.start, prev.len);
+		if (ret < 0)
+			return ret;
+	}
+	if (have_next) {
+		ret = add_file_extent_hole(holes, next.start, next.len);
+		if (ret < 0)
+			return ret;
+	}
+	return 0;
+}
+
+static int copy_file_extent_holes(struct rb_root *dst,
+				  struct rb_root *src)
+{
+	struct file_extent_hole *hole;
+	struct rb_node *node;
+	int ret = 0;
+
+	node = rb_first(src);
+	while (node) {
+		hole = rb_entry(node, struct file_extent_hole, node);
+		ret = add_file_extent_hole(dst, hole->start, hole->len);
+		if (ret)
+			break;
+		node = rb_next(node);
+	}
+	return ret;
+}
+
+static void free_file_extent_holes(struct rb_root *holes)
+{
+	struct rb_node *node;
+	struct file_extent_hole *hole;
+
+	node = rb_first(holes);
+	while (node) {
+		hole = rb_entry(node, struct file_extent_hole, node);
+		rb_erase(node, holes);
+		free(hole);
+		node = rb_first(holes);
+	}
+}
+
 struct inode_record {
 	struct list_head backrefs;
 	unsigned int checked:1;
@@ -189,7 +385,7 @@ struct inode_record {
 	u64 found_size;
 	u64 extent_start;
 	u64 extent_end;
-	u64 first_extent_gap;
+	struct rb_root holes;
 
 	u32 refs;
 };
@@ -374,6 +570,20 @@ static void print_inode_error(struct btrfs_root *root, struct inode_record *rec)
 	if (errors & I_ERR_LINK_COUNT_WRONG)
 		fprintf(stderr, ", link count wrong");
 	fprintf(stderr, "\n");
+	/* Print the holes if needed */
+	if (errors & I_ERR_FILE_EXTENT_DISCOUNT) {
+		struct file_extent_hole *hole;
+		struct rb_node *node;
+
+		node = rb_first(&rec->holes);
+		fprintf(stderr, "Found file extent holes:\n");
+		while (node) {
+			hole = rb_entry(node, struct file_extent_hole, node);
+			fprintf(stderr, "\tstart: %llu, len:%llu\n",
+				hole->start, hole->len);
+			node = rb_next(node);
+		}
+	}
 }
 
 static void print_ref_error(int errors)
@@ -428,9 +638,9 @@ static struct inode_record *get_inode_rec(struct cache_tree *inode_cache,
 		rec = calloc(1, sizeof(*rec));
 		rec->ino = ino;
 		rec->extent_start = (u64)-1;
-		rec->first_extent_gap = (u64)-1;
 		rec->refs = 1;
 		INIT_LIST_HEAD(&rec->backrefs);
+		rec->holes = RB_ROOT;
 
 		node = malloc(sizeof(*node));
 		node->cache.start = ino;
@@ -459,6 +669,7 @@ static void free_inode_rec(struct inode_record *rec)
 		list_del(&backref->list);
 		free(backref);
 	}
+	free_file_extent_holes(&rec->holes);
 	free(rec);
 }
 
@@ -506,11 +717,9 @@ static void maybe_free_inode_rec(struct cache_tree *inode_cache,
 			rec->errors |= I_ERR_ODD_DIR_ITEM;
 		if (rec->found_size != rec->nbytes)
 			rec->errors |= I_ERR_FILE_NBYTES_WRONG;
-		if (rec->extent_start == (u64)-1 || rec->extent_start > 0)
-			rec->first_extent_gap = 0;
 		if (rec->nlink > 0 && !no_holes &&
 		    (rec->extent_end < rec->isize ||
-		     rec->first_extent_gap < rec->isize))
+		     first_extent_gap(&rec->holes) < rec->isize))
 			rec->errors |= I_ERR_FILE_EXTENT_DISCOUNT;
 	}
 
@@ -659,6 +868,7 @@ static int merge_inode_recs(struct inode_record *src, struct inode_record *dst,
 {
 	struct inode_backref *backref;
 	u32 dir_count = 0;
+	int ret = 0;
 
 	dst->merging = 1;
 	list_for_each_entry(backref, &src->backrefs, list) {
@@ -691,8 +901,11 @@ static int merge_inode_recs(struct inode_record *src, struct inode_record *dst,
 		dst->found_csum_item = 1;
 	if (src->some_csum_missing)
 		dst->some_csum_missing = 1;
-	if (dst->first_extent_gap > src->first_extent_gap)
-		dst->first_extent_gap = src->first_extent_gap;
+	if (first_extent_gap(&dst->holes) > first_extent_gap(&src->holes)) {
+		ret = copy_file_extent_holes(&dst->holes, &src->holes);
+		if (ret < 0)
+			return ret;
+	}
 
 	BUG_ON(src->found_link < dir_count);
 	dst->found_link += src->found_link - dir_count;
@@ -704,9 +917,11 @@ static int merge_inode_recs(struct inode_record *src, struct inode_record *dst,
 		} else {
 			if (dst->extent_end > src->extent_start)
 				dst->errors |= I_ERR_FILE_EXTENT_OVERLAP;
-			else if (dst->extent_end < src->extent_start &&
-				 dst->extent_end < dst->first_extent_gap)
-				dst->first_extent_gap = dst->extent_end;
+			else if (dst->extent_end < src->extent_start) {
+				ret = add_file_extent_hole(&dst->holes,
+					dst->extent_end,
+					src->extent_start - dst->extent_end);
+			}
 			if (dst->extent_end < src->extent_end)
 				dst->extent_end = src->extent_end;
 		}
@@ -1231,9 +1446,12 @@ static int process_file_extent(struct btrfs_root *root,
 
 	if (rec->extent_end > key->offset)
 		rec->errors |= I_ERR_FILE_EXTENT_OVERLAP;
-	else if (rec->extent_end < key->offset &&
-		 rec->extent_end < rec->first_extent_gap)
-		rec->first_extent_gap = rec->extent_end;
+	else if (rec->extent_end < key->offset) {
+		ret = add_file_extent_hole(&rec->holes, rec->extent_end,
+					   key->offset - rec->extent_end);
+		if (ret < 0)
+			return ret;
+	}
 
 	fi = btrfs_item_ptr(eb, slot, struct btrfs_file_extent_item);
 	extent_type = btrfs_file_extent_type(eb, fi);
-- 
2.2.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v2 4/5] btrfs-progs: Add repair and report function for orphan file extent.
  2015-01-02  7:12 [PATCH v2 1/5] btrfs-progs: Record orphan data extent ref to corresponding root Qu Wenruo
  2015-01-02  7:12 ` [PATCH v2 2/5] btrfs-progs: Add btrfs_get_extent() and btrfs_punch_hole() Qu Wenruo
  2015-01-02  7:12 ` [PATCH v2 3/5] btrfs-progs: Record and report every file extent hole Qu Wenruo
@ 2015-01-02  7:12 ` Qu Wenruo
  2015-01-02  7:12 ` [PATCH v2 5/5] btrfs-progs: Add repair function for discount file extent hole Qu Wenruo
  2015-02-02 13:43 ` [PATCH v2 1/5] btrfs-progs: Record orphan data extent ref to corresponding root David Sterba
  4 siblings, 0 replies; 10+ messages in thread
From: Qu Wenruo @ 2015-01-02  7:12 UTC (permalink / raw)
  To: linux-btrfs

In some fs tree leaf/node corruption case, file extents may be lost, but
in extent tree, its record may still exists.

This provide the possibility for such orphan file extents to be
recovered even we can't recover its compression and other info, we can
still insert it as a normal non-compression file extent.

This patch provides the repair and report function for such orphan file
extent.
Even after such repair, user may still need to try to decompress its
data if user knows that is a compressed extent.

Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
---
Changelog:
v2:
   Add orphan_extents list initialization in clone_inode_rec() to avoid
   segfault in snapshot cases like fsck-tests/006.
---
 cmds-check.c | 160 +++++++++++++++++++++++++++++++++++++++++++++++------------
 1 file changed, 129 insertions(+), 31 deletions(-)

diff --git a/cmds-check.c b/cmds-check.c
index 76216c5..b880f4c 100644
--- a/cmds-check.c
+++ b/cmds-check.c
@@ -86,7 +86,8 @@ struct data_backref {
 /*
  * Much like data_backref, just removed the undetermined members
  * and change it to use list_head.
- * Stored in the root->orphan_data_extents list
+ * During extent scan, it is stored in root->orphan_data_extent.
+ * During fs tree scan, it is then moved to inode_rec->orphan_data_extents.
  */
 struct orphan_data_extent {
 	struct list_head list;
@@ -386,6 +387,7 @@ struct inode_record {
 	u64 extent_start;
 	u64 extent_end;
 	struct rb_root holes;
+	struct list_head orphan_extents;
 
 	u32 refs;
 };
@@ -404,6 +406,7 @@ struct inode_record {
 #define I_ERR_ODD_CSUM_ITEM		(1 << 11)
 #define I_ERR_SOME_CSUM_MISSING		(1 << 12)
 #define I_ERR_LINK_COUNT_WRONG		(1 << 13)
+#define I_ERR_FILE_EXTENT_ORPHAN	(1 << 14)
 
 struct root_backref {
 	struct list_head list;
@@ -509,12 +512,15 @@ static struct inode_record *clone_inode_rec(struct inode_record *orig_rec)
 	struct inode_record *rec;
 	struct inode_backref *backref;
 	struct inode_backref *orig;
+	struct orphan_data_extent *src_orphan;
+	struct orphan_data_extent *dst_orphan;
 	size_t size;
 
 	rec = malloc(sizeof(*rec));
 	memcpy(rec, orig_rec, sizeof(*rec));
 	rec->refs = 1;
 	INIT_LIST_HEAD(&rec->backrefs);
+	INIT_LIST_HEAD(&rec->orphan_extents);
 
 	list_for_each_entry(orig, &orig_rec->backrefs, list) {
 		size = sizeof(*orig) + orig->namelen + 1;
@@ -522,9 +528,32 @@ static struct inode_record *clone_inode_rec(struct inode_record *orig_rec)
 		memcpy(backref, orig, size);
 		list_add_tail(&backref->list, &rec->backrefs);
 	}
+	list_for_each_entry(src_orphan, &orig_rec->orphan_extents, list) {
+		dst_orphan = malloc(sizeof(*dst_orphan));
+		/* TODO: Fix all the HELL of un-catched -ENOMEM case */
+		BUG_ON(!dst_orphan);
+		memcpy(dst_orphan, src_orphan, sizeof(*src_orphan));
+		list_add_tail(&dst_orphan->list, &rec->orphan_extents);
+	}
 	return rec;
 }
 
+static void print_orphan_data_extents(struct list_head *orphan_extents,
+				      u64 objectid)
+{
+	struct orphan_data_extent *orphan;
+
+	if (list_empty(orphan_extents))
+		return;
+	printf("The following data extent is lost in tree %llu:\n",
+	       objectid);
+	list_for_each_entry(orphan, orphan_extents, list) {
+		printf("\tinode: %llu, offset:%llu, disk_bytenr: %llu, disk_len: %llu\n",
+		       orphan->objectid, orphan->offset, orphan->disk_bytenr,
+		       orphan->disk_len);
+	}
+}
+
 static void print_inode_error(struct btrfs_root *root, struct inode_record *rec)
 {
 	u64 root_objectid = root->root_key.objectid;
@@ -569,7 +598,13 @@ static void print_inode_error(struct btrfs_root *root, struct inode_record *rec)
 		fprintf(stderr, ", some csum missing");
 	if (errors & I_ERR_LINK_COUNT_WRONG)
 		fprintf(stderr, ", link count wrong");
+	if (errors & I_ERR_FILE_EXTENT_ORPHAN)
+		fprintf(stderr, ", orphan file extent");
 	fprintf(stderr, "\n");
+	/* Print the orphan extents if needed */
+	if (errors & I_ERR_FILE_EXTENT_ORPHAN)
+		print_orphan_data_extents(&rec->orphan_extents, root->objectid);
+
 	/* Print the holes if needed */
 	if (errors & I_ERR_FILE_EXTENT_DISCOUNT) {
 		struct file_extent_hole *hole;
@@ -640,6 +675,7 @@ static struct inode_record *get_inode_rec(struct cache_tree *inode_cache,
 		rec->extent_start = (u64)-1;
 		rec->refs = 1;
 		INIT_LIST_HEAD(&rec->backrefs);
+		INIT_LIST_HEAD(&rec->orphan_extents);
 		rec->holes = RB_ROOT;
 
 		node = malloc(sizeof(*node));
@@ -656,6 +692,18 @@ static struct inode_record *get_inode_rec(struct cache_tree *inode_cache,
 	return rec;
 }
 
+static void free_orphan_data_extents(struct list_head *orphan_extents)
+{
+	struct orphan_data_extent *orphan;
+
+	while (!list_empty(orphan_extents)) {
+		orphan = list_entry(orphan_extents->next,
+				    struct orphan_data_extent, list);
+		list_del(&orphan->list);
+		free(orphan);
+	}
+}
+
 static void free_inode_rec(struct inode_record *rec)
 {
 	struct inode_backref *backref;
@@ -669,6 +717,7 @@ static void free_inode_rec(struct inode_record *rec)
 		list_del(&backref->list);
 		free(backref);
 	}
+	free_orphan_data_extents(&rec->orphan_extents);
 	free_file_extent_holes(&rec->holes);
 	free(rec);
 }
@@ -2490,6 +2539,67 @@ out:
 	return ret;
 }
 
+static int repair_inode_orphan_extent(struct btrfs_trans_handle *trans,
+				      struct btrfs_root *root,
+				      struct btrfs_path *path,
+				      struct inode_record *rec)
+{
+	struct orphan_data_extent *orphan;
+	struct orphan_data_extent *tmp;
+	int ret = 0;
+
+	list_for_each_entry_safe(orphan, tmp, &rec->orphan_extents, list) {
+		/*
+		 * Check for conflicting file extents
+		 *
+		 * Here we don't know whether the extents is compressed or not,
+		 * so we can only assume it not compressed nor data offset,
+		 * and use its disk_len as extent length.
+		 */
+		ret = btrfs_get_extent(NULL, root, path, orphan->objectid,
+				       orphan->offset, orphan->disk_len, 0);
+		btrfs_release_path(path);
+		if (ret < 0)
+			goto out;
+		if (!ret) {
+			fprintf(stderr,
+				"orphan extent (%llu, %llu) conflicts, delete the orphan\n",
+				orphan->disk_bytenr, orphan->disk_len);
+			ret = btrfs_free_extent(trans,
+					root->fs_info->extent_root,
+					orphan->disk_bytenr, orphan->disk_len,
+					0, root->objectid, orphan->objectid,
+					orphan->offset);
+			if (ret < 0)
+				goto out;
+		}
+		ret = btrfs_insert_file_extent(trans, root, orphan->objectid,
+				orphan->offset, orphan->disk_bytenr,
+				orphan->disk_len, orphan->disk_len);
+		if (ret < 0)
+			goto out;
+
+		/* Update file size info */
+		rec->found_size += orphan->disk_len;
+		if (rec->found_size == rec->nbytes)
+			rec->errors &= ~I_ERR_FILE_NBYTES_WRONG;
+
+		/* Update the file extent hole info too */
+		ret = del_file_extent_hole(&rec->holes, orphan->offset,
+					   orphan->disk_len);
+		if (ret < 0)
+			goto out;
+		if (RB_EMPTY_ROOT(&rec->holes))
+			rec->errors &= ~I_ERR_FILE_EXTENT_DISCOUNT;
+
+		list_del(&orphan->list);
+		free(orphan);
+	}
+	rec->errors &= ~I_ERR_FILE_EXTENT_ORPHAN;
+out:
+	return ret;
+}
+
 static int try_repair_inode(struct btrfs_root *root, struct inode_record *rec)
 {
 	struct btrfs_trans_handle *trans;
@@ -2499,7 +2609,8 @@ static int try_repair_inode(struct btrfs_root *root, struct inode_record *rec)
 	if (!(rec->errors & (I_ERR_DIR_ISIZE_WRONG |
 			     I_ERR_NO_ORPHAN_ITEM |
 			     I_ERR_LINK_COUNT_WRONG |
-			     I_ERR_NO_INODE_ITEM)))
+			     I_ERR_NO_INODE_ITEM |
+			     I_ERR_FILE_EXTENT_ORPHAN)))
 		return rec->errors;
 
 	path = btrfs_alloc_path();
@@ -2521,6 +2632,8 @@ static int try_repair_inode(struct btrfs_root *root, struct inode_record *rec)
 
 	if (rec->errors & I_ERR_NO_INODE_ITEM)
 		ret = repair_inode_no_item(trans, root, path, rec);
+	if (!ret && rec->errors & I_ERR_FILE_EXTENT_ORPHAN)
+		ret = repair_inode_orphan_extent(trans, root, path, rec);
 	if (!ret && rec->errors & I_ERR_DIR_ISIZE_WRONG)
 		ret = repair_inode_isize(trans, root, path, rec);
 	if (!ret && rec->errors & I_ERR_NO_ORPHAN_ITEM)
@@ -3133,34 +3246,6 @@ out_free_path:
 	return ret;
 }
 
-static void print_orphan_data_extents(struct list_head *orphan_extents,
-				      u64 objectid)
-{
-	struct orphan_data_extent *orphan;
-
-	if (list_empty(orphan_extents))
-		return;
-	printf("The following data extent is lost in tree %llu:\n",
-	       objectid);
-	list_for_each_entry(orphan, orphan_extents, list) {
-		printf("\tinode: %llu, offset:%llu, disk_bytenr: %llu, disk_len: %llu\n",
-		       orphan->objectid, orphan->offset, orphan->disk_bytenr,
-		       orphan->disk_len);
-	}
-}
-
-static void free_orphan_data_extents(struct list_head *orphan_extents)
-{
-	struct orphan_data_extent *orphan;
-
-	while (!list_empty(orphan_extents)) {
-		orphan = list_entry(orphan_extents->next,
-				    struct orphan_data_extent, list);
-		list_del(&orphan->list);
-		free(orphan);
-	}
-}
-
 static int check_fs_root(struct btrfs_root *root,
 			 struct cache_tree *root_cache,
 			 struct walk_control *wc)
@@ -3174,6 +3259,8 @@ static int check_fs_root(struct btrfs_root *root,
 	struct root_record *rec;
 	struct btrfs_root_item *root_item = &root->root_item;
 	struct cache_tree corrupt_blocks;
+	struct orphan_data_extent *orphan;
+	struct orphan_data_extent *tmp;
 	enum btrfs_tree_block_status status;
 
 	/*
@@ -3184,6 +3271,7 @@ static int check_fs_root(struct btrfs_root *root,
 	 */
 	cache_tree_init(&corrupt_blocks);
 	root->fs_info->corrupt_blocks = &corrupt_blocks;
+
 	if (root->root_key.objectid != BTRFS_TREE_RELOC_OBJECTID) {
 		rec = get_root_rec(root_cache, root->root_key.objectid);
 		if (btrfs_root_refs(root_item) > 0)
@@ -3195,6 +3283,17 @@ static int check_fs_root(struct btrfs_root *root,
 	cache_tree_init(&root_node.root_cache);
 	cache_tree_init(&root_node.inode_cache);
 
+	/* Move the orphan extent record to corresponding inode_record */
+	list_for_each_entry_safe(orphan, tmp,
+				 &root->orphan_data_extents, list) {
+		struct inode_record *inode;
+
+		inode = get_inode_rec(&root_node.inode_cache, orphan->objectid,
+				      1);
+		inode->errors |= I_ERR_FILE_EXTENT_ORPHAN;
+		list_move(&orphan->list, &inode->orphan_extents);
+	}
+
 	level = btrfs_header_level(root->node);
 	memset(wc->nodes, 0, sizeof(wc->nodes));
 	wc->nodes[level] = &root_node;
@@ -3292,7 +3391,6 @@ skip_walking:
 
 	free_corrupt_blocks_tree(&corrupt_blocks);
 	root->fs_info->corrupt_blocks = NULL;
-	print_orphan_data_extents(&root->orphan_data_extents, root->objectid);
 	free_orphan_data_extents(&root->orphan_data_extents);
 	return ret;
 }
-- 
2.2.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v2 5/5] btrfs-progs: Add repair function for discount file extent hole.
  2015-01-02  7:12 [PATCH v2 1/5] btrfs-progs: Record orphan data extent ref to corresponding root Qu Wenruo
                   ` (2 preceding siblings ...)
  2015-01-02  7:12 ` [PATCH v2 4/5] btrfs-progs: Add repair and report function for orphan file extent Qu Wenruo
@ 2015-01-02  7:12 ` Qu Wenruo
  2015-02-02 13:43 ` [PATCH v2 1/5] btrfs-progs: Record orphan data extent ref to corresponding root David Sterba
  4 siblings, 0 replies; 10+ messages in thread
From: Qu Wenruo @ 2015-01-02  7:12 UTC (permalink / raw)
  To: linux-btrfs

Since orphan extents are handled in previous patches, now just punch
holes to fill the file extents hole.

Also since now btrfsck is aware of whether the inode has orphan file
extent, allow repair_inode_no_item() to determine filetype according to
orphan file extent.

Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
---
Changelog:
v2:
   None
---
 cmds-check.c | 51 ++++++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 40 insertions(+), 11 deletions(-)

diff --git a/cmds-check.c b/cmds-check.c
index b880f4c..ddc0ded 100644
--- a/cmds-check.c
+++ b/cmds-check.c
@@ -2476,12 +2476,6 @@ static int repair_inode_no_item(struct btrfs_trans_handle *trans,
 	int type_recovered = 0;
 	int ret = 0;
 
-	/*
-	 * TODO:
-	 * 1. salvage data from existing file extent and
-	 *    punch hole to keep fi ext consistent.
-	 * 2. salvage data from extent tree
-	 */
 	printf("Trying to rebuild inode:%llu\n", rec->ino);
 
 	type_recovered = !find_file_type(rec, &filetype);
@@ -2495,9 +2489,7 @@ static int repair_inode_no_item(struct btrfs_trans_handle *trans,
 	 * For undetermined one, use FILE as fallback.
 	 *
 	 * TODO:
-	 * 1. If found extent belong to it in extent tree, it must be FILE
-	 *    Need extra hook in extent tree scan.
-	 * 2. If found backref(inode_index/item is already handled) to it,
+	 * 1. If found backref(inode_index/item is already handled) to it,
 	 *    it must be DIR.
 	 *    Need new inode-inode ref structure to allow search for that.
 	 */
@@ -2509,7 +2501,10 @@ static int repair_inode_no_item(struct btrfs_trans_handle *trans,
 		} else if (rec->found_dir_item) {
 			type_recovered = 1;
 			filetype = BTRFS_FT_DIR;
-		} else {
+		} else if (!list_empty(&rec->orphan_extents)) {
+			type_recovered = 1;
+			filetype = BTRFS_FT_REG_FILE;
+		} else{
 			printf("Can't determint the filetype for inode %llu, assume it is a normal file\n",
 			       rec->ino);
 			type_recovered = 1;
@@ -2600,6 +2595,37 @@ out:
 	return ret;
 }
 
+static int repair_inode_discount_extent(struct btrfs_trans_handle *trans,
+					struct btrfs_root *root,
+					struct btrfs_path *path,
+					struct inode_record *rec)
+{
+	struct rb_node *node;
+	struct file_extent_hole *hole;
+	int ret = 0;
+
+	node = rb_first(&rec->holes);
+
+	while (node) {
+		hole = rb_entry(node, struct file_extent_hole, node);
+		ret = btrfs_punch_hole(trans, root, rec->ino,
+				       hole->start, hole->len);
+		if (ret < 0)
+			goto out;
+		ret = del_file_extent_hole(&rec->holes, hole->start,
+					   hole->len);
+		if (ret < 0)
+			goto out;
+		if (RB_EMPTY_ROOT(&rec->holes))
+			rec->errors &= ~I_ERR_FILE_EXTENT_DISCOUNT;
+		node = rb_first(&rec->holes);
+	}
+	printf("Fixed discount file extents for inode: %llu in root: %llu\n",
+	       rec->ino, root->objectid);
+out:
+	return ret;
+}
+
 static int try_repair_inode(struct btrfs_root *root, struct inode_record *rec)
 {
 	struct btrfs_trans_handle *trans;
@@ -2610,7 +2636,8 @@ static int try_repair_inode(struct btrfs_root *root, struct inode_record *rec)
 			     I_ERR_NO_ORPHAN_ITEM |
 			     I_ERR_LINK_COUNT_WRONG |
 			     I_ERR_NO_INODE_ITEM |
-			     I_ERR_FILE_EXTENT_ORPHAN)))
+			     I_ERR_FILE_EXTENT_ORPHAN |
+			     I_ERR_FILE_EXTENT_DISCOUNT)))
 		return rec->errors;
 
 	path = btrfs_alloc_path();
@@ -2634,6 +2661,8 @@ static int try_repair_inode(struct btrfs_root *root, struct inode_record *rec)
 		ret = repair_inode_no_item(trans, root, path, rec);
 	if (!ret && rec->errors & I_ERR_FILE_EXTENT_ORPHAN)
 		ret = repair_inode_orphan_extent(trans, root, path, rec);
+	if (!ret && rec->errors & I_ERR_FILE_EXTENT_DISCOUNT)
+		ret = repair_inode_discount_extent(trans, root, path, rec);
 	if (!ret && rec->errors & I_ERR_DIR_ISIZE_WRONG)
 		ret = repair_inode_isize(trans, root, path, rec);
 	if (!ret && rec->errors & I_ERR_NO_ORPHAN_ITEM)
-- 
2.2.1


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 1/5] btrfs-progs: Record orphan data extent ref to corresponding root.
  2015-01-02  7:12 [PATCH v2 1/5] btrfs-progs: Record orphan data extent ref to corresponding root Qu Wenruo
                   ` (3 preceding siblings ...)
  2015-01-02  7:12 ` [PATCH v2 5/5] btrfs-progs: Add repair function for discount file extent hole Qu Wenruo
@ 2015-02-02 13:43 ` David Sterba
  4 siblings, 0 replies; 10+ messages in thread
From: David Sterba @ 2015-02-02 13:43 UTC (permalink / raw)
  To: Qu Wenruo; +Cc: linux-btrfs

On Fri, Jan 02, 2015 at 03:12:29PM +0800, Qu Wenruo wrote:
> v2:
>    Do not record file extent if the file extent pointed by the data
>    backref exists but only bytenr mismatch.
>    This fix a regression bug causing fsck-test 001 fail.

Patches 1-5 applied to 3.19, thanks.

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 3/5] btrfs-progs: Record and report every file extent hole.
  2015-01-02  7:12 ` [PATCH v2 3/5] btrfs-progs: Record and report every file extent hole Qu Wenruo
@ 2015-03-25  3:05   ` Eric Sandeen
  2015-03-25  3:36     ` Qu Wenruo
  0 siblings, 1 reply; 10+ messages in thread
From: Eric Sandeen @ 2015-03-25  3:05 UTC (permalink / raw)
  To: Qu Wenruo, linux-btrfs

On 1/2/15 1:12 AM, Qu Wenruo wrote:
> Record every file extent discontinuous hole in inode_record using a
> rb_tree member.
> 
> Before the patch, btrfsck will only record the first file extent hole by
> using first_extent_gap, that's good for detecting error, but not
> suitable for fixing it.
> 
> This patch provides the ability to record every file extent hole and
> report it.

This is causing use after free and segfaults in my testing, running
xfstests btrfs/078 with multiple devices defined:

SCRATCH_DEV_POOL="/dev/sdc5 /dev/sdc6 /dev/sdc7 /dev/sdc8 /dev/sdc9 /dev/sdc10 /dev/sdc11 /dev/sdc12"

-Eric

# valgrind ./btrfsck /dev/sdc5 
==31620== Memcheck, a memory error detector
==31620== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==31620== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==31620== Command: ./btrfsck /dev/sdc5
==31620== 
Checking filesystem on /dev/sdc5
UUID: ab91fc96-549b-4048-a68b-73c5190e6265
checking extents
checking free space cache
checking fs roots
==31620== Invalid read of size 8
==31620==    at 0x4C257C3: rb_first (rbtree.c:420)
==31620==    by 0x41E609: first_extent_gap (cmds-check.c:182)
==31620==    by 0x427D43: merge_inode_recs (cmds-check.c:950)
==31620==    by 0x42827B: splice_shared_node (cmds-check.c:1032)
==31620==    by 0x428827: enter_shared_node (cmds-check.c:1138)
==31620==    by 0x428BCF: walk_down_tree (cmds-check.c:1745)
==31620==    by 0x42CA64: check_fs_root (cmds-check.c:3360)
==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
==31620==    by 0x40C089: main (btrfs.c:245)
==31620==  Address 0x4e5dc60 is 16 bytes inside a block of size 40 free'd
==31620==    at 0x4A063F0: free (vg_replace_malloc.c:446)
==31620==    by 0x421887: free_file_extent_holes (cmds-check.c:359)
==31620==    by 0x4218FB: free_inode_rec (cmds-check.c:718)
==31620==    by 0x42753E: maybe_free_inode_rec (cmds-check.c:786)
==31620==    by 0x4282A5: splice_shared_node (cmds-check.c:1038)
==31620==    by 0x42849E: leave_shared_node (cmds-check.c:1170)
==31620==    by 0x42869F: walk_up_tree (cmds-check.c:1817)
==31620==    by 0x42CA82: check_fs_root (cmds-check.c:3366)
==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
==31620==    by 0x40C089: main (btrfs.c:245)
==31620== 
==31620== Invalid read of size 8
==31620==    at 0x41E60A: first_extent_gap (cmds-check.c:183)
==31620==    by 0x427D43: merge_inode_recs (cmds-check.c:950)
==31620==    by 0x42827B: splice_shared_node (cmds-check.c:1032)
==31620==    by 0x428827: enter_shared_node (cmds-check.c:1138)
==31620==    by 0x428BCF: walk_down_tree (cmds-check.c:1745)
==31620==    by 0x42CA64: check_fs_root (cmds-check.c:3360)
==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
==31620==    by 0x40C089: main (btrfs.c:245)
==31620==  Address 0x4e5dc68 is 24 bytes inside a block of size 40 free'd
==31620==    at 0x4A063F0: free (vg_replace_malloc.c:446)
==31620==    by 0x421887: free_file_extent_holes (cmds-check.c:359)
==31620==    by 0x4218FB: free_inode_rec (cmds-check.c:718)
==31620==    by 0x42753E: maybe_free_inode_rec (cmds-check.c:786)
==31620==    by 0x4282A5: splice_shared_node (cmds-check.c:1038)
==31620==    by 0x42849E: leave_shared_node (cmds-check.c:1170)
==31620==    by 0x42869F: walk_up_tree (cmds-check.c:1817)
==31620==    by 0x42CA82: check_fs_root (cmds-check.c:3366)
==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
==31620==    by 0x40C089: main (btrfs.c:245)
==31620== 
==31620== Invalid read of size 8
==31620==    at 0x4C257C3: rb_first (rbtree.c:420)
==31620==    by 0x41E609: first_extent_gap (cmds-check.c:182)
==31620==    by 0x427421: maybe_free_inode_rec (cmds-check.c:768)
==31620==    by 0x4282A5: splice_shared_node (cmds-check.c:1038)
==31620==    by 0x428827: enter_shared_node (cmds-check.c:1138)
==31620==    by 0x428BCF: walk_down_tree (cmds-check.c:1745)
==31620==    by 0x42CA64: check_fs_root (cmds-check.c:3360)
==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
==31620==    by 0x40C089: main (btrfs.c:245)
==31620==  Address 0x4e5dc60 is 16 bytes inside a block of size 40 free'd
==31620==    at 0x4A063F0: free (vg_replace_malloc.c:446)
==31620==    by 0x421887: free_file_extent_holes (cmds-check.c:359)
==31620==    by 0x4218FB: free_inode_rec (cmds-check.c:718)
==31620==    by 0x42753E: maybe_free_inode_rec (cmds-check.c:786)
==31620==    by 0x4282A5: splice_shared_node (cmds-check.c:1038)
==31620==    by 0x42849E: leave_shared_node (cmds-check.c:1170)
==31620==    by 0x42869F: walk_up_tree (cmds-check.c:1817)
==31620==    by 0x42CA82: check_fs_root (cmds-check.c:3366)
==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
==31620==    by 0x40C089: main (btrfs.c:245)
==31620== 
==31620== Invalid read of size 8
==31620==    at 0x41E60A: first_extent_gap (cmds-check.c:183)
==31620==    by 0x427421: maybe_free_inode_rec (cmds-check.c:768)
==31620==    by 0x4282A5: splice_shared_node (cmds-check.c:1038)
==31620==    by 0x428827: enter_shared_node (cmds-check.c:1138)
==31620==    by 0x428BCF: walk_down_tree (cmds-check.c:1745)
==31620==    by 0x42CA64: check_fs_root (cmds-check.c:3360)
==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
==31620==    by 0x40C089: main (btrfs.c:245)
==31620==  Address 0x4e5dc68 is 24 bytes inside a block of size 40 free'd
==31620==    at 0x4A063F0: free (vg_replace_malloc.c:446)
==31620==    by 0x421887: free_file_extent_holes (cmds-check.c:359)
==31620==    by 0x4218FB: free_inode_rec (cmds-check.c:718)
==31620==    by 0x42753E: maybe_free_inode_rec (cmds-check.c:786)
==31620==    by 0x4282A5: splice_shared_node (cmds-check.c:1038)
==31620==    by 0x42849E: leave_shared_node (cmds-check.c:1170)
==31620==    by 0x42869F: walk_up_tree (cmds-check.c:1817)
==31620==    by 0x42CA82: check_fs_root (cmds-check.c:3366)
==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
==31620==    by 0x40C089: main (btrfs.c:245)
==31620== 
==31620== Invalid read of size 8
==31620==    at 0x4C257C3: rb_first (rbtree.c:420)
==31620==    by 0x42186C: free_file_extent_holes (cmds-check.c:355)
==31620==    by 0x4218FB: free_inode_rec (cmds-check.c:718)
==31620==    by 0x42753E: maybe_free_inode_rec (cmds-check.c:786)
==31620==    by 0x4282A5: splice_shared_node (cmds-check.c:1038)
==31620==    by 0x428827: enter_shared_node (cmds-check.c:1138)
==31620==    by 0x428BCF: walk_down_tree (cmds-check.c:1745)
==31620==    by 0x42CA64: check_fs_root (cmds-check.c:3360)
==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
==31620==    by 0x40C089: main (btrfs.c:245)
==31620==  Address 0x4e5dc60 is 16 bytes inside a block of size 40 free'd
==31620==    at 0x4A063F0: free (vg_replace_malloc.c:446)
==31620==    by 0x421887: free_file_extent_holes (cmds-check.c:359)
==31620==    by 0x4218FB: free_inode_rec (cmds-check.c:718)
==31620==    by 0x42753E: maybe_free_inode_rec (cmds-check.c:786)
==31620==    by 0x4282A5: splice_shared_node (cmds-check.c:1038)
==31620==    by 0x42849E: leave_shared_node (cmds-check.c:1170)
==31620==    by 0x42869F: walk_up_tree (cmds-check.c:1817)
==31620==    by 0x42CA82: check_fs_root (cmds-check.c:3366)
==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
==31620==    by 0x40C089: main (btrfs.c:245)

... etc ...


^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 3/5] btrfs-progs: Record and report every file extent hole.
  2015-03-25  3:05   ` Eric Sandeen
@ 2015-03-25  3:36     ` Qu Wenruo
  2015-05-02 16:36       ` Filipe David Manana
  0 siblings, 1 reply; 10+ messages in thread
From: Qu Wenruo @ 2015-03-25  3:36 UTC (permalink / raw)
  To: Eric Sandeen, linux-btrfs

Thanks, I'll investigate it soon.

Thanks,
Qu

> On 1/2/15 1:12 AM, Qu Wenruo wrote:
>> Record every file extent discontinuous hole in inode_record using a
>> rb_tree member.
>>
>> Before the patch, btrfsck will only record the first file extent hole by
>> using first_extent_gap, that's good for detecting error, but not
>> suitable for fixing it.
>>
>> This patch provides the ability to record every file extent hole and
>> report it.
>
> This is causing use after free and segfaults in my testing, running
> xfstests btrfs/078 with multiple devices defined:
>
> SCRATCH_DEV_POOL="/dev/sdc5 /dev/sdc6 /dev/sdc7 /dev/sdc8 /dev/sdc9 /dev/sdc10 /dev/sdc11 /dev/sdc12"
>
> -Eric
>
> # valgrind ./btrfsck /dev/sdc5
> ==31620== Memcheck, a memory error detector
> ==31620== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
> ==31620== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
> ==31620== Command: ./btrfsck /dev/sdc5
> ==31620==
> Checking filesystem on /dev/sdc5
> UUID: ab91fc96-549b-4048-a68b-73c5190e6265
> checking extents
> checking free space cache
> checking fs roots
> ==31620== Invalid read of size 8
> ==31620==    at 0x4C257C3: rb_first (rbtree.c:420)
> ==31620==    by 0x41E609: first_extent_gap (cmds-check.c:182)
> ==31620==    by 0x427D43: merge_inode_recs (cmds-check.c:950)
> ==31620==    by 0x42827B: splice_shared_node (cmds-check.c:1032)
> ==31620==    by 0x428827: enter_shared_node (cmds-check.c:1138)
> ==31620==    by 0x428BCF: walk_down_tree (cmds-check.c:1745)
> ==31620==    by 0x42CA64: check_fs_root (cmds-check.c:3360)
> ==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
> ==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
> ==31620==    by 0x40C089: main (btrfs.c:245)
> ==31620==  Address 0x4e5dc60 is 16 bytes inside a block of size 40 free'd
> ==31620==    at 0x4A063F0: free (vg_replace_malloc.c:446)
> ==31620==    by 0x421887: free_file_extent_holes (cmds-check.c:359)
> ==31620==    by 0x4218FB: free_inode_rec (cmds-check.c:718)
> ==31620==    by 0x42753E: maybe_free_inode_rec (cmds-check.c:786)
> ==31620==    by 0x4282A5: splice_shared_node (cmds-check.c:1038)
> ==31620==    by 0x42849E: leave_shared_node (cmds-check.c:1170)
> ==31620==    by 0x42869F: walk_up_tree (cmds-check.c:1817)
> ==31620==    by 0x42CA82: check_fs_root (cmds-check.c:3366)
> ==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
> ==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
> ==31620==    by 0x40C089: main (btrfs.c:245)
> ==31620==
> ==31620== Invalid read of size 8
> ==31620==    at 0x41E60A: first_extent_gap (cmds-check.c:183)
> ==31620==    by 0x427D43: merge_inode_recs (cmds-check.c:950)
> ==31620==    by 0x42827B: splice_shared_node (cmds-check.c:1032)
> ==31620==    by 0x428827: enter_shared_node (cmds-check.c:1138)
> ==31620==    by 0x428BCF: walk_down_tree (cmds-check.c:1745)
> ==31620==    by 0x42CA64: check_fs_root (cmds-check.c:3360)
> ==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
> ==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
> ==31620==    by 0x40C089: main (btrfs.c:245)
> ==31620==  Address 0x4e5dc68 is 24 bytes inside a block of size 40 free'd
> ==31620==    at 0x4A063F0: free (vg_replace_malloc.c:446)
> ==31620==    by 0x421887: free_file_extent_holes (cmds-check.c:359)
> ==31620==    by 0x4218FB: free_inode_rec (cmds-check.c:718)
> ==31620==    by 0x42753E: maybe_free_inode_rec (cmds-check.c:786)
> ==31620==    by 0x4282A5: splice_shared_node (cmds-check.c:1038)
> ==31620==    by 0x42849E: leave_shared_node (cmds-check.c:1170)
> ==31620==    by 0x42869F: walk_up_tree (cmds-check.c:1817)
> ==31620==    by 0x42CA82: check_fs_root (cmds-check.c:3366)
> ==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
> ==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
> ==31620==    by 0x40C089: main (btrfs.c:245)
> ==31620==
> ==31620== Invalid read of size 8
> ==31620==    at 0x4C257C3: rb_first (rbtree.c:420)
> ==31620==    by 0x41E609: first_extent_gap (cmds-check.c:182)
> ==31620==    by 0x427421: maybe_free_inode_rec (cmds-check.c:768)
> ==31620==    by 0x4282A5: splice_shared_node (cmds-check.c:1038)
> ==31620==    by 0x428827: enter_shared_node (cmds-check.c:1138)
> ==31620==    by 0x428BCF: walk_down_tree (cmds-check.c:1745)
> ==31620==    by 0x42CA64: check_fs_root (cmds-check.c:3360)
> ==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
> ==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
> ==31620==    by 0x40C089: main (btrfs.c:245)
> ==31620==  Address 0x4e5dc60 is 16 bytes inside a block of size 40 free'd
> ==31620==    at 0x4A063F0: free (vg_replace_malloc.c:446)
> ==31620==    by 0x421887: free_file_extent_holes (cmds-check.c:359)
> ==31620==    by 0x4218FB: free_inode_rec (cmds-check.c:718)
> ==31620==    by 0x42753E: maybe_free_inode_rec (cmds-check.c:786)
> ==31620==    by 0x4282A5: splice_shared_node (cmds-check.c:1038)
> ==31620==    by 0x42849E: leave_shared_node (cmds-check.c:1170)
> ==31620==    by 0x42869F: walk_up_tree (cmds-check.c:1817)
> ==31620==    by 0x42CA82: check_fs_root (cmds-check.c:3366)
> ==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
> ==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
> ==31620==    by 0x40C089: main (btrfs.c:245)
> ==31620==
> ==31620== Invalid read of size 8
> ==31620==    at 0x41E60A: first_extent_gap (cmds-check.c:183)
> ==31620==    by 0x427421: maybe_free_inode_rec (cmds-check.c:768)
> ==31620==    by 0x4282A5: splice_shared_node (cmds-check.c:1038)
> ==31620==    by 0x428827: enter_shared_node (cmds-check.c:1138)
> ==31620==    by 0x428BCF: walk_down_tree (cmds-check.c:1745)
> ==31620==    by 0x42CA64: check_fs_root (cmds-check.c:3360)
> ==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
> ==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
> ==31620==    by 0x40C089: main (btrfs.c:245)
> ==31620==  Address 0x4e5dc68 is 24 bytes inside a block of size 40 free'd
> ==31620==    at 0x4A063F0: free (vg_replace_malloc.c:446)
> ==31620==    by 0x421887: free_file_extent_holes (cmds-check.c:359)
> ==31620==    by 0x4218FB: free_inode_rec (cmds-check.c:718)
> ==31620==    by 0x42753E: maybe_free_inode_rec (cmds-check.c:786)
> ==31620==    by 0x4282A5: splice_shared_node (cmds-check.c:1038)
> ==31620==    by 0x42849E: leave_shared_node (cmds-check.c:1170)
> ==31620==    by 0x42869F: walk_up_tree (cmds-check.c:1817)
> ==31620==    by 0x42CA82: check_fs_root (cmds-check.c:3366)
> ==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
> ==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
> ==31620==    by 0x40C089: main (btrfs.c:245)
> ==31620==
> ==31620== Invalid read of size 8
> ==31620==    at 0x4C257C3: rb_first (rbtree.c:420)
> ==31620==    by 0x42186C: free_file_extent_holes (cmds-check.c:355)
> ==31620==    by 0x4218FB: free_inode_rec (cmds-check.c:718)
> ==31620==    by 0x42753E: maybe_free_inode_rec (cmds-check.c:786)
> ==31620==    by 0x4282A5: splice_shared_node (cmds-check.c:1038)
> ==31620==    by 0x428827: enter_shared_node (cmds-check.c:1138)
> ==31620==    by 0x428BCF: walk_down_tree (cmds-check.c:1745)
> ==31620==    by 0x42CA64: check_fs_root (cmds-check.c:3360)
> ==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
> ==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
> ==31620==    by 0x40C089: main (btrfs.c:245)
> ==31620==  Address 0x4e5dc60 is 16 bytes inside a block of size 40 free'd
> ==31620==    at 0x4A063F0: free (vg_replace_malloc.c:446)
> ==31620==    by 0x421887: free_file_extent_holes (cmds-check.c:359)
> ==31620==    by 0x4218FB: free_inode_rec (cmds-check.c:718)
> ==31620==    by 0x42753E: maybe_free_inode_rec (cmds-check.c:786)
> ==31620==    by 0x4282A5: splice_shared_node (cmds-check.c:1038)
> ==31620==    by 0x42849E: leave_shared_node (cmds-check.c:1170)
> ==31620==    by 0x42869F: walk_up_tree (cmds-check.c:1817)
> ==31620==    by 0x42CA82: check_fs_root (cmds-check.c:3366)
> ==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
> ==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
> ==31620==    by 0x40C089: main (btrfs.c:245)
>
> ... etc ...
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 3/5] btrfs-progs: Record and report every file extent hole.
  2015-03-25  3:36     ` Qu Wenruo
@ 2015-05-02 16:36       ` Filipe David Manana
  2015-05-05  0:55         ` Qu Wenruo
  0 siblings, 1 reply; 10+ messages in thread
From: Filipe David Manana @ 2015-05-02 16:36 UTC (permalink / raw)
  To: Qu Wenruo; +Cc: Eric Sandeen, linux-btrfs

On Wed, Mar 25, 2015 at 3:36 AM, Qu Wenruo <quwenruo@cn.fujitsu.com> wrote:
> Thanks, I'll investigate it soon.
>
> Thanks,
> Qu

Qu, did you end up finding anything?

Just upgraded to btrfs-progs 4.0 and getting pretty much the same as
Eric all the time I run btrfs/078.
Valgrind should give you some nice clues.

E.g.

(...)
checking free space cache
checking fs roots
==11808== Invalid read of size 8
==11808==    at 0x4611C2: rb_first (rbtree.c:420)
==11808==    by 0x41B694: first_extent_gap (cmds-check.c:184)
==11808==    by 0x42020E: merge_inode_recs (cmds-check.c:954)
==11808==    by 0x42020E: splice_shared_node (cmds-check.c:1036)
==11808==    by 0x4205B8: enter_shared_node (cmds-check.c:1142)
==11808==    by 0x420F6E: walk_down_tree (cmds-check.c:1758)
==11808==    by 0x429555: check_fs_root (cmds-check.c:3382)
==11808==    by 0x429555: check_fs_roots (cmds-check.c:3518)
==11808==    by 0x429555: cmd_check (cmds-check.c:9465)
==11808==    by 0x409BEC: main (btrfs.c:245)
==11808==  Address 0x6057d10 is 16 bytes inside a block of size 40 free'd
==11808==    at 0x4C29E90: free (vg_replace_malloc.c:473)
==11808==    by 0x41C118: free_file_extent_holes (cmds-check.c:363)
==11808==    by 0x41C118: free_inode_rec (cmds-check.c:722)
==11808==    by 0x41F9CA: maybe_free_inode_rec (cmds-check.c:790)
==11808==    by 0x42036C: splice_shared_node (cmds-check.c:1042)
==11808==    by 0x4205B8: enter_shared_node (cmds-check.c:1142)
==11808==    by 0x420F6E: walk_down_tree (cmds-check.c:1758)
==11808==    by 0x429555: check_fs_root (cmds-check.c:3382)
==11808==    by 0x429555: check_fs_roots (cmds-check.c:3518)
==11808==    by 0x429555: cmd_check (cmds-check.c:9465)
==11808==    by 0x409BEC: main (btrfs.c:245)
==11808==
==11808==
==11808== Process terminating with default action of signal 11 (SIGSEGV)
==11808==  General Protection Fault
==11808==    at 0x4611C2: rb_first (rbtree.c:420)
==11808==    by 0x41B694: first_extent_gap (cmds-check.c:184)
==11808==    by 0x42020E: merge_inode_recs (cmds-check.c:954)
==11808==    by 0x42020E: splice_shared_node (cmds-check.c:1036)
==11808==    by 0x4205B8: enter_shared_node (cmds-check.c:1142)
==11808==    by 0x420F6E: walk_down_tree (cmds-check.c:1758)
==11808==    by 0x429555: check_fs_root (cmds-check.c:3382)
==11808==    by 0x429555: check_fs_roots (cmds-check.c:3518)
==11808==    by 0x429555: cmd_check (cmds-check.c:9465)
==11808==    by 0x409BEC: main (btrfs.c:245)
(....)

Thanks.


>
>
>> On 1/2/15 1:12 AM, Qu Wenruo wrote:
>>>
>>> Record every file extent discontinuous hole in inode_record using a
>>> rb_tree member.
>>>
>>> Before the patch, btrfsck will only record the first file extent hole by
>>> using first_extent_gap, that's good for detecting error, but not
>>> suitable for fixing it.
>>>
>>> This patch provides the ability to record every file extent hole and
>>> report it.
>>
>>
>> This is causing use after free and segfaults in my testing, running
>> xfstests btrfs/078 with multiple devices defined:
>>
>> SCRATCH_DEV_POOL="/dev/sdc5 /dev/sdc6 /dev/sdc7 /dev/sdc8 /dev/sdc9
>> /dev/sdc10 /dev/sdc11 /dev/sdc12"
>>
>> -Eric
>>
>> # valgrind ./btrfsck /dev/sdc5
>> ==31620== Memcheck, a memory error detector
>> ==31620== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
>> ==31620== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright
>> info
>> ==31620== Command: ./btrfsck /dev/sdc5
>> ==31620==
>> Checking filesystem on /dev/sdc5
>> UUID: ab91fc96-549b-4048-a68b-73c5190e6265
>> checking extents
>> checking free space cache
>> checking fs roots
>> ==31620== Invalid read of size 8
>> ==31620==    at 0x4C257C3: rb_first (rbtree.c:420)
>> ==31620==    by 0x41E609: first_extent_gap (cmds-check.c:182)
>> ==31620==    by 0x427D43: merge_inode_recs (cmds-check.c:950)
>> ==31620==    by 0x42827B: splice_shared_node (cmds-check.c:1032)
>> ==31620==    by 0x428827: enter_shared_node (cmds-check.c:1138)
>> ==31620==    by 0x428BCF: walk_down_tree (cmds-check.c:1745)
>> ==31620==    by 0x42CA64: check_fs_root (cmds-check.c:3360)
>> ==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
>> ==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
>> ==31620==    by 0x40C089: main (btrfs.c:245)
>> ==31620==  Address 0x4e5dc60 is 16 bytes inside a block of size 40 free'd
>> ==31620==    at 0x4A063F0: free (vg_replace_malloc.c:446)
>> ==31620==    by 0x421887: free_file_extent_holes (cmds-check.c:359)
>> ==31620==    by 0x4218FB: free_inode_rec (cmds-check.c:718)
>> ==31620==    by 0x42753E: maybe_free_inode_rec (cmds-check.c:786)
>> ==31620==    by 0x4282A5: splice_shared_node (cmds-check.c:1038)
>> ==31620==    by 0x42849E: leave_shared_node (cmds-check.c:1170)
>> ==31620==    by 0x42869F: walk_up_tree (cmds-check.c:1817)
>> ==31620==    by 0x42CA82: check_fs_root (cmds-check.c:3366)
>> ==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
>> ==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
>> ==31620==    by 0x40C089: main (btrfs.c:245)
>> ==31620==
>> ==31620== Invalid read of size 8
>> ==31620==    at 0x41E60A: first_extent_gap (cmds-check.c:183)
>> ==31620==    by 0x427D43: merge_inode_recs (cmds-check.c:950)
>> ==31620==    by 0x42827B: splice_shared_node (cmds-check.c:1032)
>> ==31620==    by 0x428827: enter_shared_node (cmds-check.c:1138)
>> ==31620==    by 0x428BCF: walk_down_tree (cmds-check.c:1745)
>> ==31620==    by 0x42CA64: check_fs_root (cmds-check.c:3360)
>> ==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
>> ==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
>> ==31620==    by 0x40C089: main (btrfs.c:245)
>> ==31620==  Address 0x4e5dc68 is 24 bytes inside a block of size 40 free'd
>> ==31620==    at 0x4A063F0: free (vg_replace_malloc.c:446)
>> ==31620==    by 0x421887: free_file_extent_holes (cmds-check.c:359)
>> ==31620==    by 0x4218FB: free_inode_rec (cmds-check.c:718)
>> ==31620==    by 0x42753E: maybe_free_inode_rec (cmds-check.c:786)
>> ==31620==    by 0x4282A5: splice_shared_node (cmds-check.c:1038)
>> ==31620==    by 0x42849E: leave_shared_node (cmds-check.c:1170)
>> ==31620==    by 0x42869F: walk_up_tree (cmds-check.c:1817)
>> ==31620==    by 0x42CA82: check_fs_root (cmds-check.c:3366)
>> ==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
>> ==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
>> ==31620==    by 0x40C089: main (btrfs.c:245)
>> ==31620==
>> ==31620== Invalid read of size 8
>> ==31620==    at 0x4C257C3: rb_first (rbtree.c:420)
>> ==31620==    by 0x41E609: first_extent_gap (cmds-check.c:182)
>> ==31620==    by 0x427421: maybe_free_inode_rec (cmds-check.c:768)
>> ==31620==    by 0x4282A5: splice_shared_node (cmds-check.c:1038)
>> ==31620==    by 0x428827: enter_shared_node (cmds-check.c:1138)
>> ==31620==    by 0x428BCF: walk_down_tree (cmds-check.c:1745)
>> ==31620==    by 0x42CA64: check_fs_root (cmds-check.c:3360)
>> ==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
>> ==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
>> ==31620==    by 0x40C089: main (btrfs.c:245)
>> ==31620==  Address 0x4e5dc60 is 16 bytes inside a block of size 40 free'd
>> ==31620==    at 0x4A063F0: free (vg_replace_malloc.c:446)
>> ==31620==    by 0x421887: free_file_extent_holes (cmds-check.c:359)
>> ==31620==    by 0x4218FB: free_inode_rec (cmds-check.c:718)
>> ==31620==    by 0x42753E: maybe_free_inode_rec (cmds-check.c:786)
>> ==31620==    by 0x4282A5: splice_shared_node (cmds-check.c:1038)
>> ==31620==    by 0x42849E: leave_shared_node (cmds-check.c:1170)
>> ==31620==    by 0x42869F: walk_up_tree (cmds-check.c:1817)
>> ==31620==    by 0x42CA82: check_fs_root (cmds-check.c:3366)
>> ==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
>> ==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
>> ==31620==    by 0x40C089: main (btrfs.c:245)
>> ==31620==
>> ==31620== Invalid read of size 8
>> ==31620==    at 0x41E60A: first_extent_gap (cmds-check.c:183)
>> ==31620==    by 0x427421: maybe_free_inode_rec (cmds-check.c:768)
>> ==31620==    by 0x4282A5: splice_shared_node (cmds-check.c:1038)
>> ==31620==    by 0x428827: enter_shared_node (cmds-check.c:1138)
>> ==31620==    by 0x428BCF: walk_down_tree (cmds-check.c:1745)
>> ==31620==    by 0x42CA64: check_fs_root (cmds-check.c:3360)
>> ==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
>> ==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
>> ==31620==    by 0x40C089: main (btrfs.c:245)
>> ==31620==  Address 0x4e5dc68 is 24 bytes inside a block of size 40 free'd
>> ==31620==    at 0x4A063F0: free (vg_replace_malloc.c:446)
>> ==31620==    by 0x421887: free_file_extent_holes (cmds-check.c:359)
>> ==31620==    by 0x4218FB: free_inode_rec (cmds-check.c:718)
>> ==31620==    by 0x42753E: maybe_free_inode_rec (cmds-check.c:786)
>> ==31620==    by 0x4282A5: splice_shared_node (cmds-check.c:1038)
>> ==31620==    by 0x42849E: leave_shared_node (cmds-check.c:1170)
>> ==31620==    by 0x42869F: walk_up_tree (cmds-check.c:1817)
>> ==31620==    by 0x42CA82: check_fs_root (cmds-check.c:3366)
>> ==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
>> ==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
>> ==31620==    by 0x40C089: main (btrfs.c:245)
>> ==31620==
>> ==31620== Invalid read of size 8
>> ==31620==    at 0x4C257C3: rb_first (rbtree.c:420)
>> ==31620==    by 0x42186C: free_file_extent_holes (cmds-check.c:355)
>> ==31620==    by 0x4218FB: free_inode_rec (cmds-check.c:718)
>> ==31620==    by 0x42753E: maybe_free_inode_rec (cmds-check.c:786)
>> ==31620==    by 0x4282A5: splice_shared_node (cmds-check.c:1038)
>> ==31620==    by 0x428827: enter_shared_node (cmds-check.c:1138)
>> ==31620==    by 0x428BCF: walk_down_tree (cmds-check.c:1745)
>> ==31620==    by 0x42CA64: check_fs_root (cmds-check.c:3360)
>> ==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
>> ==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
>> ==31620==    by 0x40C089: main (btrfs.c:245)
>> ==31620==  Address 0x4e5dc60 is 16 bytes inside a block of size 40 free'd
>> ==31620==    at 0x4A063F0: free (vg_replace_malloc.c:446)
>> ==31620==    by 0x421887: free_file_extent_holes (cmds-check.c:359)
>> ==31620==    by 0x4218FB: free_inode_rec (cmds-check.c:718)
>> ==31620==    by 0x42753E: maybe_free_inode_rec (cmds-check.c:786)
>> ==31620==    by 0x4282A5: splice_shared_node (cmds-check.c:1038)
>> ==31620==    by 0x42849E: leave_shared_node (cmds-check.c:1170)
>> ==31620==    by 0x42869F: walk_up_tree (cmds-check.c:1817)
>> ==31620==    by 0x42CA82: check_fs_root (cmds-check.c:3366)
>> ==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
>> ==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
>> ==31620==    by 0x40C089: main (btrfs.c:245)
>>
>> ... etc ...
>>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html



-- 
Filipe David Manana,

"Reasonable men adapt themselves to the world.
 Unreasonable men adapt the world to themselves.
 That's why all progress depends on unreasonable men."

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v2 3/5] btrfs-progs: Record and report every file extent hole.
  2015-05-02 16:36       ` Filipe David Manana
@ 2015-05-05  0:55         ` Qu Wenruo
  0 siblings, 0 replies; 10+ messages in thread
From: Qu Wenruo @ 2015-05-05  0:55 UTC (permalink / raw)
  To: fdmanana; +Cc: Eric Sandeen, linux-btrfs

Sorry, I was busy making another patchset for offline fsid/chunk tree 
uuid change, and didn't have time investigating it.

But now the patchset is finished and I'll begin investigate it.

Thanks for your valgrind output.
Qu

-------- Original Message  --------
Subject: Re: [PATCH v2 3/5] btrfs-progs: Record and report every file 
extent hole.
From: Filipe David Manana <fdmanana@gmail.com>
To: Qu Wenruo <quwenruo@cn.fujitsu.com>
Date: 2015年05月03日 00:36

> On Wed, Mar 25, 2015 at 3:36 AM, Qu Wenruo <quwenruo@cn.fujitsu.com> wrote:
>> Thanks, I'll investigate it soon.
>>
>> Thanks,
>> Qu
>
> Qu, did you end up finding anything?
>
> Just upgraded to btrfs-progs 4.0 and getting pretty much the same as
> Eric all the time I run btrfs/078.
> Valgrind should give you some nice clues.
>
> E.g.
>
> (...)
> checking free space cache
> checking fs roots
> ==11808== Invalid read of size 8
> ==11808==    at 0x4611C2: rb_first (rbtree.c:420)
> ==11808==    by 0x41B694: first_extent_gap (cmds-check.c:184)
> ==11808==    by 0x42020E: merge_inode_recs (cmds-check.c:954)
> ==11808==    by 0x42020E: splice_shared_node (cmds-check.c:1036)
> ==11808==    by 0x4205B8: enter_shared_node (cmds-check.c:1142)
> ==11808==    by 0x420F6E: walk_down_tree (cmds-check.c:1758)
> ==11808==    by 0x429555: check_fs_root (cmds-check.c:3382)
> ==11808==    by 0x429555: check_fs_roots (cmds-check.c:3518)
> ==11808==    by 0x429555: cmd_check (cmds-check.c:9465)
> ==11808==    by 0x409BEC: main (btrfs.c:245)
> ==11808==  Address 0x6057d10 is 16 bytes inside a block of size 40 free'd
> ==11808==    at 0x4C29E90: free (vg_replace_malloc.c:473)
> ==11808==    by 0x41C118: free_file_extent_holes (cmds-check.c:363)
> ==11808==    by 0x41C118: free_inode_rec (cmds-check.c:722)
> ==11808==    by 0x41F9CA: maybe_free_inode_rec (cmds-check.c:790)
> ==11808==    by 0x42036C: splice_shared_node (cmds-check.c:1042)
> ==11808==    by 0x4205B8: enter_shared_node (cmds-check.c:1142)
> ==11808==    by 0x420F6E: walk_down_tree (cmds-check.c:1758)
> ==11808==    by 0x429555: check_fs_root (cmds-check.c:3382)
> ==11808==    by 0x429555: check_fs_roots (cmds-check.c:3518)
> ==11808==    by 0x429555: cmd_check (cmds-check.c:9465)
> ==11808==    by 0x409BEC: main (btrfs.c:245)
> ==11808==
> ==11808==
> ==11808== Process terminating with default action of signal 11 (SIGSEGV)
> ==11808==  General Protection Fault
> ==11808==    at 0x4611C2: rb_first (rbtree.c:420)
> ==11808==    by 0x41B694: first_extent_gap (cmds-check.c:184)
> ==11808==    by 0x42020E: merge_inode_recs (cmds-check.c:954)
> ==11808==    by 0x42020E: splice_shared_node (cmds-check.c:1036)
> ==11808==    by 0x4205B8: enter_shared_node (cmds-check.c:1142)
> ==11808==    by 0x420F6E: walk_down_tree (cmds-check.c:1758)
> ==11808==    by 0x429555: check_fs_root (cmds-check.c:3382)
> ==11808==    by 0x429555: check_fs_roots (cmds-check.c:3518)
> ==11808==    by 0x429555: cmd_check (cmds-check.c:9465)
> ==11808==    by 0x409BEC: main (btrfs.c:245)
> (....)
>
> Thanks.
>
>
>>
>>
>>> On 1/2/15 1:12 AM, Qu Wenruo wrote:
>>>>
>>>> Record every file extent discontinuous hole in inode_record using a
>>>> rb_tree member.
>>>>
>>>> Before the patch, btrfsck will only record the first file extent hole by
>>>> using first_extent_gap, that's good for detecting error, but not
>>>> suitable for fixing it.
>>>>
>>>> This patch provides the ability to record every file extent hole and
>>>> report it.
>>>
>>>
>>> This is causing use after free and segfaults in my testing, running
>>> xfstests btrfs/078 with multiple devices defined:
>>>
>>> SCRATCH_DEV_POOL="/dev/sdc5 /dev/sdc6 /dev/sdc7 /dev/sdc8 /dev/sdc9
>>> /dev/sdc10 /dev/sdc11 /dev/sdc12"
>>>
>>> -Eric
>>>
>>> # valgrind ./btrfsck /dev/sdc5
>>> ==31620== Memcheck, a memory error detector
>>> ==31620== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
>>> ==31620== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright
>>> info
>>> ==31620== Command: ./btrfsck /dev/sdc5
>>> ==31620==
>>> Checking filesystem on /dev/sdc5
>>> UUID: ab91fc96-549b-4048-a68b-73c5190e6265
>>> checking extents
>>> checking free space cache
>>> checking fs roots
>>> ==31620== Invalid read of size 8
>>> ==31620==    at 0x4C257C3: rb_first (rbtree.c:420)
>>> ==31620==    by 0x41E609: first_extent_gap (cmds-check.c:182)
>>> ==31620==    by 0x427D43: merge_inode_recs (cmds-check.c:950)
>>> ==31620==    by 0x42827B: splice_shared_node (cmds-check.c:1032)
>>> ==31620==    by 0x428827: enter_shared_node (cmds-check.c:1138)
>>> ==31620==    by 0x428BCF: walk_down_tree (cmds-check.c:1745)
>>> ==31620==    by 0x42CA64: check_fs_root (cmds-check.c:3360)
>>> ==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
>>> ==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
>>> ==31620==    by 0x40C089: main (btrfs.c:245)
>>> ==31620==  Address 0x4e5dc60 is 16 bytes inside a block of size 40 free'd
>>> ==31620==    at 0x4A063F0: free (vg_replace_malloc.c:446)
>>> ==31620==    by 0x421887: free_file_extent_holes (cmds-check.c:359)
>>> ==31620==    by 0x4218FB: free_inode_rec (cmds-check.c:718)
>>> ==31620==    by 0x42753E: maybe_free_inode_rec (cmds-check.c:786)
>>> ==31620==    by 0x4282A5: splice_shared_node (cmds-check.c:1038)
>>> ==31620==    by 0x42849E: leave_shared_node (cmds-check.c:1170)
>>> ==31620==    by 0x42869F: walk_up_tree (cmds-check.c:1817)
>>> ==31620==    by 0x42CA82: check_fs_root (cmds-check.c:3366)
>>> ==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
>>> ==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
>>> ==31620==    by 0x40C089: main (btrfs.c:245)
>>> ==31620==
>>> ==31620== Invalid read of size 8
>>> ==31620==    at 0x41E60A: first_extent_gap (cmds-check.c:183)
>>> ==31620==    by 0x427D43: merge_inode_recs (cmds-check.c:950)
>>> ==31620==    by 0x42827B: splice_shared_node (cmds-check.c:1032)
>>> ==31620==    by 0x428827: enter_shared_node (cmds-check.c:1138)
>>> ==31620==    by 0x428BCF: walk_down_tree (cmds-check.c:1745)
>>> ==31620==    by 0x42CA64: check_fs_root (cmds-check.c:3360)
>>> ==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
>>> ==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
>>> ==31620==    by 0x40C089: main (btrfs.c:245)
>>> ==31620==  Address 0x4e5dc68 is 24 bytes inside a block of size 40 free'd
>>> ==31620==    at 0x4A063F0: free (vg_replace_malloc.c:446)
>>> ==31620==    by 0x421887: free_file_extent_holes (cmds-check.c:359)
>>> ==31620==    by 0x4218FB: free_inode_rec (cmds-check.c:718)
>>> ==31620==    by 0x42753E: maybe_free_inode_rec (cmds-check.c:786)
>>> ==31620==    by 0x4282A5: splice_shared_node (cmds-check.c:1038)
>>> ==31620==    by 0x42849E: leave_shared_node (cmds-check.c:1170)
>>> ==31620==    by 0x42869F: walk_up_tree (cmds-check.c:1817)
>>> ==31620==    by 0x42CA82: check_fs_root (cmds-check.c:3366)
>>> ==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
>>> ==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
>>> ==31620==    by 0x40C089: main (btrfs.c:245)
>>> ==31620==
>>> ==31620== Invalid read of size 8
>>> ==31620==    at 0x4C257C3: rb_first (rbtree.c:420)
>>> ==31620==    by 0x41E609: first_extent_gap (cmds-check.c:182)
>>> ==31620==    by 0x427421: maybe_free_inode_rec (cmds-check.c:768)
>>> ==31620==    by 0x4282A5: splice_shared_node (cmds-check.c:1038)
>>> ==31620==    by 0x428827: enter_shared_node (cmds-check.c:1138)
>>> ==31620==    by 0x428BCF: walk_down_tree (cmds-check.c:1745)
>>> ==31620==    by 0x42CA64: check_fs_root (cmds-check.c:3360)
>>> ==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
>>> ==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
>>> ==31620==    by 0x40C089: main (btrfs.c:245)
>>> ==31620==  Address 0x4e5dc60 is 16 bytes inside a block of size 40 free'd
>>> ==31620==    at 0x4A063F0: free (vg_replace_malloc.c:446)
>>> ==31620==    by 0x421887: free_file_extent_holes (cmds-check.c:359)
>>> ==31620==    by 0x4218FB: free_inode_rec (cmds-check.c:718)
>>> ==31620==    by 0x42753E: maybe_free_inode_rec (cmds-check.c:786)
>>> ==31620==    by 0x4282A5: splice_shared_node (cmds-check.c:1038)
>>> ==31620==    by 0x42849E: leave_shared_node (cmds-check.c:1170)
>>> ==31620==    by 0x42869F: walk_up_tree (cmds-check.c:1817)
>>> ==31620==    by 0x42CA82: check_fs_root (cmds-check.c:3366)
>>> ==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
>>> ==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
>>> ==31620==    by 0x40C089: main (btrfs.c:245)
>>> ==31620==
>>> ==31620== Invalid read of size 8
>>> ==31620==    at 0x41E60A: first_extent_gap (cmds-check.c:183)
>>> ==31620==    by 0x427421: maybe_free_inode_rec (cmds-check.c:768)
>>> ==31620==    by 0x4282A5: splice_shared_node (cmds-check.c:1038)
>>> ==31620==    by 0x428827: enter_shared_node (cmds-check.c:1138)
>>> ==31620==    by 0x428BCF: walk_down_tree (cmds-check.c:1745)
>>> ==31620==    by 0x42CA64: check_fs_root (cmds-check.c:3360)
>>> ==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
>>> ==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
>>> ==31620==    by 0x40C089: main (btrfs.c:245)
>>> ==31620==  Address 0x4e5dc68 is 24 bytes inside a block of size 40 free'd
>>> ==31620==    at 0x4A063F0: free (vg_replace_malloc.c:446)
>>> ==31620==    by 0x421887: free_file_extent_holes (cmds-check.c:359)
>>> ==31620==    by 0x4218FB: free_inode_rec (cmds-check.c:718)
>>> ==31620==    by 0x42753E: maybe_free_inode_rec (cmds-check.c:786)
>>> ==31620==    by 0x4282A5: splice_shared_node (cmds-check.c:1038)
>>> ==31620==    by 0x42849E: leave_shared_node (cmds-check.c:1170)
>>> ==31620==    by 0x42869F: walk_up_tree (cmds-check.c:1817)
>>> ==31620==    by 0x42CA82: check_fs_root (cmds-check.c:3366)
>>> ==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
>>> ==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
>>> ==31620==    by 0x40C089: main (btrfs.c:245)
>>> ==31620==
>>> ==31620== Invalid read of size 8
>>> ==31620==    at 0x4C257C3: rb_first (rbtree.c:420)
>>> ==31620==    by 0x42186C: free_file_extent_holes (cmds-check.c:355)
>>> ==31620==    by 0x4218FB: free_inode_rec (cmds-check.c:718)
>>> ==31620==    by 0x42753E: maybe_free_inode_rec (cmds-check.c:786)
>>> ==31620==    by 0x4282A5: splice_shared_node (cmds-check.c:1038)
>>> ==31620==    by 0x428827: enter_shared_node (cmds-check.c:1138)
>>> ==31620==    by 0x428BCF: walk_down_tree (cmds-check.c:1745)
>>> ==31620==    by 0x42CA64: check_fs_root (cmds-check.c:3360)
>>> ==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
>>> ==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
>>> ==31620==    by 0x40C089: main (btrfs.c:245)
>>> ==31620==  Address 0x4e5dc60 is 16 bytes inside a block of size 40 free'd
>>> ==31620==    at 0x4A063F0: free (vg_replace_malloc.c:446)
>>> ==31620==    by 0x421887: free_file_extent_holes (cmds-check.c:359)
>>> ==31620==    by 0x4218FB: free_inode_rec (cmds-check.c:718)
>>> ==31620==    by 0x42753E: maybe_free_inode_rec (cmds-check.c:786)
>>> ==31620==    by 0x4282A5: splice_shared_node (cmds-check.c:1038)
>>> ==31620==    by 0x42849E: leave_shared_node (cmds-check.c:1170)
>>> ==31620==    by 0x42869F: walk_up_tree (cmds-check.c:1817)
>>> ==31620==    by 0x42CA82: check_fs_root (cmds-check.c:3366)
>>> ==31620==    by 0x42CE2D: check_fs_roots (cmds-check.c:3496)
>>> ==31620==    by 0x42E342: cmd_check (cmds-check.c:9161)
>>> ==31620==    by 0x40C089: main (btrfs.c:245)
>>>
>>> ... etc ...
>>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>
>
>

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2015-05-05  0:55 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-01-02  7:12 [PATCH v2 1/5] btrfs-progs: Record orphan data extent ref to corresponding root Qu Wenruo
2015-01-02  7:12 ` [PATCH v2 2/5] btrfs-progs: Add btrfs_get_extent() and btrfs_punch_hole() Qu Wenruo
2015-01-02  7:12 ` [PATCH v2 3/5] btrfs-progs: Record and report every file extent hole Qu Wenruo
2015-03-25  3:05   ` Eric Sandeen
2015-03-25  3:36     ` Qu Wenruo
2015-05-02 16:36       ` Filipe David Manana
2015-05-05  0:55         ` Qu Wenruo
2015-01-02  7:12 ` [PATCH v2 4/5] btrfs-progs: Add repair and report function for orphan file extent Qu Wenruo
2015-01-02  7:12 ` [PATCH v2 5/5] btrfs-progs: Add repair function for discount file extent hole Qu Wenruo
2015-02-02 13:43 ` [PATCH v2 1/5] btrfs-progs: Record orphan data extent ref to corresponding root David Sterba

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.