• Ignat Korchagin's avatar
    dm crypt: do not wait for backlogged crypto request completion in softirq · 8abec36d
    Ignat Korchagin authored
    Commit 39d42fa9 ("dm crypt: add flags to optionally bypass kcryptd
    workqueues") made it possible for some code paths in dm-crypt to be
    executed in softirq context, when the underlying driver processes IO
    requests in interrupt/softirq context.
    
    When Crypto API backlogs a crypto request, dm-crypt uses
    wait_for_completion to avoid sending further requests to an already
    overloaded crypto driver. However, if the code is executing in softirq
    context, we might get the following stacktrace:
    
    [  210.235213][    C0] BUG: scheduling while atomic: fio/2602/0x00000102
    [  210.236701][    C0] Modules linked in:
    [  210.237566][    C0] CPU: 0 PID: 2602 Comm: fio Tainted: G        W         5.10.0+ #50
    [  210.239292][    C0] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 0.0.0 02/06/2015
    [  210.241233][    C0] Call Trace:
    [  210.241946][    C0]  <IRQ>
    [  210.242561][    C0]  dump_stack+0x7d/0xa3
    [  210.243466][    C0]  __schedule_bug.cold+0xb3/0xc2
    [  210.244539][    C0]  __schedule+0x156f/0x20d0
    [  210.245518][    C0]  ? io_schedule_timeout+0x140/0x140
    [  210.246660][    C0]  schedule+0xd0/0x270
    [  210.247541][    C0]  schedule_timeout+0x1fb/0x280
    [  210.248586][    C0]  ? usleep_range+0x150/0x150
    [  210.249624][    C0]  ? unpoison_range+0x3a/0x60
    [  210.250632][    C0]  ? ____kasan_kmalloc.constprop.0+0x82/0xa0
    [  210.251949][    C0]  ? unpoison_range+0x3a/0x60
    [  210.252958][    C0]  ? __prepare_to_swait+0xa7/0x190
    [  210.254067][    C0]  do_wait_for_common+0x2ab/0x370
    [  210.255158][    C0]  ? usleep_range+0x150/0x150
    [  210.256192][    C0]  ? bit_wait_io_timeout+0x160/0x160
    [  210.257358][    C0]  ? blk_update_request+0x757/0x1150
    [  210.258582][    C0]  ? _raw_spin_lock_irq+0x82/0xd0
    [  210.259674][    C0]  ? _raw_read_unlock_irqrestore+0x30/0x30
    [  210.260917][    C0]  wait_for_completion+0x4c/0x90
    [  210.261971][    C0]  crypt_convert+0x19a6/0x4c00
    [  210.263033][    C0]  ? _raw_spin_lock_irqsave+0x87/0xe0
    [  210.264193][    C0]  ? kasan_set_track+0x1c/0x30
    [  210.265191][    C0]  ? crypt_iv_tcw_ctr+0x4a0/0x4a0
    [  210.266283][    C0]  ? kmem_cache_free+0x104/0x470
    [  210.267363][    C0]  ? crypt_endio+0x91/0x180
    [  210.268327][    C0]  kcryptd_crypt_read_convert+0x30e/0x420
    [  210.269565][    C0]  blk_update_request+0x757/0x1150
    [  210.270563][    C0]  blk_mq_end_request+0x4b/0x480
    [  210.271680][    C0]  blk_done_softirq+0x21d/0x340
    [  210.272775][    C0]  ? _raw_spin_lock+0x81/0xd0
    [  210.273847][    C0]  ? blk_mq_stop_hw_queue+0x30/0x30
    [  210.275031][    C0]  ? _raw_read_lock_irq+0x40/0x40
    [  210.276182][    C0]  __do_softirq+0x190/0x611
    [  210.277203][    C0]  ? handle_edge_irq+0x221/0xb60
    [  210.278340][    C0]  asm_call_irq_on_stack+0x12/0x20
    [  210.279514][    C0]  </IRQ>
    [  210.280164][    C0]  do_softirq_own_stack+0x37/0x40
    [  210.281281][    C0]  irq_exit_rcu+0x110/0x1b0
    [  210.282286][    C0]  common_interrupt+0x74/0x120
    [  210.283376][    C0]  asm_common_interrupt+0x1e/0x40
    [  210.284496][    C0] RIP: 0010:_aesni_enc1+0x65/0xb0
    
    Fix this by making crypt_convert function reentrant from the point of
    a single bio and make dm-crypt defer further bio processing to a
    workqueue, if Crypto API backlogs a request in interrupt context.
    
    Fixes: 39d42fa9 ("dm crypt: add flags to optionally bypass kcryptd workqueues")
    Cc: stable@vger.kernel.org # v5.9+
    Signed-off-by: default avatarIgnat Korchagin <ignat@cloudflare.com>
    Acked-by: default avatarMikulas Patocka <mpatocka@redhat.com>
    Signed-off-by: default avatarMike Snitzer <snitzer@redhat.com>
    8abec36d
dm-crypt.c 91 KB