summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--btrfs-find-root.c81
1 files changed, 71 insertions, 10 deletions
diff --git a/btrfs-find-root.c b/btrfs-find-root.c
index 74a52b7b..9347b91f 100644
--- a/btrfs-find-root.c
+++ b/btrfs-find-root.c
@@ -31,6 +31,8 @@
#include "volumes.h"
#include "utils.h"
#include "crc32c.h"
+#include "extent-cache.h"
+#include "find-root.h"
static u16 csum_size = 0;
static u64 search_objectid = BTRFS_ROOT_TREE_OBJECTID;
@@ -330,22 +332,70 @@ static void get_root_gen_and_level(u64 objectid, struct btrfs_fs_info *fs_info,
}
}
+static void print_one_result(struct cache_extent *tree_block,
+ u8 level, u64 generation,
+ struct btrfs_find_root_filter *filter)
+{
+ int unsure = 0;
+
+ if (filter->match_gen == (u64)-1 || filter->match_level == (u8)-1)
+ unsure = 1;
+ printf("Well block %llu(gen: %llu level: %u) seems good, ",
+ tree_block->start, generation, level);
+ if (unsure)
+ printf("but we are unsure about the correct generation/level\n");
+ else
+ printf("but generation/level doesn't match, want gen: %llu level: %u\n",
+ filter->match_gen, filter->match_level);
+}
+
+static void print_find_root_result(struct cache_tree *result,
+ struct btrfs_find_root_filter *filter)
+{
+ struct btrfs_find_root_gen_cache *gen_cache;
+ struct cache_extent *cache;
+ struct cache_extent *tree_block;
+ u64 generation = 0;
+ u8 level = 0;
+
+ for (cache = last_cache_extent(result);
+ cache; cache = prev_cache_extent(cache)) {
+ gen_cache = container_of(cache,
+ struct btrfs_find_root_gen_cache, cache);
+ level = gen_cache->highest_level;
+ generation = cache->start;
+ if (level == filter->match_level &&
+ generation == filter->match_gen)
+ continue;
+ for (tree_block = last_cache_extent(&gen_cache->eb_tree);
+ tree_block; tree_block = prev_cache_extent(tree_block))
+ print_one_result(tree_block, level, generation, filter);
+ }
+}
+
int main(int argc, char **argv)
{
struct btrfs_root *root;
+ struct btrfs_find_root_filter filter = {0};
+ struct cache_tree result;
+ struct cache_extent *found;
int opt;
int ret;
+ /* Default to search root tree */
+ filter.objectid = BTRFS_ROOT_TREE_OBJECTID;
+ filter.match_gen = (u64)-1;
+ filter.match_level = (u8)-1;
while ((opt = getopt(argc, argv, "l:o:g:")) != -1) {
switch(opt) {
case 'o':
- search_objectid = arg_strtou64(optarg);
+ filter.objectid = arg_strtou64(optarg);
break;
case 'g':
- search_generation = arg_strtou64(optarg);
+ filter.generation = arg_strtou64(optarg);
break;
case 'l':
- search_level = arg_strtou64(optarg);
+ filter.level = arg_strtou64(optarg);
break;
default:
usage();
@@ -365,13 +415,24 @@ int main(int argc, char **argv)
fprintf(stderr, "Open ctree failed\n");
exit(1);
}
-
- if (search_generation == 0)
- get_root_gen_and_level(search_objectid, root->fs_info,
- &search_generation, NULL);
-
- csum_size = btrfs_super_csum_size(root->fs_info->super_copy);
- ret = find_root(root);
+ cache_tree_init(&result);
+
+ get_root_gen_and_level(filter.objectid, root->fs_info,
+ &filter.match_gen, &filter.match_level);
+ ret = btrfs_find_root_search(root, &filter, &result, &found);
+ if (ret < 0) {
+ fprintf(stderr, "Fail to search the tree root: %s\n",
+ strerror(-ret));
+ goto out;
+ }
+ if (ret > 0) {
+ printf("Found tree root at %llu gen %llu level %u\n",
+ found->start, filter.match_gen, filter.match_level);
+ ret = 0;
+ }
+ print_find_root_result(&result, &filter);
+out:
+ btrfs_find_root_free(&result);
close_ctree(root);
return ret;
}