Subject: scsi disks with "Medium Format Corrupted"
To: None <tech-kern@netbsd.org>
From: Manuel Bouyer <bouyer@antioche.lip6.fr>
List: tech-kern
Date: 05/19/2004 17:15:47
--mP3DRpeJDSE+ciuQ
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline

Hi,
as part of tests with esiop I managed to damage a scsi disk with the format
command. It's now in this state:
java:/root#scsictl /dev/rsd1c format 516
scsictl: /dev/rsd1c: Device not configured

And on console:
sd1(esiop0:0:3:0):  Check Condition on CDB: 0x23 00 00 00 00 00 00 00 0c 00
    SENSE KEY:  Media Error
     ASC/ASCQ:  Medium Format Corrupted
     FRU CODE:  0xc

The problem is that we allow opening disks which are not formatted at all,
or with a format we can't handle, but we don't handle the case where
READ_FORMAT_CAPACITIES fails.
The attached patch cause sd_interpret_sense() to return EFTYPE instead of
EIO for the "Medium Format Corrupted" ASC/ASQ, so that we can check for
this kind of event in sd_get_capacity().
We also should not try to build a disklabel if the media is not formatted
(in my case this caused a panic: buf mem pool index 54, because sd->params
is not initialised properly).

Any comments ?

-- 
Manuel Bouyer <bouyer@antioche.eu.org>
     NetBSD: 26 ans d'experience feront toujours la difference
--

--mP3DRpeJDSE+ciuQ
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=diff

Index: sd.c
===================================================================
RCS file: /cvsroot/src/sys/dev/scsipi/sd.c,v
retrieving revision 1.216
diff -u -r1.216 sd.c
--- sd.c	14 Mar 2004 00:17:37 -0000	1.216
+++ sd.c	19 May 2004 15:12:42 -0000
@@ -532,6 +532,7 @@
 		}
 
 		if ((periph->periph_flags & PERIPH_MEDIA_LOADED) == 0) {
+			int param_error;
 			periph->periph_flags |= PERIPH_MEDIA_LOADED;
 
 			/*
@@ -542,15 +543,16 @@
 			 * The drive should refuse real I/O, if the media is
 			 * unformatted.
 			 */
-			if (sd_get_parms(sd, &sd->params,
-			    0) == SDGP_RESULT_OFFLINE) {
+			if ((param_error = sd_get_parms(sd, &sd->params, 0))
+			     == SDGP_RESULT_OFFLINE) {
 				error = ENXIO;
 				goto bad2;
 			}
 			SC_DEBUG(periph, SCSIPI_DB3, ("Params loaded "));
 
 			/* Load the partition info if not already loaded. */
-			sdgetdisklabel(sd);
+			if (param_error == 0)
+				sdgetdisklabel(sd);
 			SC_DEBUG(periph, SCSIPI_DB3, ("Disklabel loaded "));
 		}
 	}
@@ -1393,6 +1395,12 @@
 			splx(s);
 		}
 	}
+	if ((sense->flags & SSD_KEY) == SKEY_MEDIUM_ERROR &&
+	    sense->add_sense_code == 0x31 &&
+	    sense->add_sense_code_qual == 0x00)	{ /* maybe for any asq ? */
+		/* Medium Format Corrupted */
+		retval = EFTYPE;
+	}
 	return (retval);
 }
 
@@ -1701,6 +1709,10 @@
 		    sizeof(scsipi_result), SDRETRIES, 20000,
 		    NULL, flags | XS_CTL_DATA_IN | XS_CTL_DATA_ONSTACK /*|
 		    XS_CTL_IGNORE_ILLEGAL_REQUEST*/);
+		if (error == EFTYPE) {
+			/* Medium Format Corrupted, handle as not formatted */
+			return (SDGP_RESULT_UNFORMATTED);
+		}
 		if (error || scsipi_result.header.length == 0)
 			return (SDGP_RESULT_OFFLINE);
 

--mP3DRpeJDSE+ciuQ--