• Chris Mason's avatar
    Btrfs: Fix oops and use after free during space balancing · 44fb5511
    Chris Mason authored
    The btrfs allocator uses list_for_each to walk the available block
    groups when searching for free blocks.  It starts off with a hint
    to help find the best block group for a given allocation.
    
    The hint is resolved into a block group, but we don't properly check
    to make sure the block group we find isn't in the middle of being
    freed due to filesystem shrinking or balancing.  If it is being
    freed, the list pointers in it are bogus and can't be trusted.  But,
    the code happily goes along and uses them in the list_for_each loop,
    leading to all kinds of fun.
    
    The fix used here is to check to make sure the block group we find really
    is on the list before we use it.  list_del_init is used when removing
    it from the list, so we can do a proper check.
    
    The allocation clustering code has a similar bug where it will trust
    the block group in the current free space cluster.  If our allocation
    flags have changed (going from single spindle dup to raid1 for example)
    because the drives in the FS have changed, we're not allowed to use
    the old block group any more.
    
    The fix used here is to check the current cluster against the
    current allocation flags.
    Signed-off-by: default avatarChris Mason <chris.mason@oracle.com>
    44fb5511
extent-tree.c 156 KB