diff options
Diffstat (limited to 'drivers/scsi/sd.c')
-rw-r--r-- | drivers/scsi/sd.c | 66 |
1 files changed, 18 insertions, 48 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 3be5db5d6343..bd0806e64e85 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -597,6 +597,7 @@ static int scsi_setup_discard_cmnd(struct scsi_device *sdp, struct request *rq) break; default: + ret = BLKPREP_KILL; goto out; } @@ -1054,7 +1055,7 @@ static int sd_getgeo(struct block_device *bdev, struct hd_geometry *geo) * @arg: this is third argument given to ioctl(2) system call. * Often contains a pointer. * - * Returns 0 if successful (some ioctls return postive numbers on + * Returns 0 if successful (some ioctls return positive numbers on * success as well). Returns a negated errno value in case of error. * * Note: most ioctls are forward onto the block subsystem or further @@ -2026,14 +2027,10 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) int old_rcd = sdkp->RCD; int old_dpofua = sdkp->DPOFUA; - if (sdp->skip_ms_page_8) { - if (sdp->type == TYPE_RBC) - goto defaults; - else { - modepage = 0x3F; - dbd = 0; - } - } else if (sdp->type == TYPE_RBC) { + if (sdp->skip_ms_page_8) + goto defaults; + + if (sdp->type == TYPE_RBC) { modepage = 6; dbd = 8; } else { @@ -2061,11 +2058,13 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) */ if (len < 3) goto bad_sense; - else if (len > SD_BUF_SIZE) { - sd_printk(KERN_NOTICE, sdkp, "Truncating mode parameter " - "data from %d to %d bytes\n", len, SD_BUF_SIZE); - len = SD_BUF_SIZE; - } + if (len > 20) + len = 20; + + /* Take headers and block descriptors into account */ + len += data.header_length + data.block_descriptor_length; + if (len > SD_BUF_SIZE) + goto bad_sense; /* Get the data */ res = sd_do_mode_sense(sdp, dbd, modepage, buffer, len, &data, &sshdr); @@ -2073,45 +2072,16 @@ sd_read_cache_type(struct scsi_disk *sdkp, unsigned char *buffer) if (scsi_status_is_good(res)) { int offset = data.header_length + data.block_descriptor_length; - while (offset < len) { - u8 page_code = buffer[offset] & 0x3F; - u8 spf = buffer[offset] & 0x40; - - if (page_code == 8 || page_code == 6) { - /* We're interested only in the first 3 bytes. - */ - if (len - offset <= 2) { - sd_printk(KERN_ERR, sdkp, "Incomplete " - "mode parameter data\n"); - goto defaults; - } else { - modepage = page_code; - goto Page_found; - } - } else { - /* Go to the next page */ - if (spf && len - offset > 3) - offset += 4 + (buffer[offset+2] << 8) + - buffer[offset+3]; - else if (!spf && len - offset > 1) - offset += 2 + buffer[offset+1]; - else { - sd_printk(KERN_ERR, sdkp, "Incomplete " - "mode parameter data\n"); - goto defaults; - } - } + if (offset >= SD_BUF_SIZE - 2) { + sd_printk(KERN_ERR, sdkp, "Malformed MODE SENSE response\n"); + goto defaults; } - if (modepage == 0x3F) { - sd_printk(KERN_ERR, sdkp, "No Caching mode page " - "present\n"); - goto defaults; - } else if ((buffer[offset] & 0x3f) != modepage) { + if ((buffer[offset] & 0x3f) != modepage) { sd_printk(KERN_ERR, sdkp, "Got wrong page\n"); goto defaults; } - Page_found: + if (modepage == 8) { sdkp->WCE = ((buffer[offset + 2] & 0x04) != 0); sdkp->RCD = ((buffer[offset + 2] & 0x01) != 0); |