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
;