From 87edb6fbf4991e47e7563c4589197aa88befe266 Mon Sep 17 00:00:00 2001 From: Josef Bacik 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 --- 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