Rebase master to b117
[zfs.git] / module / zfs / zfs_fm.c
index 236d69e..8b7785f 100644 (file)
@@ -19,7 +19,7 @@
  * CDDL HEADER END
  */
 /*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
@@ -96,7 +96,6 @@ zfs_ereport_post(const char *subclass, spa_t *spa, vdev_t *vd, zio_t *zio,
        nvlist_t *ereport, *detector;
        uint64_t ena;
        char class[64];
-       int state;
 
        /*
         * If we are doing a spa_tryimport(), ignore errors.
@@ -130,15 +129,39 @@ zfs_ereport_post(const char *subclass, spa_t *spa, vdev_t *vd, zio_t *zio,
                        return;
 
                /*
-                * If the vdev has already been marked as failing due to a
-                * failed probe, then ignore any subsequent I/O errors, as the
-                * DE will automatically fault the vdev on the first such
-                * failure.
+                * If this I/O is not a retry I/O, don't post an ereport.
+                * Otherwise, we risk making bad diagnoses based on B_FAILFAST
+                * I/Os.
                 */
-               if (vd != NULL &&
-                   (!vdev_readable(vd) || !vdev_writeable(vd)) &&
-                   strcmp(subclass, FM_EREPORT_ZFS_PROBE_FAILURE) != 0)
+               if (zio->io_error == EIO &&
+                   !(zio->io_flags & ZIO_FLAG_IO_RETRY))
                        return;
+
+               if (vd != NULL) {
+                       /*
+                        * If the vdev has already been marked as failing due
+                        * to a failed probe, then ignore any subsequent I/O
+                        * errors, as the DE will automatically fault the vdev
+                        * on the first such failure.  This also catches cases
+                        * where vdev_remove_wanted is set and the device has
+                        * not yet been asynchronously placed into the REMOVED
+                        * state.
+                        */
+                       if (zio->io_vd == vd &&
+                           !vdev_accessible(vd, zio) &&
+                           strcmp(subclass, FM_EREPORT_ZFS_PROBE_FAILURE) != 0)
+                               return;
+
+                       /*
+                        * Ignore checksum errors for reads from DTL regions of
+                        * leaf vdevs.
+                        */
+                       if (zio->io_type == ZIO_TYPE_READ &&
+                           zio->io_error == ECKSUM &&
+                           vd->vdev_ops->vdev_op_leaf &&
+                           vdev_dtl_contains(vd, DTL_MISSING, zio->io_txg, 1))
+                               return;
+               }
        }
 
        if ((ereport = fm_nvlist_create(NULL)) == NULL)
@@ -189,21 +212,13 @@ zfs_ereport_post(const char *subclass, spa_t *spa, vdev_t *vd, zio_t *zio,
         */
 
        /*
-        * If we are importing a faulted pool, then we treat it like an open,
-        * not an import.  Otherwise, the DE will ignore all faults during
-        * import, since the default behavior is to mark the devices as
-        * persistently unavailable, not leave them in the faulted state.
-        */
-       state = spa->spa_import_faulted ? SPA_LOAD_OPEN : spa->spa_load_state;
-
-       /*
         * Generic payload members common to all ereports.
         */
        fm_payload_set(ereport, FM_EREPORT_PAYLOAD_ZFS_POOL,
            DATA_TYPE_STRING, spa_name(spa), FM_EREPORT_PAYLOAD_ZFS_POOL_GUID,
            DATA_TYPE_UINT64, spa_guid(spa),
            FM_EREPORT_PAYLOAD_ZFS_POOL_CONTEXT, DATA_TYPE_INT32,
-           state, NULL);
+           spa->spa_load_state, NULL);
 
        if (spa != NULL) {
                fm_payload_set(ereport, FM_EREPORT_PAYLOAD_ZFS_POOL_FAILMODE,
@@ -222,14 +237,18 @@ zfs_ereport_post(const char *subclass, spa_t *spa, vdev_t *vd, zio_t *zio,
                    DATA_TYPE_UINT64, vd->vdev_guid,
                    FM_EREPORT_PAYLOAD_ZFS_VDEV_TYPE,
                    DATA_TYPE_STRING, vd->vdev_ops->vdev_op_type, NULL);
-               if (vd->vdev_path)
+               if (vd->vdev_path != NULL)
                        fm_payload_set(ereport,
                            FM_EREPORT_PAYLOAD_ZFS_VDEV_PATH,
                            DATA_TYPE_STRING, vd->vdev_path, NULL);
-               if (vd->vdev_devid)
+               if (vd->vdev_devid != NULL)
                        fm_payload_set(ereport,
                            FM_EREPORT_PAYLOAD_ZFS_VDEV_DEVID,
                            DATA_TYPE_STRING, vd->vdev_devid, NULL);
+               if (vd->vdev_fru != NULL)
+                       fm_payload_set(ereport,
+                           FM_EREPORT_PAYLOAD_ZFS_VDEV_FRU,
+                           DATA_TYPE_STRING, vd->vdev_fru, NULL);
 
                if (pvd != NULL) {
                        fm_payload_set(ereport,