Fix zinject list handlers
[zfs.git] / cmd / zinject / zinject.c
index 643d73e..13d067d 100644 (file)
@@ -20,6 +20,7 @@
  */
 /*
  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012 by Delphix. All rights reserved.
  */
 
 /*
@@ -235,8 +236,8 @@ usage(void)
            "\t\t'pad1', or 'pad2'.\n"
            "\t\t'errno' can be 'nxio' (the default), 'io', or 'dtl'.\n"
            "\n"
-           "\tzinject -d device -A <degrade|fault> pool\n"
-           "\t\tPerform a specific action on a particular device\n"
+           "\tzinject -d device -A <degrade|fault> -D <delay secs> pool\n"
+           "\t\tPerform a specific action on a particular device.\n"
            "\n"
            "\tzinject -I [-s <seconds> | -g <txgs>] pool\n"
            "\t\tCause the pool to stop writing blocks yet not\n"
@@ -566,18 +567,15 @@ main(int argc, char **argv)
        zinject_record_t record = { 0 };
        char pool[MAXNAMELEN];
        char dataset[MAXNAMELEN];
-       zfs_handle_t *zhp;
+       zfs_handle_t *zhp = NULL;
        int nowrites = 0;
        int dur_txg = 0;
        int dur_secs = 0;
        int ret;
        int flags = 0;
 
-       if ((g_zfs = libzfs_init()) == NULL) {
-               (void) fprintf(stderr, "internal error: failed to "
-                   "initialize ZFS library\n");
+       if ((g_zfs = libzfs_init()) == NULL)
                return (1);
-       }
 
        libzfs_print_on_error(g_zfs, B_TRUE);
 
@@ -602,7 +600,7 @@ main(int argc, char **argv)
        }
 
        while ((c = getopt(argc, argv,
-           ":aA:b:d:f:Fg:qhIc:t:T:l:mr:s:e:uL:p:")) != -1) {
+           ":aA:b:d:D:f:Fg:qhIc:t:T:l:mr:s:e:uL:p:")) != -1) {
                switch (c) {
                case 'a':
                        flags |= ZINJECT_FLUSH_ARC;
@@ -628,6 +626,16 @@ main(int argc, char **argv)
                case 'd':
                        device = optarg;
                        break;
+               case 'D':
+                       errno = 0;
+                       record.zi_timer = strtoull(optarg, &end, 10);
+                       if (errno != 0 || *end != '\0') {
+                               (void) fprintf(stderr, "invalid i/o delay "
+                                   "value: '%s'\n", optarg);
+                               usage();
+                               return (1);
+                       }
+                       break;
                case 'e':
                        if (strcasecmp(optarg, "io") == 0) {
                                error = EIO;
@@ -692,6 +700,7 @@ main(int argc, char **argv)
                case 'p':
                        (void) strlcpy(record.zi_func, optarg,
                            sizeof (record.zi_func));
+                       record.zi_cmd = ZINJECT_PANIC;
                        break;
                case 'q':
                        quiet = 1;
@@ -765,13 +774,15 @@ main(int argc, char **argv)
        argc -= optind;
        argv += optind;
 
+       if (record.zi_duration != 0)
+               record.zi_cmd = ZINJECT_IGNORED_WRITES;
+
        if (cancel != NULL) {
                /*
                 * '-c' is invalid with any other options.
                 */
                if (raw != NULL || range != NULL || type != TYPE_INVAL ||
-                   level != 0 || record.zi_func[0] != '\0' ||
-                   record.zi_duration != 0) {
+                   level != 0 || record.zi_cmd != ZINJECT_UNINITIALIZED) {
                        (void) fprintf(stderr, "cancel (-c) incompatible with "
                            "any other options\n");
                        usage();
@@ -803,8 +814,7 @@ main(int argc, char **argv)
                 * for doing injection, so handle it separately here.
                 */
                if (raw != NULL || range != NULL || type != TYPE_INVAL ||
-                   level != 0 || record.zi_func[0] != '\0' ||
-                   record.zi_duration != 0) {
+                   level != 0 || record.zi_cmd != ZINJECT_UNINITIALIZED) {
                        (void) fprintf(stderr, "device (-d) incompatible with "
                            "data error injection\n");
                        usage();
@@ -838,7 +848,7 @@ main(int argc, char **argv)
 
        } else if (raw != NULL) {
                if (range != NULL || type != TYPE_INVAL || level != 0 ||
-                   record.zi_func[0] != '\0' || record.zi_duration != 0) {
+                   record.zi_cmd != ZINJECT_UNINITIALIZED) {
                        (void) fprintf(stderr, "raw (-b) format with "
                            "any other options\n");
                        usage();
@@ -861,13 +871,14 @@ main(int argc, char **argv)
                        return (1);
                }
 
+               record.zi_cmd = ZINJECT_DATA_FAULT;
                if (translate_raw(raw, &record) != 0)
                        return (1);
                if (!error)
                        error = EIO;
-       } else if (record.zi_func[0] != '\0') {
+       } else if (record.zi_cmd == ZINJECT_PANIC) {
                if (raw != NULL || range != NULL || type != TYPE_INVAL ||
-                   level != 0 || device != NULL || record.zi_duration != 0) {
+                   level != 0 || device != NULL) {
                        (void) fprintf(stderr, "panic (-p) incompatible with "
                            "other options\n");
                        usage();
@@ -885,7 +896,7 @@ main(int argc, char **argv)
                if (argv[1] != NULL)
                        record.zi_type = atoi(argv[1]);
                dataset[0] = '\0';
-       } else if (record.zi_duration != 0) {
+       } else if (record.zi_cmd == ZINJECT_IGNORED_WRITES) {
                if (nowrites == 0) {
                        (void) fprintf(stderr, "-s or -g meaningless "
                            "without -I (ignore writes)\n");
@@ -939,6 +950,7 @@ main(int argc, char **argv)
                        return (1);
                }
 
+               record.zi_cmd = ZINJECT_DATA_FAULT;
                if (translate_record(type, argv[0], range, level, &record, pool,
                    dataset) != 0)
                        return (1);
@@ -954,20 +966,16 @@ main(int argc, char **argv)
        if (dataset[0] != '\0' && domount) {
                if ((zhp = zfs_open(g_zfs, dataset, ZFS_TYPE_DATASET)) == NULL)
                        return (1);
-#ifdef HAVE_ZPL
                if (zfs_unmount(zhp, NULL, 0) != 0)
                        return (1);
-#endif /* HAVE_ZPL */
        }
 
        record.zi_error = error;
 
        ret = register_handler(pool, flags, &record, quiet);
 
-#ifdef HAVE_ZPL
        if (dataset[0] != '\0' && domount)
                ret = (zfs_mount(zhp, NULL, 0) != 0);
-#endif /* HAVE_ZPL */
 
        libzfs_fini(g_zfs);