2 * Copyright (C) 2015 Fujitsu. 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.
19 #include "kerncompat.h"
25 #include "find-root.h"
28 #include "extent-cache.h"
30 /* Return value is the same as btrfs_find_root_search(). */
31 static int add_eb_to_result(struct extent_buffer *eb,
32 struct cache_tree *result,
34 struct btrfs_find_root_filter *filter,
35 struct cache_extent **match)
37 u64 generation = btrfs_header_generation(eb);
38 u64 level = btrfs_header_level(eb);
39 u64 owner = btrfs_header_owner(eb);
40 u64 start = eb->start;
41 struct cache_extent *cache;
42 struct btrfs_find_root_gen_cache *gen_cache = NULL;
45 if (owner != filter->objectid || level < filter->level ||
46 generation < filter->generation)
49 /* Get the generation cache or create one */
50 cache = search_cache_extent(result, generation);
52 gen_cache = malloc(sizeof(*gen_cache));
54 cache = &gen_cache->cache;
55 cache->start = generation;
58 gen_cache->highest_level = 0;
59 cache_tree_init(&gen_cache->eb_tree);
61 ret = insert_cache_extent(result, cache);
65 gen_cache = container_of(cache, struct btrfs_find_root_gen_cache,
68 /* Higher level, clean tree and insert the new one */
69 if (level > gen_cache->highest_level) {
70 free_extent_cache_tree(&gen_cache->eb_tree);
71 gen_cache->highest_level = level;
72 /* Fall into the insert routine */
75 /* Same level, insert it into the eb_tree */
76 if (level == gen_cache->highest_level) {
77 ret = add_cache_extent(&gen_cache->eb_tree,
79 if (ret < 0 && ret != -EEXIST)
83 if (generation == filter->match_gen &&
84 level == filter->match_level &&
85 !filter->search_all) {
88 *match = search_cache_extent(&gen_cache->eb_tree,
95 * Return 0 if iterating all the metadata extents.
96 * Return 1 if found root with given gen/level and set *match to it.
97 * Return <0 if error happens
99 int btrfs_find_root_search(struct btrfs_root *chunk_root,
100 struct btrfs_find_root_filter *filter,
101 struct cache_tree *result,
102 struct cache_extent **match)
104 struct btrfs_fs_info *fs_info = chunk_root->fs_info;
105 struct extent_buffer *eb;
106 u64 metadata_offset = 0;
107 u64 metadata_size = 0;
109 u32 leafsize = chunk_root->leafsize;
110 int suppress_errors = 0;
113 suppress_errors = fs_info->suppress_check_block_errors;
114 fs_info->suppress_check_block_errors = 1;
116 ret = btrfs_next_metadata(&fs_info->mapping_tree,
117 &metadata_offset, &metadata_size);
123 for (offset = metadata_offset;
124 offset < metadata_offset + metadata_size;
125 offset += chunk_root->leafsize) {
126 eb = read_tree_block(chunk_root, offset, leafsize, 0);
127 if (!eb || IS_ERR(eb))
129 ret = add_eb_to_result(eb, result, leafsize, filter,
131 free_extent_buffer(eb);
137 fs_info->suppress_check_block_errors = suppress_errors;