summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@home.osdl.org>2003-09-23 19:45:35 -0700
committerLinus Torvalds <torvalds@home.osdl.org>2003-09-23 19:45:35 -0700
commitabd184cb4bf6fcb965c4aafab88e26ef6a46ccec (patch)
treeb7cf51a3fbfc6bcf8118fea3107ec13209ebcf66
parentdd7937d338f549b80be239caf18d5dc6c22a2921 (diff)
sd.c: be more cautious in asking for mode page 8 data,
sanity-checking the information more carefully. The old code basically just used a random-number approach to determine how much to read.
-rw-r--r--drivers/scsi/sd.c59
1 files changed, 37 insertions, 22 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 2bd0ee80e138..08d7cd49ca2b 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -1108,14 +1108,26 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname,
/* cautiously ask */
res = sd_do_mode_sense(SRpnt, dbd, modepage, buffer, 4, &data);
- if (scsi_status_is_good(res)) {
- /* that went OK, now ask for the proper length */
- len = data.length;
- if (len > 128)
- len = 128;
- res = sd_do_mode_sense(SRpnt, dbd, modepage, buffer,
- len, &data);
- }
+ if (!scsi_status_is_good(res))
+ goto bad_sense;
+
+ /* that went OK, now ask for the proper length */
+ len = data.length;
+
+ /*
+ * We're only interested in the first three bytes, actually.
+ * But the data cache page is defined for the first 20.
+ */
+ if (len < 3)
+ goto bad_sense;
+ if (len > 20)
+ len = 20;
+
+ /* Take headers and block descriptors into account */
+ len += data.header_length + data.block_descriptor_length;
+
+ /* Get the data */
+ res = sd_do_mode_sense(SRpnt, dbd, modepage, buffer, len, &data);
if (scsi_status_is_good(res)) {
const char *types[] = {
@@ -1133,23 +1145,26 @@ sd_read_cache_type(struct scsi_disk *sdkp, char *diskname,
printk(KERN_NOTICE "SCSI device %s: drive cache: %s\n",
diskname, types[ct]);
+
+ return;
+ }
+
+bad_sense:
+ if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70
+ && (SRpnt->sr_sense_buffer[2] & 0x0f) == ILLEGAL_REQUEST
+ /* ASC 0x24 ASCQ 0x00: Invalid field in CDB */
+ && SRpnt->sr_sense_buffer[12] == 0x24
+ && SRpnt->sr_sense_buffer[13] == 0x00) {
+ printk(KERN_NOTICE "%s: cache data unavailable\n",
+ diskname);
} else {
- if ((SRpnt->sr_sense_buffer[0] & 0x70) == 0x70
- && (SRpnt->sr_sense_buffer[2] & 0x0f) == ILLEGAL_REQUEST
- /* ASC 0x24 ASCQ 0x00: Invalid field in CDB */
- && SRpnt->sr_sense_buffer[12] == 0x24
- && SRpnt->sr_sense_buffer[13] == 0x00) {
- printk(KERN_NOTICE "%s: cache data unavailable\n",
- diskname);
- } else {
- printk(KERN_ERR "%s: asking for cache data failed\n",
- diskname);
- }
- printk(KERN_ERR "%s: assuming drive cache: write through\n",
+ printk(KERN_ERR "%s: asking for cache data failed\n",
diskname);
- sdkp->WCE = 0;
- sdkp->RCD = 0;
}
+ printk(KERN_ERR "%s: assuming drive cache: write through\n",
+ diskname);
+ sdkp->WCE = 0;
+ sdkp->RCD = 0;
}
/**