Skip to content

Commit 430380b

Browse files
He Zheaxboe
authored andcommitted
block: aoe: Fix kernel crash due to atomic sleep when exiting
Since commit 3582dd2 ("aoe: convert aoeblk to blk-mq"), aoedev_downdev has had the possibility of sleeping and causing the following crash. BUG: scheduling while atomic: rmmod/2242/0x00000003 Modules linked in: aoe Preemption disabled at: [<ffffffffc01d95e5>] flush+0x95/0x4a0 [aoe] CPU: 7 PID: 2242 Comm: rmmod Tainted: G I 5.2.3 #1 Hardware name: Intel Corporation S5520HC/S5520HC, BIOS S5500.86B.01.10.0025.030220091519 03/02/2009 Call Trace: dump_stack+0x4f/0x6a ? flush+0x95/0x4a0 [aoe] __schedule_bug.cold+0x44/0x54 __schedule+0x44f/0x680 schedule+0x44/0xd0 blk_mq_freeze_queue_wait+0x46/0xb0 ? wait_woken+0x80/0x80 blk_mq_freeze_queue+0x1b/0x20 aoedev_downdev+0x111/0x160 [aoe] flush+0xff/0x4a0 [aoe] aoedev_exit+0x23/0x30 [aoe] aoe_exit+0x35/0x948 [aoe] __se_sys_delete_module+0x183/0x210 __x64_sys_delete_module+0x16/0x20 do_syscall_64+0x4d/0x130 entry_SYSCALL_64_after_hwframe+0x44/0xa9 RIP: 0033:0x7f24e0043b07 Code: 73 01 c3 48 8b 0d 89 73 0b 00 f7 d8 64 89 01 48 83 c8 ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 b8 b0 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d 59 73 0b 00 f7 d8 64 89 01 48 RSP: 002b:00007ffe18f7f1e8 EFLAGS: 00000206 ORIG_RAX: 00000000000000b0 RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f24e0043b07 RDX: 000000000000000a RSI: 0000000000000800 RDI: 0000555c3ecf87c8 RBP: 00007ffe18f7f1f0 R08: 0000000000000000 R09: 0000000000000000 R10: 00007f24e00b4ac0 R11: 0000000000000206 R12: 00007ffe18f7f238 R13: 00007ffe18f7f410 R14: 00007ffe18f80e73 R15: 0000555c3ecf8760 This patch, handling in the same way of pass two, unlocks the locks and restart pass one after aoedev_downdev is done. Fixes: 3582dd2 ("aoe: convert aoeblk to blk-mq") Signed-off-by: He Zhe <[email protected]> Signed-off-by: Jens Axboe <[email protected]>
1 parent 752ead4 commit 430380b

File tree

1 file changed

+10
-3
lines changed

1 file changed

+10
-3
lines changed

drivers/block/aoe/aoedev.c

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -323,10 +323,14 @@ flush(const char __user *str, size_t cnt, int exiting)
323323
}
324324

325325
flush_scheduled_work();
326-
/* pass one: without sleeping, do aoedev_downdev */
326+
/* pass one: do aoedev_downdev, which might sleep */
327+
restart1:
327328
spin_lock_irqsave(&devlist_lock, flags);
328329
for (d = devlist; d; d = d->next) {
329330
spin_lock(&d->lock);
331+
if (d->flags & DEVFL_TKILL)
332+
goto cont;
333+
330334
if (exiting) {
331335
/* unconditionally take each device down */
332336
} else if (specified) {
@@ -338,8 +342,11 @@ flush(const char __user *str, size_t cnt, int exiting)
338342
|| d->ref)
339343
goto cont;
340344

345+
spin_unlock(&d->lock);
346+
spin_unlock_irqrestore(&devlist_lock, flags);
341347
aoedev_downdev(d);
342348
d->flags |= DEVFL_TKILL;
349+
goto restart1;
343350
cont:
344351
spin_unlock(&d->lock);
345352
}
@@ -348,7 +355,7 @@ flush(const char __user *str, size_t cnt, int exiting)
348355
/* pass two: call freedev, which might sleep,
349356
* for aoedevs marked with DEVFL_TKILL
350357
*/
351-
restart:
358+
restart2:
352359
spin_lock_irqsave(&devlist_lock, flags);
353360
for (d = devlist; d; d = d->next) {
354361
spin_lock(&d->lock);
@@ -357,7 +364,7 @@ flush(const char __user *str, size_t cnt, int exiting)
357364
spin_unlock(&d->lock);
358365
spin_unlock_irqrestore(&devlist_lock, flags);
359366
freedev(d);
360-
goto restart;
367+
goto restart2;
361368
}
362369
spin_unlock(&d->lock);
363370
}

0 commit comments

Comments
 (0)