Btrfs-progs: fix csum check when extent lands on block group
authorJosef Bacik <jbacik@fusionio.com>
Tue, 16 Apr 2013 17:00:56 +0000 (13:00 -0400)
committerDavid Sterba <dsterba@suse.cz>
Tue, 23 Apr 2013 16:56:27 +0000 (18:56 +0200)
I was running fsync() tests and noticed that occasionally I was getting a bunch
of errors from fsck complaining about csums not having corresponding extents.
Thankfully after a few days of debugging this it turned out to be a bug with
fsck.  The csums were for an extent that started at the same offset as a block
group, and were offset within the extent.  So the search put us out at the block
group item and we just walked forward from there, never finding the actual
extent.  This is because the block group item key is higher than the extent item
key, so it comes first.  In order to fix this we need to check and see if we
landed on a block group item and take another step backwards to make sure we end
up at the extent item.  With this patch my reproducer no longer finds csums that
don't have matching extent records.  Thanks,

Signed-off-by: Josef Bacik <jbacik@fusionio.com>
cmds-check.c

index 9db048c..44b19d8 100644 (file)
@@ -2841,6 +2841,7 @@ static int check_extent_exists(struct btrfs_root *root, u64 bytenr,
        key.type = BTRFS_EXTENT_ITEM_KEY;
        key.offset = 0;
 
+
 again:
        ret = btrfs_search_slot(NULL, root->fs_info->extent_root, &key, path,
                                0, 0);
@@ -2848,8 +2849,27 @@ again:
                fprintf(stderr, "Error looking up extent record %d\n", ret);
                btrfs_free_path(path);
                return ret;
-       } else if (ret && path->slots[0]) {
-               path->slots[0]--;
+       } else if (ret) {
+               if (path->slots[0])
+                       path->slots[0]--;
+               else
+                       btrfs_prev_leaf(root, path);
+       }
+
+       btrfs_item_key_to_cpu(path->nodes[0], &key, path->slots[0]);
+
+       /*
+        * Block group items come before extent items if they have the same
+        * bytenr, so walk back one more just in case.  Dear future traveler,
+        * first congrats on mastering time travel.  Now if it's not too much
+        * trouble could you go back to 2006 and tell Chris to make the
+        * BLOCK_GROUP_ITEM_KEY lower than the EXTENT_ITEM_KEY please?
+        */
+       if (key.type == BTRFS_BLOCK_GROUP_ITEM_KEY) {
+               if (path->slots[0])
+                       path->slots[0]--;
+               else
+                       btrfs_prev_leaf(root, path);
        }
 
        while (num_bytes) {