• F
    btrfs: fix race between writes to swap files and scrub · 195a49ea
    Filipe Manana 提交于
    When we active a swap file, at btrfs_swap_activate(), we acquire the
    exclusive operation lock to prevent the physical location of the swap
    file extents to be changed by operations such as balance and device
    replace/resize/remove. We also call there can_nocow_extent() which,
    among other things, checks if the block group of a swap file extent is
    currently RO, and if it is we can not use the extent, since a write
    into it would result in COWing the extent.
    
    However we have no protection against a scrub operation running after we
    activate the swap file, which can result in the swap file extents to be
    COWed while the scrub is running and operating on the respective block
    group, because scrub turns a block group into RO before it processes it
    and then back again to RW mode after processing it. That means an attempt
    to write into a swap file extent while scrub is processing the respective
    block group, will result in COWing the extent, changing its physical
    location on disk.
    
    Fix this by making sure that block groups that have extents that are used
    by active swap files can not be turned into RO mode, therefore making it
    not possible for a scrub to turn them into RO mode. When a scrub finds a
    block group that can not be turned to RO due to the existence of extents
    used by swap files, it proceeds to the next block group and logs a warning
    message that mentions the block group was skipped due to active swap
    files - this is the same approach we currently use for balance.
    
    Fixes: ed46ff3d ("Btrfs: support swap files")
    CC: stable@vger.kernel.org # 5.4+
    Reviewed-by: NAnand Jain <anand.jain@oracle.com>
    Reviewed-by: NJosef Bacik <josef@toxicpanda.com>
    Signed-off-by: NFilipe Manana <fdmanana@suse.com>
    Signed-off-by: NDavid Sterba <dsterba@suse.com>
    195a49ea
scrub.c 112.7 KB