Page MenuHomeFreeBSD

D48689.diff
No OneTemporary

D48689.diff

diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c
--- a/sys/cam/scsi/scsi_da.c
+++ b/sys/cam/scsi/scsi_da.c
@@ -1805,7 +1805,10 @@
/*
* Only 'validate' the pack if the media size is non-zero and the
- * underlying peripheral isn't invalid (the only error != 0 path).
+ * underlying peripheral isn't invalid (the only error != 0 path). Once
+ * the periph is marked invalid, we only get here on lost races with its
+ * teardown, so keeping the pack invalid also keeps more I/O from
+ * starting.
*/
if (error == 0 && softc->params.sectors != 0)
softc->flags &= ~DA_FLAG_PACK_INVALID;
@@ -4609,33 +4612,45 @@
*/
bp = (struct bio *)done_ccb->ccb_h.ccb_bp;
if (error != 0) {
- int queued_error;
+ bool pack_invalid =
+ (softc->flags & DA_FLAG_PACK_INVALID) != 0;
- /*
- * return all queued I/O with EIO, so that
- * the client can retry these I/Os in the
- * proper order should it attempt to recover.
- */
- queued_error = EIO;
-
- if (error == ENXIO
- && (softc->flags & DA_FLAG_PACK_INVALID)== 0) {
+ if (error == ENXIO && !pack_invalid) {
/*
- * Catastrophic error. Mark our pack as
- * invalid.
+ * ENXIO flags ASC/ASCQ codes for either media
+ * missing, or the drive being extremely
+ * unhealthy. Invalidate peripheral on this
+ * catestrophic error when the pack is valid
+ * since we set the pack invalid bit only for
+ * the few ASC/ASCQ codes indicating missing
+ * media. The invalidation will flush any
+ * queued I/O and short-circuit retries for
+ * other I/O. We only invalidate the da device
+ * so the passX device remains for recovery and
+ * diagnostics.
*
- * XXX See if this is really a media
- * XXX change first?
+ * While we do also set the pack invalid bit
+ * after invalidating the peripheral, the
+ * pending I/O will have been flushed then with
+ * no new I/O starting, so this 'edge' case
+ * doesn't matter.
*/
xpt_print(periph->path, "Invalidating pack\n");
- softc->flags |= DA_FLAG_PACK_INVALID;
-#ifdef CAM_IO_STATS
- softc->invalidations++;
-#endif
- queued_error = ENXIO;
+ cam_periph_invalidate(periph);
+ } else {
+ /*
+ * Return all queued I/O with EIO, so that the
+ * client can retry these I/Os in the proper
+ * order should it attempt to recover. When the
+ * pack is invalid, fail all I/O with ENXIO
+ * since we can't assume when the media returns
+ * it's the same media and we force a trip
+ * through daclose / daopen and the client won't
+ * retry.
+ */
+ cam_iosched_flush(softc->cam_iosched, NULL,
+ pack_invalid ? ENXIO : EIO);
}
- cam_iosched_flush(softc->cam_iosched, NULL,
- queued_error);
if (bp != NULL) {
bp->bio_error = error;
bp->bio_resid = bp->bio_bcount;

File Metadata

Mime Type
text/plain
Expires
Sun, Apr 27, 1:04 PM (18 h, 22 s)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
16564233
Default Alt Text
D48689.diff (2 KB)

Event Timeline