db07609875
segfaults from bnc#710486 due to unchecked usage of return value of open_ctree() [fixed compilation warnings] - pull upstream, replace existing patches, spec update - update 'restore' utility - lzo support - tools may now take earlies superblock when opening the fs - other fixes - pull integration-20111030 branch - mkfs: force mkfs if desired - other fixes - add btrfs-dump-super to mkinitrd - other fixes - skip non-existent devices or without media - documentation updates - scrubbing single device - graceful error handling when opening fs fails - updated mkinitrd script to scan devices before mount (bnc#727383) OBS-URL: https://build.opensuse.org/package/show/filesystems/btrfsprogs?expand=0&rev=115
181 lines
4.6 KiB
Diff
181 lines
4.6 KiB
Diff
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
|
|
|