diff mbox series

[4/7] btrfs-progs: properly populate missing trees

Message ID 0acd92a3b95f21b89e249fdf2f78e914b6b9c1c0.1645567860.git.josef@toxicpanda.com (mailing list archive)
State New, archived
Headers show
Series btrfs-progs: various regression fixes | expand

Commit Message

Josef Bacik Feb. 22, 2022, 10:22 p.m. UTC
With my global roots prep patches I regressed us on handling the case
where we didn't find a root at all.  In this case we need to return an
error (prior we returned -ENOENT) or we need to populate a dummy tree if
we have OPEN_CTREE_PARTIAL set.  This fixes a segfault of fuzz test 006.

Signed-off-by: Josef Bacik <josef@toxicpanda.com>
---
 kernel-shared/disk-io.c | 43 +++++++++++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

Comments

David Sterba March 4, 2022, 10:18 p.m. UTC | #1
On Tue, Feb 22, 2022 at 05:22:39PM -0500, Josef Bacik wrote:
> With my global roots prep patches I regressed us on handling the case
> where we didn't find a root at all.  In this case we need to return an
> error (prior we returned -ENOENT) or we need to populate a dummy tree if
> we have OPEN_CTREE_PARTIAL set.  This fixes a segfault of fuzz test 006.

This unfortunatelly breaks test fsck/001-bad-file-extent-bytenr, seems
that the image can't be properly restored before the test starts.
David Sterba March 8, 2022, 5:26 p.m. UTC | #2
On Fri, Mar 04, 2022 at 11:18:29PM +0100, David Sterba wrote:
> On Tue, Feb 22, 2022 at 05:22:39PM -0500, Josef Bacik wrote:
> > With my global roots prep patches I regressed us on handling the case
> > where we didn't find a root at all.  In this case we need to return an
> > error (prior we returned -ENOENT) or we need to populate a dummy tree if
> > we have OPEN_CTREE_PARTIAL set.  This fixes a segfault of fuzz test 006.
> 
> This unfortunatelly breaks test fsck/001-bad-file-extent-bytenr, seems
> that the image can't be properly restored before the test starts.

Fixed by reordering patches.
diff mbox series

Patch

diff --git a/kernel-shared/disk-io.c b/kernel-shared/disk-io.c
index e7eab1a1..1cd965aa 100644
--- a/kernel-shared/disk-io.c
+++ b/kernel-shared/disk-io.c
@@ -1059,6 +1059,7 @@  static int load_global_roots_objectid(struct btrfs_fs_info *fs_info,
 	struct btrfs_root *tree_root = fs_info->tree_root;
 	struct btrfs_root *root;
 	int ret;
+	int found = 0;
 	struct btrfs_key key = {
 		.objectid = objectid,
 		.type = BTRFS_ROOT_ITEM_KEY,
@@ -1124,9 +1125,51 @@  static int load_global_roots_objectid(struct btrfs_fs_info *fs_info,
 			break;
 		}
 
+		found++;
 		path->slots[0]++;
 	}
 	btrfs_release_path(path);
+
+	/*
+	 * We didn't find all of our roots, create empty ones if we have PARTIAL
+	 * set.
+	 */
+	if (!ret && found < fs_info->nr_global_roots) {
+		int i;
+
+		if (!(flags & OPEN_CTREE_PARTIAL)) {
+			error("could not setup %s tree", str);
+			return -EIO;
+		}
+
+		warning("could not setup %s tree, skipping it", str);
+		for (i = found; i < fs_info->nr_global_roots; i++) {
+			root = calloc(1, sizeof(*root));
+			if (!root) {
+				ret = -ENOMEM;
+				break;
+			}
+			btrfs_setup_root(root, fs_info, objectid);
+			root->root_key.objectid = objectid;
+			root->root_key.type = BTRFS_ROOT_ITEM_KEY;
+			root->root_key.offset = i;
+			root->track_dirty = 1;
+			root->node = btrfs_find_create_tree_block(fs_info, 0);
+			if (!root->node) {
+				free(root);
+				ret = -ENOMEM;
+				break;
+			}
+			clear_extent_buffer_uptodate(root->node);
+			ret = btrfs_global_root_insert(fs_info, root);
+			if (ret) {
+				free_extent_buffer(root->node);
+				free(root);
+				break;
+			}
+		}
+	}
+
 	return ret;
 }