X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=find-root.c;h=7e4c51f670aeb89485ea653701f8d3b7726e555e;hb=658cc4daa6ed6e6463cba2f30731abd9a91a7b2d;hp=1af37b549fabf3cd27adb98695c57b2a967da7b4;hpb=e404d4fd703af915b31b279b748a57c287e7a654;p=platform%2Fupstream%2Fbtrfs-progs.git diff --git a/find-root.c b/find-root.c index 1af37b5..7e4c51f 100644 --- a/find-root.c +++ b/find-root.c @@ -30,7 +30,7 @@ /* 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) { @@ -46,9 +46,14 @@ static int add_eb_to_result(struct extent_buffer *eb, 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; @@ -75,7 +80,7 @@ static int add_eb_to_result(struct extent_buffer *eb, /* 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; @@ -96,37 +101,42 @@ static int add_eb_to_result(struct extent_buffer *eb, * 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)