Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
Please login to access the resource
home:lafenghu
btrfsprogs
0134-Btrfs-progs-give-restore-a-list-roots-opti...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 0134-Btrfs-progs-give-restore-a-list-roots-option.patch of Package btrfsprogs
From 9bb7aa76e43f4942f5fa398bf00778067859f66c Mon Sep 17 00:00:00 2001 From: Josef Bacik <josef@redhat.com> Date: Fri, 9 Dec 2011 14:09:18 -0500 Subject: [PATCH 35/35] Btrfs-progs: give restore a list roots option Since restore has the ability to open really really screwed up file systems, add a list roots option to it so we can still get the contents of the tree root on a horribly broken fs. Thanks, Signed-off-by: Josef Bacik <josef@redhat.com> --- restore.c | 95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 files changed, 88 insertions(+), 7 deletions(-) diff --git a/restore.c b/restore.c index 398c49a..95daef2 100644 --- a/restore.c +++ b/restore.c @@ -773,11 +773,71 @@ next: static void usage() { - fprintf(stderr, "Usage: restore [-svioc] [-t disk offset] " + fprintf(stderr, "Usage: restore [-sviocl] [-t disk offset] " "[-m regex] <device> <directory>\n"); } -static struct btrfs_root *open_fs(const char *dev, u64 root_location, int super_mirror) +static int do_list_roots(struct btrfs_root *root) +{ + struct btrfs_key key; + struct btrfs_key found_key; + struct btrfs_disk_key disk_key; + struct btrfs_path *path; + struct extent_buffer *leaf; + struct btrfs_root_item ri; + unsigned long offset; + int slot; + int ret; + + root = root->fs_info->tree_root; + path = btrfs_alloc_path(); + if (!path) { + fprintf(stderr, "Failed to alloc path\n"); + return -1; + } + + key.offset = 0; + key.objectid = 0; + key.type = BTRFS_ROOT_ITEM_KEY; + + ret = btrfs_search_slot(NULL, root, &key, path, 0, 0); + if (ret < 0) { + fprintf(stderr, "Failed to do search %d\n", ret); + btrfs_free_path(path); + return -1; + } + + while (1) { + leaf = path->nodes[0]; + slot = path->slots[0]; + if (slot >= btrfs_header_nritems(leaf)) { + ret = btrfs_next_leaf(root, path); + if (ret) + break; + leaf = path->nodes[0]; + slot = path->slots[0]; + } + btrfs_item_key(leaf, &disk_key, slot); + btrfs_disk_key_to_cpu(&found_key, &disk_key); + if (btrfs_key_type(&found_key) != BTRFS_ROOT_ITEM_KEY) { + path->slots[0]++; + continue; + } + + offset = btrfs_item_ptr_offset(leaf, slot); + read_extent_buffer(leaf, &ri, offset, sizeof(ri)); + printf(" tree "); + btrfs_print_key(&disk_key); + printf(" %Lu level %d\n", btrfs_root_bytenr(&ri), + btrfs_root_level(&ri)); + path->slots[0]++; + } + btrfs_free_path(path); + + return 0; +} + +static struct btrfs_root *open_fs(const char *dev, u64 root_location, int super_mirror, int list_roots) { struct btrfs_key key; struct btrfs_root *root; @@ -791,7 +851,7 @@ static struct btrfs_root *open_fs(const char *dev, u64 root_location, int super_ bytenr = btrfs_sb_offset(i); root = open_ctree_recovery(dev, bytenr, root_location); if (root) - return root; + goto out; fprintf(stderr, "Could not open root, trying backup super\n"); } @@ -826,16 +886,27 @@ static struct btrfs_root *open_fs(const char *dev, u64 root_location, int super_ return NULL; } + if (list_roots) + goto out; + key.objectid = BTRFS_FS_TREE_OBJECTID; key.type = BTRFS_ROOT_ITEM_KEY; key.offset = (u64)-1; root->fs_info->fs_root = btrfs_read_fs_root(root->fs_info, &key); if (IS_ERR(root->fs_info->fs_root)) { - fprintf(stderr, "Couldn't read fs_root: %d\n", PTR_ERR(root)); + fprintf(stderr, "Couldn't read fs_root: %ld\n", PTR_ERR(root)); close_ctree(root); return NULL; } +out: + if (list_roots) { + int ret = do_list_roots(root); + if (ret) { + root = NULL; + close_ctree(root); + } + } return root->fs_info->fs_root; } @@ -917,8 +988,9 @@ int main(int argc, char **argv) int match_cflags = REG_EXTENDED | REG_NOSUB | REG_NEWLINE; regex_t match_reg, *mreg = NULL; char reg_err[256]; + int list_roots = 0; - while ((opt = getopt(argc, argv, "sviot:u:df:r:cm:")) != -1) { + while ((opt = getopt(argc, argv, "sviot:u:df:r:cm:l")) != -1) { switch (opt) { case 's': get_snaps = 1; @@ -975,13 +1047,19 @@ int main(int argc, char **argv) case 'm': match_regstr = optarg; break; + case 'l': + list_roots = 1; + break; default: usage(); exit(1); } } - if (optind + 1 >= argc) { + if (!list_roots && optind + 1 >= argc) { + usage(); + exit(1); + } else if (list_roots && optind >= argc) { usage(); exit(1); } @@ -995,10 +1073,13 @@ int main(int argc, char **argv) return -EBUSY; } - root = open_fs(argv[optind], tree_location, super_mirror); + root = open_fs(argv[optind], tree_location, 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); -- 1.7.6.233.gd79bc
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor