/* Return value is the same as btrfs_find_root_search(). */
static int add_eb_to_result(struct extent_buffer *eb,
struct cache_tree *result,
- u32 leafsize,
+ u32 nodesize,
struct btrfs_find_root_filter *filter,
struct cache_extent **match)
{
generation < filter->generation)
return ret;
- /* Get the generation cache or create one */
+ /*
+ * Get the generation cache or create one
+ *
+ * NOTE: search_cache_extent() may return cache that doesn't cover
+ * the range. So we need an extra check to make sure it's the right one.
+ */
cache = search_cache_extent(result, generation);
- if (!cache) {
+ if (!cache || cache->start != generation) {
gen_cache = malloc(sizeof(*gen_cache));
BUG_ON(!gen_cache);
cache = &gen_cache->cache;
/* Same level, insert it into the eb_tree */
if (level == gen_cache->highest_level) {
ret = add_cache_extent(&gen_cache->eb_tree,
- start, leafsize);
+ start, nodesize);
if (ret < 0 && ret != -EEXIST)
return ret;
ret = 0;
* Return 1 if found root with given gen/level and set *match to it.
* Return <0 if error happens
*/
-int btrfs_find_root_search(struct btrfs_root *chunk_root,
+int btrfs_find_root_search(struct btrfs_fs_info *fs_info,
struct btrfs_find_root_filter *filter,
struct cache_tree *result,
struct cache_extent **match)
{
- struct btrfs_fs_info *fs_info = chunk_root->fs_info;
struct extent_buffer *eb;
- u64 metadata_offset = 0;
- u64 metadata_size = 0;
+ u64 chunk_offset = 0;
+ u64 chunk_size = 0;
u64 offset = 0;
- u32 leafsize = chunk_root->leafsize;
+ u32 nodesize = btrfs_super_nodesize(fs_info->super_copy);
int suppress_errors = 0;
int ret = 0;
suppress_errors = fs_info->suppress_check_block_errors;
fs_info->suppress_check_block_errors = 1;
while (1) {
- ret = btrfs_next_metadata(&fs_info->mapping_tree,
- &metadata_offset, &metadata_size);
+ if (filter->objectid != BTRFS_CHUNK_TREE_OBJECTID)
+ ret = btrfs_next_bg_metadata(fs_info,
+ &chunk_offset,
+ &chunk_size);
+ else
+ ret = btrfs_next_bg_system(fs_info,
+ &chunk_offset,
+ &chunk_size);
if (ret) {
if (ret == -ENOENT)
ret = 0;
break;
}
- for (offset = metadata_offset;
- offset < metadata_offset + metadata_size;
- offset += chunk_root->leafsize) {
- eb = read_tree_block(chunk_root, offset, leafsize, 0);
+ for (offset = chunk_offset;
+ offset < chunk_offset + chunk_size;
+ offset += nodesize) {
+ eb = read_tree_block(fs_info, offset, 0);
if (!eb || IS_ERR(eb))
continue;
- ret = add_eb_to_result(eb, result, leafsize, filter,
+ ret = add_eb_to_result(eb, result, nodesize, filter,
match);
free_extent_buffer(eb);
if (ret)