diff options
| author | Linus Torvalds <torvalds@home.osdl.org> | 2003-09-23 19:45:35 -0700 |
|---|---|---|
| committer | Linus Torvalds <torvalds@home.osdl.org> | 2003-09-23 19:45:35 -0700 |
| commit | abd184cb4bf6fcb965c4aafab88e26ef6a46ccec (patch) | |
| tree | b7cf51a3fbfc6bcf8118fea3107ec13209ebcf66 | |
| parent | dd7937d338f549b80be239caf18d5dc6c22a2921 (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.c | 59 |
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; } /** |
