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 GitHub
parent d2147de319
commit b8c73ab780
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

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);