btrfsprogs/0145-Btrfs-progs-make-specifying-root-objectid-work-if-th.patch

171 lines
4.6 KiB
Diff
Raw Normal View History

From 87edb6fbf4991e47e7563c4589197aa88befe266 Mon Sep 17 00:00:00 2001
From: Josef Bacik <josef@redhat.com>
Date: Wed, 4 Jan 2012 11:50:55 -0500
Subject: [PATCH 42/43] Btrfs-progs: make specifying root objectid work if the
fs is broken
We need to be able to handle the case where we want to restore from a specific
root if the fs is really really really toast, this patch does that. Thanks,
Signed-off-by: Josef Bacik <josef@redhat.com>
---
restore.c | 109 +++++++++++++++++++++++++++++++++++++++----------------------
1 files changed, 70 insertions(+), 39 deletions(-)
diff --git a/restore.c b/restore.c
index abc66ca..5aa35ae 100644
--- a/restore.c
+++ b/restore.c
@@ -837,7 +837,35 @@ static int do_list_roots(struct btrfs_root *root)
return 0;
}
-static struct btrfs_root *open_fs(const char *dev, u64 root_location, int super_mirror, int list_roots)
+static int __setup_root(u32 nodesize, u32 leafsize, u32 sectorsize,
+ u32 stripesize, struct btrfs_root *root,
+ struct btrfs_fs_info *fs_info, u64 objectid)
+{
+ root->node = NULL;
+ root->commit_root = NULL;
+ root->sectorsize = sectorsize;
+ root->nodesize = nodesize;
+ root->leafsize = leafsize;
+ root->stripesize = stripesize;
+ root->ref_cows = 0;
+ root->track_dirty = 0;
+
+ root->fs_info = fs_info;
+ root->objectid = objectid;
+ root->last_trans = 0;
+ root->highest_inode = 0;
+ root->last_inode_alloc = 0;
+
+ INIT_LIST_HEAD(&root->dirty_list);
+ memset(&root->root_key, 0, sizeof(root->root_key));
+ memset(&root->root_item, 0, sizeof(root->root_item));
+ root->root_key.objectid = objectid;
+ return 0;
+}
+
+static struct btrfs_root *open_fs(const char *dev, u64 root_location,
+ u64 fs_location, u64 root_objectid,
+ int super_mirror, int list_roots)
{
struct btrfs_key key;
struct btrfs_root *root;
@@ -889,23 +917,51 @@ static struct btrfs_root *open_fs(const char *dev, u64 root_location, int super_
if (list_roots)
goto out;
- key.objectid = BTRFS_FS_TREE_OBJECTID;
- key.type = BTRFS_ROOT_ITEM_KEY;
- key.offset = (u64)-1;
+ if (!root_objectid)
+ root_objectid = BTRFS_FS_TREE_OBJECTID;
- root->fs_info->fs_root = btrfs_read_fs_root_no_cache(root->fs_info, &key);
- if (IS_ERR(root->fs_info->fs_root)) {
- fprintf(stderr, "Couldn't read fs_root: %d\n",
- PTR_ERR(root->fs_info->fs_root));
- close_ctree(root);
- return NULL;
- }
out:
+ if (fs_location) {
+ struct btrfs_root *fs_root = root->fs_info->fs_root;
+ if (fs_root) {
+ free_extent_buffer(fs_root->node);
+ } else {
+ fs_root = malloc(sizeof(struct btrfs_root));
+ if (!fs_root) {
+ fprintf(stderr, "Out of memory\n");
+ close_ctree(root);
+ return NULL;
+ }
+ __setup_root(4096, 4096, 4096, 4096, fs_root,
+ root->fs_info, root_objectid);
+ root->fs_info->fs_root = fs_root;
+ }
+ fs_root->node = read_tree_block(root, fs_location, 4096, 0);
+ if (!fs_root->node) {
+ fprintf(stderr, "Failed to read fs location\n");
+ close_ctree(root);
+ return NULL;
+ }
+ } else if (root_objectid) {
+ key.objectid = root_objectid;
+ key.type = BTRFS_ROOT_ITEM_KEY;
+ key.offset = (u64)-1;
+
+ root->fs_info->fs_root =
+ btrfs_read_fs_root_no_cache(root->fs_info, &key);
+ if (IS_ERR(root->fs_info->fs_root)) {
+ fprintf(stderr, "Error reading fs root %d\n",
+ PTR_ERR(root->fs_info->fs_root));
+ close_ctree(root);
+ return NULL;
+ }
+ }
+
if (list_roots) {
int ret = do_list_roots(root);
if (ret) {
- root = NULL;
close_ctree(root);
+ return NULL;
}
}
@@ -1074,22 +1130,14 @@ int main(int argc, char **argv)
return -EBUSY;
}
- root = open_fs(argv[optind], tree_location, super_mirror, list_roots);
+ root = open_fs(argv[optind], tree_location, fs_location, root_objectid,
+ super_mirror, list_roots);
if (root == NULL)
return 1;
if (list_roots)
goto out;
- if (fs_location != 0) {
- free_extent_buffer(root->node);
- root->node = read_tree_block(root, fs_location, 4096, 0);
- if (!root->node) {
- fprintf(stderr, "Failed to read fs location\n");
- goto out;
- }
- }
-
memset(path_name, 0, 4096);
strncpy(dir_name, argv[optind + 1], 128);
@@ -1102,23 +1150,6 @@ int main(int argc, char **argv)
dir_name[len - 1] = '\0';
}
- if (root_objectid != 0) {
- struct btrfs_root *orig_root = root;
-
- key.objectid = root_objectid;
- key.type = BTRFS_ROOT_ITEM_KEY;
- key.offset = (u64)-1;
- root = btrfs_read_fs_root(orig_root->fs_info, &key);
- if (IS_ERR(root)) {
- fprintf(stderr, "Error reading root\n");
- root = orig_root;
- ret = 1;
- goto out;
- }
- key.type = 0;
- key.offset = 0;
- }
-
if (find_dir) {
ret = find_first_dir(root, &key.objectid);
if (ret)
--
1.7.6.233.gd79bc