• F
    Btrfs: fix deadlock with memory reclaim during scrub · a5fb1142
    Filipe Manana 提交于
    When a transaction commit starts, it attempts to pause scrub and it blocks
    until the scrub is paused. So while the transaction is blocked waiting for
    scrub to pause, we can not do memory allocation with GFP_KERNEL from scrub,
    otherwise we risk getting into a deadlock with reclaim.
    
    Checking for scrub pause requests is done early at the beginning of the
    while loop of scrub_stripe() and later in the loop, scrub_extent() and
    scrub_raid56_parity() are called, which in turn call scrub_pages() and
    scrub_pages_for_parity() respectively. These last two functions do memory
    allocations using GFP_KERNEL. Same problem could happen while scrubbing
    the super blocks, since it calls scrub_pages().
    
    We also can not have any of the worker tasks, created by the scrub task,
    doing GFP_KERNEL allocations, because before pausing, the scrub task waits
    for all the worker tasks to complete (also done at scrub_stripe()).
    
    So make sure GFP_NOFS is used for the memory allocations because at any
    time a scrub pause request can happen from another task that started to
    commit a transaction.
    
    Fixes: 58c4e173 ("btrfs: scrub: use GFP_KERNEL on the submission path")
    CC: stable@vger.kernel.org # 4.6+
    Reviewed-by: NNikolay Borisov <nborisov@suse.com>
    Signed-off-by: NFilipe Manana <fdmanana@suse.com>
    Reviewed-by: NDavid Sterba <dsterba@suse.com>
    Signed-off-by: NDavid Sterba <dsterba@suse.com>
    a5fb1142
scrub.c 106.1 KB