btrfsprogs/0134-Btrfs-progs-give-restore-a-list-roots-option.patch
David Sterba db07609875 - btrfs-progs-fix-open_ctree_usage_segfaults.patch: fix
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
2011-12-14 23:25:51 +00:00

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