• Josef Bacik's avatar
    btrfs: remove a BUG_ON() from merge_reloc_roots() · 7b7b7431
    Josef Bacik authored
    This was pretty subtle, we default to reloc roots having 0 root refs, so
    if we crash in the middle of the relocation they can just be deleted.
    If we successfully complete the relocation operations we'll set our root
    refs to 1 in prepare_to_merge() and then go on to merge_reloc_roots().
    
    At prepare_to_merge() time if any of the reloc roots have a 0 reference
    still, we will remove that reloc root from our reloc root rb tree, and
    then clean it up later.
    
    However this only happens if we successfully start a transaction.  If
    we've aborted previously we will skip this step completely, and only
    have reloc roots with a reference count of 0, but were never properly
    removed from the reloc control's rb tree.
    
    This isn't a problem per-se, our references are held by the list the
    reloc roots are on, and by the original root the reloc root belongs to.
    If we end up in this situation all the reloc roots will be added to the
    dirty_reloc_list, and then properly dropped at that point.  The reloc
    control will be free'd and the rb tree is no longer used.
    
    There were two options when fixing this, one was to remove the BUG_ON(),
    the other was to make prepare_to_merge() handle the case where we
    couldn't start a trans handle.
    
    IMO this is the cleaner solution.  I started with handling the error in
    prepare_to_merge(), but it turned out super ugly.  And in the end this
    BUG_ON() simply doesn't matter, the cleanup was happening properly, we
    were just panicing because this BUG_ON() only matters in the success
    case.  So I've opted to just remove it and add a comment where it was.
    Reviewed-by: default avatarQu Wenruo <wqu@suse.com>
    Signed-off-by: default avatarJosef Bacik <josef@toxicpanda.com>
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    7b7b7431
relocation.c 117 KB