2 * Copyright (C) 2011 Red Hat. All rights reserved.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public
6 * License v2 as published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 * General Public License for more details.
13 * You should have received a copy of the GNU General Public
14 * License along with this program; if not, write to the
15 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
16 * Boston, MA 021110-1307, USA.
25 #include "kerncompat.h"
28 #include "print-tree.h"
29 #include "transaction.h"
34 #include "extent-cache.h"
35 #include "find-root.h"
37 static void usage(void)
39 fprintf(stderr
, "Usage: find-roots [-a] [-o search_objectid] "
40 "[ -g search_generation ] [ -l search_level ] <device>\n");
44 * Get reliable generation and level for given root.
46 * We have two sources of gen/level: superblock and tree root.
47 * superblock include the following level:
49 * and the following generations:
51 * Other gen/leven can only be read from its btrfs_tree_root if possible.
53 * Currently we only believe things from superblock.
55 static void get_root_gen_and_level(u64 objectid
, struct btrfs_fs_info
*fs_info
,
56 u64
*ret_gen
, u8
*ret_level
)
58 struct btrfs_super_block
*super
= fs_info
->super_copy
;
63 case BTRFS_ROOT_TREE_OBJECTID
:
64 level
= btrfs_super_root_level(super
);
65 gen
= btrfs_super_generation(super
);
67 case BTRFS_CHUNK_TREE_OBJECTID
:
68 level
= btrfs_super_chunk_root_level(super
);
69 gen
= btrfs_super_chunk_root_generation(super
);
70 printf("Search for chunk root is not supported yet\n");
72 case BTRFS_TREE_LOG_OBJECTID
:
73 level
= btrfs_super_log_root_level(super
);
74 gen
= btrfs_super_log_root_transid(super
);
76 case BTRFS_UUID_TREE_OBJECTID
:
77 gen
= btrfs_super_uuid_tree_generation(super
);
81 printf("Superblock thinks the generation is %llu\n", gen
);
85 printf("Superblock doesn't contain generation info for root %llu\n",
88 if (level
!= (u8
)-1) {
89 printf("Superblock thinks the level is %u\n", level
);
93 printf("Superblock doesn't contain the level info for root %llu\n",
98 static void print_one_result(struct cache_extent
*tree_block
,
99 u8 level
, u64 generation
,
100 struct btrfs_find_root_filter
*filter
)
104 if (filter
->match_gen
== (u64
)-1 || filter
->match_level
== (u8
)-1)
106 printf("Well block %llu(gen: %llu level: %u) seems good, ",
107 tree_block
->start
, generation
, level
);
109 printf("but we are unsure about the correct generation/level\n");
111 printf("but generation/level doesn't match, want gen: %llu level: %u\n",
112 filter
->match_gen
, filter
->match_level
);
115 static void print_find_root_result(struct cache_tree
*result
,
116 struct btrfs_find_root_filter
*filter
)
118 struct btrfs_find_root_gen_cache
*gen_cache
;
119 struct cache_extent
*cache
;
120 struct cache_extent
*tree_block
;
124 for (cache
= last_cache_extent(result
);
125 cache
; cache
= prev_cache_extent(cache
)) {
126 gen_cache
= container_of(cache
,
127 struct btrfs_find_root_gen_cache
, cache
);
128 level
= gen_cache
->highest_level
;
129 generation
= cache
->start
;
130 if (level
== filter
->match_level
&&
131 generation
== filter
->match_gen
)
133 for (tree_block
= last_cache_extent(&gen_cache
->eb_tree
);
134 tree_block
; tree_block
= prev_cache_extent(tree_block
))
135 print_one_result(tree_block
, level
, generation
, filter
);
139 int main(int argc
, char **argv
)
141 struct btrfs_root
*root
;
142 struct btrfs_find_root_filter filter
= {0};
143 struct cache_tree result
;
144 struct cache_extent
*found
;
148 /* Default to search root tree */
149 filter
.objectid
= BTRFS_ROOT_TREE_OBJECTID
;
150 filter
.match_gen
= (u64
)-1;
151 filter
.match_level
= (u8
)-1;
152 while ((opt
= getopt(argc
, argv
, "al:o:g:")) != -1) {
155 filter
.search_all
= 1;
158 filter
.objectid
= arg_strtou64(optarg
);
161 filter
.generation
= arg_strtou64(optarg
);
164 filter
.level
= arg_strtou64(optarg
);
173 argc
= argc
- optind
;
174 if (check_argc_min(argc
, 1)) {
179 root
= open_ctree(argv
[optind
], 0, OPEN_CTREE_CHUNK_ROOT_ONLY
);
181 fprintf(stderr
, "Open ctree failed\n");
184 cache_tree_init(&result
);
186 get_root_gen_and_level(filter
.objectid
, root
->fs_info
,
187 &filter
.match_gen
, &filter
.match_level
);
188 ret
= btrfs_find_root_search(root
, &filter
, &result
, &found
);
190 fprintf(stderr
, "Fail to search the tree root: %s\n",
195 printf("Found tree root at %llu gen %llu level %u\n",
196 found
->start
, filter
.match_gen
, filter
.match_level
);
199 print_find_root_result(&result
, &filter
);
201 btrfs_find_root_free(&result
);