3246 ZFS I/O deadman thread
[zfs.git] / module / zfs / zio_inject.c
index 16eaed6..eb589c4 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.
  */
 
 /*
@@ -46,7 +47,7 @@
 #include <sys/dmu_objset.h>
 #include <sys/fs/zfs.h>
 
-uint32_t zio_injection_enabled;
+uint32_t zio_injection_enabled = 0;
 
 typedef struct inject_handler {
        int                     zi_id;
@@ -147,14 +148,8 @@ zio_handle_fault_injection(zio_t *zio, int error)
        for (handler = list_head(&inject_handlers); handler != NULL;
            handler = list_next(&inject_handlers, handler)) {
 
-               /* Ignore errors not destined for this pool */
-               if (zio->io_spa != handler->zi_spa)
-                       continue;
-
-               /* Ignore device errors and panic injection */
-               if (handler->zi_record.zi_guid != 0 ||
-                   handler->zi_record.zi_func[0] != '\0' ||
-                   handler->zi_record.zi_duration != 0)
+               if (zio->io_spa != handler->zi_spa ||
+                   handler->zi_record.zi_cmd != ZINJECT_DATA_FAULT)
                        continue;
 
                /* If this handler matches, return EIO */
@@ -197,10 +192,7 @@ zio_handle_label_injection(zio_t *zio, int error)
                uint64_t start = handler->zi_record.zi_start;
                uint64_t end = handler->zi_record.zi_end;
 
-               /* Ignore device only faults or panic injection */
-               if (handler->zi_record.zi_start == 0 ||
-                   handler->zi_record.zi_func[0] != '\0' ||
-                   handler->zi_record.zi_duration != 0)
+               if (handler->zi_record.zi_cmd != ZINJECT_LABEL_FAULT)
                        continue;
 
                /*
@@ -246,13 +238,7 @@ zio_handle_device_injection(vdev_t *vd, zio_t *zio, int error)
        for (handler = list_head(&inject_handlers); handler != NULL;
            handler = list_next(&inject_handlers, handler)) {
 
-               /*
-                * Ignore label specific faults, panic injection
-                * or fake writes
-                */
-               if (handler->zi_record.zi_start != 0 ||
-                   handler->zi_record.zi_func[0] != '\0' ||
-                   handler->zi_record.zi_duration != 0)
+               if (handler->zi_record.zi_cmd != ZINJECT_DEVICE_FAULT)
                        continue;
 
                if (vd->vdev_guid == handler->zi_record.zi_guid) {
@@ -316,10 +302,8 @@ zio_handle_ignored_writes(zio_t *zio)
            handler = list_next(&inject_handlers, handler)) {
 
                /* Ignore errors not destined for this pool */
-               if (zio->io_spa != handler->zi_spa)
-                       continue;
-
-               if (handler->zi_record.zi_duration == 0)
+               if (zio->io_spa != handler->zi_spa ||
+                   handler->zi_record.zi_cmd != ZINJECT_IGNORED_WRITES)
                        continue;
 
                /*
@@ -355,11 +339,8 @@ spa_handle_ignored_writes(spa_t *spa)
        for (handler = list_head(&inject_handlers); handler != NULL;
            handler = list_next(&inject_handlers, handler)) {
 
-               /* Ignore errors not destined for this pool */
-               if (spa != handler->zi_spa)
-                       continue;
-
-               if (handler->zi_record.zi_duration == 0)
+               if (spa != handler->zi_spa ||
+                   handler->zi_record.zi_cmd != ZINJECT_IGNORED_WRITES)
                        continue;
 
                if (handler->zi_record.zi_duration > 0) {
@@ -379,6 +360,34 @@ spa_handle_ignored_writes(spa_t *spa)
        rw_exit(&inject_lock);
 }
 
+uint64_t
+zio_handle_io_delay(zio_t *zio)
+{
+       vdev_t *vd = zio->io_vd;
+       inject_handler_t *handler;
+       uint64_t seconds = 0;
+
+       if (zio_injection_enabled == 0)
+               return (0);
+
+       rw_enter(&inject_lock, RW_READER);
+
+       for (handler = list_head(&inject_handlers); handler != NULL;
+           handler = list_next(&inject_handlers, handler)) {
+
+               if (handler->zi_record.zi_cmd != ZINJECT_DELAY_IO)
+                       continue;
+
+               if (vd->vdev_guid == handler->zi_record.zi_guid) {
+                       seconds = handler->zi_record.zi_timer;
+                       break;
+               }
+
+       }
+       rw_exit(&inject_lock);
+       return (seconds);
+}
+
 /*
  * Create a new handler for the given record.  We add it to the list, adding
  * a reference to the spa_t in the process.  We increment zio_injection_enabled,
@@ -476,7 +485,6 @@ int
 zio_clear_fault(int id)
 {
        inject_handler_t *handler;
-       int ret;
 
        rw_enter(&inject_lock, RW_WRITER);
 
@@ -486,18 +494,18 @@ zio_clear_fault(int id)
                        break;
 
        if (handler == NULL) {
-               ret = ENOENT;
-       } else {
-               list_remove(&inject_handlers, handler);
-               spa_inject_delref(handler->zi_spa);
-               kmem_free(handler, sizeof (inject_handler_t));
-               atomic_add_32(&zio_injection_enabled, -1);
-               ret = 0;
+               rw_exit(&inject_lock);
+               return (ENOENT);
        }
 
+       list_remove(&inject_handlers, handler);
        rw_exit(&inject_lock);
 
-       return (ret);
+       spa_inject_delref(handler->zi_spa);
+       kmem_free(handler, sizeof (inject_handler_t));
+       atomic_add_32(&zio_injection_enabled, -1);
+
+       return (0);
 }
 
 void
@@ -514,3 +522,8 @@ zio_inject_fini(void)
        list_destroy(&inject_handlers);
        rw_destroy(&inject_lock);
 }
+
+#if defined(_KERNEL) && defined(HAVE_SPL)
+module_param(zio_injection_enabled, int, 0644);
+MODULE_PARM_DESC(zio_injection_enabled, "Enable fault injection");
+#endif