• Filipe Manana's avatar
    Btrfs: fix scrub preventing unused block groups from being deleted · 758f2dfc
    Filipe Manana authored
    Currently scrub can race with the cleaner kthread when the later attempts
    to delete an unused block group, and the result is preventing the cleaner
    kthread from ever deleting later the block group - unless the block group
    becomes used and unused again. The following diagram illustrates that
    race:
    
                  CPU 1                                 CPU 2
    
     cleaner kthread
       btrfs_delete_unused_bgs()
    
         gets block group X from
         fs_info->unused_bgs and
         removes it from that list
    
                                                 scrub_enumerate_chunks()
    
                                                   searches device tree using
                                                   its commit root
    
                                                   finds device extent for
                                                   block group X
    
                                                   gets block group X from the tree
                                                   fs_info->block_group_cache_tree
                                                   (via btrfs_lookup_block_group())
    
                                                   sets bg X to RO
    
         sees the block group is
         already RO and therefore
         doesn't delete it nor adds
         it back to unused list
    
    So fix this by making scrub add the block group again to the list of
    unused block groups if the block group is still unused when it finished
    scrubbing it and it hasn't been removed already.
    Signed-off-by: default avatarFilipe Manana <fdmanana@suse.com>
    Signed-off-by: default avatarChris Mason <clm@fb.com>
    758f2dfc
extent-tree.c 288 KB