A user reported that fsck was complaining about unresolved refs for some
snapshots.  You can reproduce this by doing

mkfs.btrfs /dev/sdb
mount /dev/sdb /mnt
btrfs subvol snap /mnt/ /mnt/a
btrfs subvol snap /mnt/ /mnt/b
btrfs subvol del /mnt/a
umount /mnt
btrfsck /dev/sdb

and you'd get this

unresolved ref root 258 dir 256 index 2 namelen 1 name a error 600

because snapshot b has a dir item that points to a.  Except we encode in our
root ref the dirid of the ref holder, and if it doesn't match we just give it
back a empty directory since we can't hardlink directories.  This makes the
check in btrfsck bogus, when we delete a we remove the ref key for it so any
lookups into /mnt/b/a will just give a blank directory as it's supposed to.  Fix
this by only saying the backref is reachable if there is both a DIR_ITEM and a
REF_KEY for the given root.  With this patch I no longer see errors when running
this reproducer.  Thanks,

Signed-off-by: Josef Bacik <jba...@fusionio.com>
---
 cmds-check.c |    8 ++++++--
 1 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/cmds-check.c b/cmds-check.c
index bbef89a..4083298 100644
--- a/cmds-check.c
+++ b/cmds-check.c
@@ -1507,14 +1507,16 @@ static int add_root_backref(struct cache_tree 
*root_cache,
        }
 
        if (item_type == BTRFS_DIR_ITEM_KEY) {
+               if (backref->found_forward_ref)
+                       rec->found_ref++;
                backref->found_dir_item = 1;
-               backref->reachable = 1;
-               rec->found_ref++;
        } else if (item_type == BTRFS_DIR_INDEX_KEY) {
                backref->found_dir_index = 1;
        } else if (item_type == BTRFS_ROOT_REF_KEY) {
                if (backref->found_forward_ref)
                        backref->errors |= REF_ERR_DUP_ROOT_REF;
+               else if (backref->found_dir_item)
+                       rec->found_ref++;
                backref->found_forward_ref = 1;
        } else if (item_type == BTRFS_ROOT_BACKREF_KEY) {
                if (backref->found_back_ref)
@@ -1524,6 +1526,8 @@ static int add_root_backref(struct cache_tree *root_cache,
                BUG_ON(1);
        }
 
+       if (backref->found_forward_ref && backref->found_dir_item)
+               backref->reachable = 1;
        return 0;
 }
 
-- 
1.7.7.6

--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to