- if (spa_config_held(spa, SCL_ZIO, RW_WRITER)) {
- /*
- * vdev_cant_read and vdev_cant_write can only transition
- * from TRUE to FALSE when we have the SCL_ZIO lock as writer;
- * otherwise they can only transition from FALSE to TRUE.
- * This ensures that any zio looking at these values can
- * assume that failures persist for the life of the I/O.
- * That's important because when a device has intermittent
- * connectivity problems, we want to ensure that they're
- * ascribed to the device (ENXIO) and not the zio (EIO).
- *
- * Since we hold SCL_ZIO as writer here, clear both values
- * so the probe can reevaluate from first principles.
- */
- vps->vps_flags |= ZIO_FLAG_CONFIG_WRITER;
- vd->vdev_cant_read = B_FALSE;
- vd->vdev_cant_write = B_FALSE;
+ /*
+ * To prevent 'probe storms' when a device fails, we create
+ * just one probe i/o at a time. All zios that want to probe
+ * this vdev will become parents of the probe io.
+ */
+ mutex_enter(&vd->vdev_probe_lock);
+
+ if ((pio = vd->vdev_probe_zio) == NULL) {
+ vps = kmem_zalloc(sizeof (*vps), KM_SLEEP);
+
+ vps->vps_flags = ZIO_FLAG_CANFAIL | ZIO_FLAG_PROBE |
+ ZIO_FLAG_DONT_CACHE | ZIO_FLAG_DONT_AGGREGATE |
+ ZIO_FLAG_TRYHARD;
+
+ if (spa_config_held(spa, SCL_ZIO, RW_WRITER)) {
+ /*
+ * vdev_cant_read and vdev_cant_write can only
+ * transition from TRUE to FALSE when we have the
+ * SCL_ZIO lock as writer; otherwise they can only
+ * transition from FALSE to TRUE. This ensures that
+ * any zio looking at these values can assume that
+ * failures persist for the life of the I/O. That's
+ * important because when a device has intermittent
+ * connectivity problems, we want to ensure that
+ * they're ascribed to the device (ENXIO) and not
+ * the zio (EIO).
+ *
+ * Since we hold SCL_ZIO as writer here, clear both
+ * values so the probe can reevaluate from first
+ * principles.
+ */
+ vps->vps_flags |= ZIO_FLAG_CONFIG_WRITER;
+ vd->vdev_cant_read = B_FALSE;
+ vd->vdev_cant_write = B_FALSE;
+ }
+
+ vd->vdev_probe_zio = pio = zio_null(NULL, spa, vd,
+ vdev_probe_done, vps,
+ vps->vps_flags | ZIO_FLAG_DONT_PROPAGATE);
+
+ if (zio != NULL) {
+ vd->vdev_probe_wanted = B_TRUE;
+ spa_async_request(spa, SPA_ASYNC_PROBE);
+ }