btrfs-progs: check: special case for last item
authorSu Yue <suy.fnst@cn.fujitsu.com>
Fri, 1 Sep 2017 02:56:16 +0000 (10:56 +0800)
committerDavid Sterba <dsterba@suse.com>
Mon, 16 Oct 2017 18:33:00 +0000 (20:33 +0200)
Since repair functions will search path again, if the last item
was checked, the location where the path points is invalid.

Fix it by saving the last valid key if err contains LAST_ITEM,
and call btrfs_next_item() before return of check_inode_item().

Signed-off-by: Su Yue <suy.fnst@cn.fujitsu.com>
Signed-off-by: David Sterba <dsterba@suse.com>
cmds-check.c

index edc2726..1d399d7 100644 (file)
@@ -5748,6 +5748,7 @@ static int check_inode_item(struct btrfs_root *root, struct btrfs_path *path,
        struct extent_buffer *node;
        struct btrfs_inode_item *ii;
        struct btrfs_key key;
+       struct btrfs_key last_key;
        u64 inode_id;
        u32 mode;
        u64 nlink;
@@ -5787,6 +5788,7 @@ static int check_inode_item(struct btrfs_root *root, struct btrfs_path *path,
        nodatasum = btrfs_inode_flags(node, ii) & BTRFS_INODE_NODATASUM;
 
        while (1) {
+               btrfs_item_key_to_cpu(path->nodes[0], &last_key, path->slots[0]);
                ret = btrfs_next_item(root, path);
                if (ret < 0) {
                        /* out will fill 'err' rusing current statistics */
@@ -5848,6 +5850,13 @@ static int check_inode_item(struct btrfs_root *root, struct btrfs_path *path,
        }
 
 out:
+       if (err & LAST_ITEM) {
+               btrfs_release_path(path);
+               ret = btrfs_search_slot(NULL, root, &last_key, path, 0, 0);
+               if (ret)
+                       return err;
+       }
+
        /* verify INODE_ITEM nlink/isize/nbytes */
        if (dir) {
                if (repair && (err & DIR_COUNT_AGAIN)) {
@@ -5937,6 +5946,8 @@ out:
                }
        }
 
+       if (err & LAST_ITEM)
+               btrfs_next_item(root, path);
        return err;
 }