]> git.proxmox.com Git - mirror_zfs.git/commitdiff
zinject: inject device errors into ioctls
authorRob N <rob.norris@klarasystems.com>
Mon, 8 Apr 2024 18:59:04 +0000 (04:59 +1000)
committerGitHub <noreply@github.com>
Mon, 8 Apr 2024 18:59:04 +0000 (11:59 -0700)
Adds 'ioctl' as a valid IO type for device error injection, so we can
simulate a flush error (which OpenZFS currently ignores, but that's by
the by).

To support this, adding ZIO_STAGE_VDEV_IO_DONE to ZIO_IOCTL_PIPELINE,
since that's where device error injection happens. This needs a small
exclusion to avoid the vdev_queue, since flushes are not queued, and I'm
assuming that the various failure responses are still reasonable for
flush failures (probes, media change, etc). This seems reasonable to me,
as a flush failure is not unlike a write failure in this regard, however
this may be too aggressive or subtle to assume in just this change.

Sponsored-by: Klara, Inc.
Sponsored-by: Wasabi Technology, Inc.
Reviewed-by: Alexander Motin <mav@FreeBSD.org>
Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Signed-off-by: Rob Norris <rob.norris@klarasystems.com>
Closes #16061

cmd/zinject/zinject.c
include/sys/zio_impl.h
man/man8/zinject.8
man/man8/zpool-events.8
module/zfs/zio.c
module/zfs/zio_inject.c

index 8d0cf5d0a95750e9d4e21b05b03647abfdc9752b..07d3d8af9980b79f18dfecfd105f211bd9d741c8 100644 (file)
@@ -265,7 +265,7 @@ usage(void)
            "\t\tspa_vdev_exit() will trigger a panic.\n"
            "\n"
            "\tzinject -d device [-e errno] [-L <nvlist|uber|pad1|pad2>] [-F]\n"
-           "\t\t[-T <read|write|free|claim|all>] [-f frequency] pool\n\n"
+           "\t\t[-T <read|write|free|claim|ioctl|all>] [-f frequency] pool\n\n"
            "\t\tInject a fault into a particular device or the device's\n"
            "\t\tlabel.  Label injection can either be 'nvlist', 'uber',\n "
            "\t\t'pad1', or 'pad2'.\n"
@@ -978,12 +978,14 @@ main(int argc, char **argv)
                                io_type = ZIO_TYPE_FREE;
                        } else if (strcasecmp(optarg, "claim") == 0) {
                                io_type = ZIO_TYPE_CLAIM;
+                       } else if (strcasecmp(optarg, "ioctl") == 0) {
+                               io_type = ZIO_TYPE_IOCTL;
                        } else if (strcasecmp(optarg, "all") == 0) {
                                io_type = ZIO_TYPES;
                        } else {
                                (void) fprintf(stderr, "invalid I/O type "
                                    "'%s': must be 'read', 'write', 'free', "
-                                   "'claim' or 'all'\n", optarg);
+                                   "'claim', 'ioctl' or 'all'\n", optarg);
                                usage();
                                libzfs_fini(g_zfs);
                                return (1);
index 1c0a44059d242e9bb61b7ae0e576ce5b67b5cefb..4b3726d7eec4d307581c1880605d6f1f64db61df 100644 (file)
@@ -153,7 +153,7 @@ enum zio_stage {
        ZIO_STAGE_READY                 = 1 << 20,      /* RWFCIT */
 
        ZIO_STAGE_VDEV_IO_START         = 1 << 21,      /* RW--IT */
-       ZIO_STAGE_VDEV_IO_DONE          = 1 << 22,      /* RW---T */
+       ZIO_STAGE_VDEV_IO_DONE          = 1 << 22,      /* RW--IT */
        ZIO_STAGE_VDEV_IO_ASSESS        = 1 << 23,      /* RW--IT */
 
        ZIO_STAGE_CHECKSUM_VERIFY       = 1 << 24,      /* R----- */
@@ -261,8 +261,7 @@ enum zio_stage {
 
 #define        ZIO_IOCTL_PIPELINE                      \
        (ZIO_INTERLOCK_STAGES |                 \
-       ZIO_STAGE_VDEV_IO_START |               \
-       ZIO_STAGE_VDEV_IO_ASSESS)
+       ZIO_VDEV_IO_STAGES)
 
 #define        ZIO_TRIM_PIPELINE                       \
        (ZIO_INTERLOCK_STAGES |                 \
index b692f12130a816700f598944d80423a9d8693a3e..817dcb7fe32ab99504ccd4e94eb28316a91098cb 100644 (file)
 .\" CDDL HEADER END
 .\"
 .\" Copyright 2013 Darik Horn <dajhorn@vanadac.com>. All rights reserved.
+.\" Copyright (c) 2024, Klara Inc.
 .\"
 .\" lint-ok: WARNING: sections out of conventional order: Sh SYNOPSIS
 .\"
-.Dd May 26, 2021
+.Dd April 4, 2024
 .Dt ZINJECT 8
 .Os
 .
@@ -257,6 +258,7 @@ Run for this many seconds before reporting failure.
 .It Fl T Ar failure
 Set the failure type to one of
 .Sy all ,
+.Sy ioctl ,
 .Sy claim ,
 .Sy free ,
 .Sy read ,
index a7a9e33442da3170fda55bc1c4e7f6dad2fb30b1..12331b7b2a2da5fbcc2e3dc42734b0ae53eeeebc 100644 (file)
@@ -404,7 +404,7 @@ ZIO_STAGE_DVA_CLAIM:0x00080000:---C--
 ZIO_STAGE_READY:0x00100000:RWFCIT
 
 ZIO_STAGE_VDEV_IO_START:0x00200000:RW--IT
-ZIO_STAGE_VDEV_IO_DONE:0x00400000:RW---T
+ZIO_STAGE_VDEV_IO_DONE:0x00400000:RW--IT
 ZIO_STAGE_VDEV_IO_ASSESS:0x00800000:RW--IT
 
 ZIO_STAGE_CHECKSUM_VERIFY:0x01000000:R-----
index e96bbda35a047e19ee8579239d089eb6cb7043d8..08d56eef83e9bd17afd1170ed730f6e3cf8f7ce5 100644 (file)
@@ -4086,14 +4086,17 @@ zio_vdev_io_done(zio_t *zio)
        }
 
        ASSERT(zio->io_type == ZIO_TYPE_READ ||
-           zio->io_type == ZIO_TYPE_WRITE || zio->io_type == ZIO_TYPE_TRIM);
+           zio->io_type == ZIO_TYPE_WRITE ||
+           zio->io_type == ZIO_TYPE_IOCTL ||
+           zio->io_type == ZIO_TYPE_TRIM);
 
        if (zio->io_delay)
                zio->io_delay = gethrtime() - zio->io_delay;
 
        if (vd != NULL && vd->vdev_ops->vdev_op_leaf &&
            vd->vdev_ops != &vdev_draid_spare_ops) {
-               vdev_queue_io_done(zio);
+               if (zio->io_type != ZIO_TYPE_IOCTL)
+                       vdev_queue_io_done(zio);
 
                if (zio_injection_enabled && zio->io_error == 0)
                        zio->io_error = zio_handle_device_injections(vd, zio,
index 609182f4a2cd0826db6c5b0070ff21f57e817090..0a4851ecb40da9ad0318f5f2f4914447e89a63b5 100644 (file)
@@ -364,10 +364,10 @@ zio_handle_device_injection_impl(vdev_t *vd, zio_t *zio, int err1, int err2)
        int ret = 0;
 
        /*
-        * We skip over faults in the labels unless it's during
-        * device open (i.e. zio == NULL).
+        * We skip over faults in the labels unless it's during device open
+        * (i.e. zio == NULL) or a device flush (offset is meaningless)
         */
-       if (zio != NULL) {
+       if (zio != NULL && zio->io_type != ZIO_TYPE_IOCTL) {
                uint64_t offset = zio->io_offset;
 
                if (offset < VDEV_LABEL_START_SIZE ||