btrfs-progs: volume: Fix a bug causing btrfs-find-root to skip first chunk
authorQu Wenruo <quwenruo@cn.fujitsu.com>
Mon, 22 Feb 2016 06:59:53 +0000 (14:59 +0800)
committerDavid Sterba <dsterba@suse.com>
Fri, 26 Feb 2016 16:27:58 +0000 (17:27 +0100)
There is a small bug from 2011, where btrfs_next_bg (formally
btrfs_next_metadata) function will always skip the first chunk.

That's OK for that time, as there is always 3 empty temporary chunks.
But now, we may ended up with only one metadata or system chunk, with
empty chunk auto-remove from kernel or new mkfs.btrfs.

So fix it by checking the initial value so btrfs_next_bg() will return
the first chunk if its *logical parameter is 0.

Signed-off-by: Qu Wenruo <quwenruo@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.com>
volumes.c

index a94be0e..059c4f4 100644 (file)
--- a/volumes.c
+++ b/volumes.c
@@ -1170,14 +1170,23 @@ int btrfs_next_bg(struct btrfs_mapping_tree *map_tree, u64 *logical,
 {
        struct cache_extent *ce;
        struct map_lookup *map;
 {
        struct cache_extent *ce;
        struct map_lookup *map;
+       u64 cur = *logical;
 
 
-       ce = search_cache_extent(&map_tree->cache_tree, *logical);
+       ce = search_cache_extent(&map_tree->cache_tree, cur);
 
        while (ce) {
 
        while (ce) {
-               ce = next_cache_extent(ce);
-               if (!ce)
-                       return -ENOENT;
+               /*
+                * only jump to next bg if our cur is not 0
+                * As the initial logical for btrfs_next_bg() is 0, and
+                * if we jump to next bg, we skipped a valid bg.
+                */
+               if (cur) {
+                       ce = next_cache_extent(ce);
+                       if (!ce)
+                               return -ENOENT;
+               }
 
 
+               cur = ce->start;
                map = container_of(ce, struct map_lookup, ce);
                if (map->type & type) {
                        *logical = ce->start;
                map = container_of(ce, struct map_lookup, ce);
                if (map->type & type) {
                        *logical = ce->start;