]> git.proxmox.com Git - mirror_zfs.git/commitdiff
zfs_dbgmsg() is not safe from every context
authorLOLi <loli10K@users.noreply.github.com>
Wed, 28 Nov 2018 19:29:57 +0000 (20:29 +0100)
committerBrian Behlendorf <behlendorf1@llnl.gov>
Wed, 28 Nov 2018 19:29:57 +0000 (11:29 -0800)
This commit reverts to using printk() instead of zfs_dbgmsg() to log
messages in vdev_disk_error(): this is necessary because the latter can
be called from interrupt context where we are not allowed to sleep.
Unfortunately zfs_dbgmsg() performs its allocations calling kmalloc()
with the KM_SLEEP flag which may result in the following oops:

   BUG: scheduling while atomic: swapper/4/0/0x10000100
Call Trace:
<IRQ>  [<0>] dump_stack+0x19/0x1b
...
[<0>] spl_kmem_alloc+0xdf/0x140 [spl] <-- kmem_alloc(size, KM_SLEEP)
[<0>] __dprintf+0x69/0x150 [zfs]
[<0>] ? kmem_cache_free+0x1e2/0x200
[<0>] vdev_disk_error.part.15+0x5f/0x70 [zfs]
[<0>] vdev_disk_io_flush_completion+0x48/0x70 [zfs]
[<0>] bio_endio+0x67/0xb0
[<0>] blk_update_request+0x90/0x360
...
[<0>] scsi_finish_command+0xdc/0x140
[<0>] scsi_softirq_done+0x132/0x160
[<0>] blk_done_softirq+0x96/0xc0
[<0>] __do_softirq+0xf5/0x280
[<0>] call_softirq+0x1c/0x30
[<0>] do_softirq+0x65/0xa0
[<0>] irq_exit+0x105/0x110
[<0>] do_IRQ+0x56/0xf0
[<0>] common_interrupt+0x162/0x162
<EOI>  [<0>] ? cpuidle_enter_state+0x54/0xd0
[<0>] cpuidle_idle_call+0xde/0x230
[<0>] arch_cpu_idle+0xe/0xb0
[<0>] cpu_startup_entry+0x14a/0x1e0
[<0>] start_secondary+0x1f7/0x270
[<0>] start_cpu+0x5/0x14

Reviewed-by: Olaf Faaland <faaland1@llnl.gov>
Reviewed by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: loli10K <ezomori.nozomu@gmail.com>
Closes #8137
Closes #8150

module/zfs/vdev_disk.c

index a4109543dfc3aeb359d2505a53b7543939aa4ddb..9c44ba12a36ad188bf11e303b65ed573ab227360 100644 (file)
@@ -139,9 +139,16 @@ bdev_max_capacity(struct block_device *bdev, uint64_t wholedisk)
 static void
 vdev_disk_error(zio_t *zio)
 {
-       zfs_dbgmsg("zio error=%d type=%d offset=%llu size=%llu flags=%x\n",
-           zio->io_error, zio->io_type, (u_longlong_t)zio->io_offset,
-           (u_longlong_t)zio->io_size, zio->io_flags);
+       /*
+        * This function can be called in interrupt context, for instance while
+        * handling IRQs coming from a misbehaving disk device; use printk()
+        * which is safe from any context.
+        */
+       printk(KERN_WARNING "zio pool=%s vdev=%s error=%d type=%d "
+           "offset=%llu size=%llu flags=%x\n", spa_name(zio->io_spa),
+           zio->io_vd->vdev_path, zio->io_error, zio->io_type,
+           (u_longlong_t)zio->io_offset, (u_longlong_t)zio->io_size,
+           zio->io_flags);
 }
 
 /*