• Josef Bacik's avatar
    btrfs: fix invalid removal of root ref · d49d3287
    Josef Bacik authored
    If we have the following sequence of events
    
      btrfs sub create A
      btrfs sub create A/B
      btrfs sub snap A C
      mkdir C/foo
      mv A/B C/foo
      rm -rf *
    
    We will end up with a transaction abort.
    
    The reason for this is because we create a root ref for B pointing to A.
    When we create a snapshot of C we still have B in our tree, but because
    the root ref points to A and not C we will make it appear to be empty.
    
    The problem happens when we move B into C.  This removes the root ref
    for B pointing to A and adds a ref of B pointing to C.  When we rmdir C
    we'll see that we have a ref to our root and remove the root ref,
    despite not actually matching our reference name.
    
    Now btrfs_del_root_ref() allowing this to work is a bug as well, however
    we know that this inode does not actually point to a root ref in the
    first place, so we shouldn't be calling btrfs_del_root_ref() in the
    first place and instead simply look up our dir index for this item and
    do the rest of the removal.
    
    CC: stable@vger.kernel.org # 4.4+
    Signed-off-by: default avatarJosef Bacik <josef@toxicpanda.com>
    Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    d49d3287
inode.c 300 KB