zio: do no-op injections just before handing off to vdevs

The purpose of no-op is to simulate a failure between a device cache and
its permanent store. We still want it to go through the queue and
respond in the same way to everything else.

So, inject "success" as the very last thing, and then move on to
VDEV_IO_DONE to be dequeued and so any followup work can occur.

Sponsored-by: Klara, Inc.
Sponsored-by: Wasabi Technology, Inc.
Reviewed-by: Alexander Motin <mav@FreeBSD.org>
Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Signed-off-by: Rob Norris <rob.norris@klarasystems.com>
Closes #17029
This commit is contained in:
Rob Norris 2025-02-08 12:42:24 +11:00 committed by Ameer Hamza
parent 001ab5941d
commit 0be3b266ed

View File

@ -4495,16 +4495,6 @@ zio_vdev_io_start(zio_t *zio)
zio->io_type == ZIO_TYPE_WRITE ||
zio->io_type == ZIO_TYPE_TRIM)) {
if (zio_handle_device_injection(vd, zio, ENOSYS) != 0) {
/*
* "no-op" injections return success, but do no actual
* work. Just skip the remaining vdev stages.
*/
zio_vdev_io_bypass(zio);
zio_interrupt(zio);
return (NULL);
}
if ((zio = vdev_queue_io(zio)) == NULL)
return (NULL);
@ -4514,6 +4504,15 @@ zio_vdev_io_start(zio_t *zio)
return (NULL);
}
zio->io_delay = gethrtime();
if (zio_handle_device_injection(vd, zio, ENOSYS) != 0) {
/*
* "no-op" injections return success, but do no actual
* work. Just return it.
*/
zio_delay_interrupt(zio);
return (NULL);
}
}
vd->vdev_ops->vdev_op_io_start(zio);