From d76d79fd2784fb8a09edc6a9879b927d2745b6ff Mon Sep 17 00:00:00 2001 From: Mark Johnston Date: Wed, 20 Nov 2024 11:23:08 -0500 Subject: [PATCH] zio: Avoid sleeping in the I/O path zio_delay_interrupt(), apparently used for fault injection, is executed in the I/O pipeline. It can cause the calling thread to go to sleep, which is not allowed on FreeBSD. This happens only for small delays, though, and there's no apparent reason to avoid deferring to a taskqueue in that case, as it already does otherwise. Simply go to sleep unconditionally. This fixes an occasional panic I see when running the ZTS on FreeBSD. Also remove an unhelpful comment referencing the non-existent timeout_generic(). Reviewed-by: Brian Behlendorf Reviewed-by: Alexander Motin Signed-off-by: Mark Johnston Closes #16785 --- module/zfs/zio.c | 27 ++++++++------------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/module/zfs/zio.c b/module/zfs/zio.c index a5daf73d5..f4d7e5754 100644 --- a/module/zfs/zio.c +++ b/module/zfs/zio.c @@ -2192,31 +2192,20 @@ zio_delay_interrupt(zio_t *zio) } else { taskqid_t tid; hrtime_t diff = zio->io_target_timestamp - now; - clock_t expire_at_tick = ddi_get_lbolt() + - NSEC_TO_TICK(diff); + int ticks = MAX(1, NSEC_TO_TICK(diff)); + clock_t expire_at_tick = ddi_get_lbolt() + ticks; DTRACE_PROBE3(zio__delay__hit, zio_t *, zio, hrtime_t, now, hrtime_t, diff); - if (NSEC_TO_TICK(diff) == 0) { - /* Our delay is less than a jiffy - just spin */ - zfs_sleep_until(zio->io_target_timestamp); - zio_interrupt(zio); - } else { + tid = taskq_dispatch_delay(system_taskq, zio_interrupt, + zio, TQ_NOSLEEP, expire_at_tick); + if (tid == TASKQID_INVALID) { /* - * Use taskq_dispatch_delay() in the place of - * OpenZFS's timeout_generic(). + * Couldn't allocate a task. Just finish the + * zio without a delay. */ - tid = taskq_dispatch_delay(system_taskq, - zio_interrupt, zio, TQ_NOSLEEP, - expire_at_tick); - if (tid == TASKQID_INVALID) { - /* - * Couldn't allocate a task. Just - * finish the zio without a delay. - */ - zio_interrupt(zio); - } + zio_interrupt(zio); } } return;