--- linux/drivers/scsi/sd.c 2005-05-07 16:18:00.000000000 +1000 +++ linux/drivers/scsi/sd.c2612rc4resid 2005-05-08 12:36:34.000000000 +1000 @@ -843,6 +843,9 @@ { int result = SCpnt->result; int this_count = SCpnt->bufflen; + int resid = SCpnt->resid; + int opcode = SCpnt->cmnd[0]; + struct request * req = SCpnt->request; int good_bytes = (result == 0 ? this_count : 0); sector_t block_sectors = 1; u64 first_err_block; @@ -859,12 +862,18 @@ } #ifdef CONFIG_SCSI_LOGGING - SCSI_LOG_HLCOMPLETE(1, printk("sd_rw_intr: %s: res=0x%x\n", - SCpnt->request->rq_disk->disk_name, result)); + SCSI_LOG_HLCOMPLETE(1, printk("sd_rw_intr: %s: opcode=0x%x " + "res=0x%x\n", req->rq_disk->disk_name, + opcode, result)); if (sense_valid) { - SCSI_LOG_HLCOMPLETE(1, printk("sd_rw_intr: sb[respc,sk,asc," - "ascq]=%x,%x,%x,%x\n", sshdr.response_code, - sshdr.sense_key, sshdr.asc, sshdr.ascq)); + SCSI_LOG_HLCOMPLETE(1, printk(" sd_rw_intr: sb[respc,sk,asc," + "ascq]=%x,%x,%x,%x %s\n", + sshdr.response_code, sshdr.sense_key, sshdr.asc, + sshdr.ascq, (sense_deferred ? "DEFERRED" : ""))); + } + if (resid) { + SCSI_LOG_HLCOMPLETE(1, printk(" sd_rw_intr: resid=%d\n", + resid)); } #endif /* @@ -878,13 +887,13 @@ * else if errors, check them, and if necessary prepare for * (partial) retries. */ - if (blk_pc_request(SCpnt->request)) + if (blk_pc_request(req)) good_bytes = this_count; else if (driver_byte(result) != 0 && sense_valid && !sense_deferred) { switch (sshdr.sense_key) { case MEDIUM_ERROR: - if (!blk_fs_request(SCpnt->request)) + if (!blk_fs_request(req)) break; info_valid = scsi_get_sense_info_fld( SCpnt->sense_buffer, SCSI_SENSE_BUFFERSIZE, @@ -894,8 +903,8 @@ * in actual truncation (if sector_t < 64 bits) */ error_sector = (sector_t)first_err_block; - if (SCpnt->request->bio != NULL) - block_sectors = bio_sectors(SCpnt->request->bio); + if (req->bio != NULL) + block_sectors = bio_sectors(req->bio); switch (SCpnt->device->sector_size) { case 1024: error_sector <<= 1; @@ -920,7 +929,7 @@ } error_sector &= ~(block_sectors - 1); - good_bytes = (error_sector - SCpnt->request->sector) << 9; + good_bytes = (error_sector - req->sector) << 9; if (good_bytes < 0 || good_bytes >= this_count) good_bytes = 0; break; @@ -930,6 +939,10 @@ /* * Inform the user, but make sure that it's not treated * as a hard error. + * N.B. This could be a "Failure prediction threshold + * exceeded" type message (depending on MRIE setting + * in IEC mode page). Ignore such a message at your + * peril. */ scsi_print_sense("sd", SCpnt); SCpnt->result = 0; @@ -939,18 +952,45 @@ case ILLEGAL_REQUEST: if (SCpnt->device->use_10_for_rw && - (SCpnt->cmnd[0] == READ_10 || - SCpnt->cmnd[0] == WRITE_10)) + (opcode == READ_10 || opcode == WRITE_10)) SCpnt->device->use_10_for_rw = 0; if (SCpnt->device->use_10_for_ms && - (SCpnt->cmnd[0] == MODE_SENSE_10 || - SCpnt->cmnd[0] == MODE_SELECT_10)) + (opcode == MODE_SENSE_10 || + opcode == MODE_SELECT_10)) SCpnt->device->use_10_for_ms = 0; break; default: break; } + } else if ((resid > 0) && + ((opcode == READ_6) || (opcode == READ_10) || + (opcode == READ_16))) { + /* + * During a read operation the LLD DMA element has indicated + * that less bytes were read than requested. + * Assume truncated DMA transfers on WRITE operations + * are reported by device. + */ + if (req->bio != NULL) + block_sectors = bio_sectors(req->bio); + switch (SCpnt->device->sector_size) { + case 1024: + if (block_sectors < 2) + block_sectors = 2; + break; + case 2048: + if (block_sectors < 4) + block_sectors = 4; + break; + case 4096: + if (block_sectors < 8) + block_sectors = 8; + break; + default: + break; + } + good_bytes = (this_count > resid) ? (this_count - resid) : 0; } /* * This calls the generic completion function, now that we know