[SCSI] sd/scsi_lib simplify sd_rw_intr and scsi_io_completion
This patch simplifies "good_bytes" computation in sd_rw_intr(). sd: "good_bytes" computation is always done in terms of the resolution of the device's medium, since after that it is the number of good bytes we pass around and other layers/contexts (as opposed ot sd) can translate that to their own resolution (block layer:512). It also makes scsi_io_completion() processing more straightforward, eliminating the 3rd argument to the function. It also fixes a couple of bugs like not checking return value, using "break" instead of "return;", etc. I've been running with this patch for some time now on a test (do-it-all) system. Signed-off-by: Luben Tuikov <ltuikov@yahoo.com> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
This commit is contained in:
committed by
James Bottomley
parent
f89d0a4e1d
commit
03aba2f795
@@ -891,11 +891,10 @@ static struct block_device_operations sd_fops = {
|
||||
static void sd_rw_intr(struct scsi_cmnd * SCpnt)
|
||||
{
|
||||
int result = SCpnt->result;
|
||||
int this_count = SCpnt->request_bufflen;
|
||||
int good_bytes = (result == 0 ? this_count : 0);
|
||||
sector_t block_sectors = 1;
|
||||
u64 first_err_block;
|
||||
sector_t error_sector;
|
||||
unsigned int xfer_size = SCpnt->request_bufflen;
|
||||
unsigned int good_bytes = result ? 0 : xfer_size;
|
||||
u64 start_lba = SCpnt->request->sector;
|
||||
u64 bad_lba;
|
||||
struct scsi_sense_hdr sshdr;
|
||||
int sense_valid = 0;
|
||||
int sense_deferred = 0;
|
||||
@@ -906,7 +905,6 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt)
|
||||
if (sense_valid)
|
||||
sense_deferred = scsi_sense_is_deferred(&sshdr);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SCSI_LOGGING
|
||||
SCSI_LOG_HLCOMPLETE(1, printk("sd_rw_intr: %s: res=0x%x\n",
|
||||
SCpnt->request->rq_disk->disk_name, result));
|
||||
@@ -916,89 +914,72 @@ static void sd_rw_intr(struct scsi_cmnd * SCpnt)
|
||||
sshdr.sense_key, sshdr.asc, sshdr.ascq));
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
Handle MEDIUM ERRORs that indicate partial success. Since this is a
|
||||
relatively rare error condition, no care is taken to avoid
|
||||
unnecessary additional work such as memcpy's that could be avoided.
|
||||
*/
|
||||
if (driver_byte(result) != 0 &&
|
||||
sense_valid && !sense_deferred) {
|
||||
switch (sshdr.sense_key) {
|
||||
case MEDIUM_ERROR:
|
||||
if (!blk_fs_request(SCpnt->request))
|
||||
break;
|
||||
info_valid = scsi_get_sense_info_fld(
|
||||
SCpnt->sense_buffer, SCSI_SENSE_BUFFERSIZE,
|
||||
&first_err_block);
|
||||
/*
|
||||
* May want to warn and skip if following cast results
|
||||
* 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);
|
||||
switch (SCpnt->device->sector_size) {
|
||||
case 1024:
|
||||
error_sector <<= 1;
|
||||
if (block_sectors < 2)
|
||||
block_sectors = 2;
|
||||
break;
|
||||
case 2048:
|
||||
error_sector <<= 2;
|
||||
if (block_sectors < 4)
|
||||
block_sectors = 4;
|
||||
break;
|
||||
case 4096:
|
||||
error_sector <<=3;
|
||||
if (block_sectors < 8)
|
||||
block_sectors = 8;
|
||||
break;
|
||||
case 256:
|
||||
error_sector >>= 1;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (driver_byte(result) != DRIVER_SENSE &&
|
||||
(!sense_valid || sense_deferred))
|
||||
goto out;
|
||||
|
||||
error_sector &= ~(block_sectors - 1);
|
||||
good_bytes = (error_sector - SCpnt->request->sector) << 9;
|
||||
if (good_bytes < 0 || good_bytes >= this_count)
|
||||
good_bytes = 0;
|
||||
switch (sshdr.sense_key) {
|
||||
case HARDWARE_ERROR:
|
||||
case MEDIUM_ERROR:
|
||||
if (!blk_fs_request(SCpnt->request))
|
||||
goto out;
|
||||
info_valid = scsi_get_sense_info_fld(SCpnt->sense_buffer,
|
||||
SCSI_SENSE_BUFFERSIZE,
|
||||
&bad_lba);
|
||||
if (!info_valid)
|
||||
goto out;
|
||||
if (xfer_size <= SCpnt->device->sector_size)
|
||||
goto out;
|
||||
switch (SCpnt->device->sector_size) {
|
||||
case 256:
|
||||
start_lba <<= 1;
|
||||
break;
|
||||
|
||||
case RECOVERED_ERROR: /* an error occurred, but it recovered */
|
||||
case NO_SENSE: /* LLDD got sense data */
|
||||
/*
|
||||
* Inform the user, but make sure that it's not treated
|
||||
* as a hard error.
|
||||
*/
|
||||
scsi_print_sense("sd", SCpnt);
|
||||
SCpnt->result = 0;
|
||||
memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
|
||||
good_bytes = this_count;
|
||||
case 512:
|
||||
break;
|
||||
|
||||
case ILLEGAL_REQUEST:
|
||||
if (SCpnt->device->use_10_for_rw &&
|
||||
(SCpnt->cmnd[0] == READ_10 ||
|
||||
SCpnt->cmnd[0] == 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))
|
||||
SCpnt->device->use_10_for_ms = 0;
|
||||
case 1024:
|
||||
start_lba >>= 1;
|
||||
break;
|
||||
case 2048:
|
||||
start_lba >>= 2;
|
||||
break;
|
||||
case 4096:
|
||||
start_lba >>= 3;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Print something here with limiting frequency. */
|
||||
goto out;
|
||||
break;
|
||||
}
|
||||
/* This computation should always be done in terms of
|
||||
* the resolution of the device's medium.
|
||||
*/
|
||||
good_bytes = (bad_lba - start_lba)*SCpnt->device->sector_size;
|
||||
break;
|
||||
case RECOVERED_ERROR:
|
||||
case NO_SENSE:
|
||||
/* Inform the user, but make sure that it's not treated
|
||||
* as a hard error.
|
||||
*/
|
||||
scsi_print_sense("sd", SCpnt);
|
||||
SCpnt->result = 0;
|
||||
memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);
|
||||
good_bytes = xfer_size;
|
||||
break;
|
||||
case ILLEGAL_REQUEST:
|
||||
if (SCpnt->device->use_10_for_rw &&
|
||||
(SCpnt->cmnd[0] == READ_10 ||
|
||||
SCpnt->cmnd[0] == 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))
|
||||
SCpnt->device->use_10_for_ms = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* This calls the generic completion function, now that we know
|
||||
* how many actual sectors finished, and how many sectors we need
|
||||
* to say have failed.
|
||||
*/
|
||||
scsi_io_completion(SCpnt, good_bytes, block_sectors << 9);
|
||||
out:
|
||||
scsi_io_completion(SCpnt, good_bytes);
|
||||
}
|
||||
|
||||
static int media_not_present(struct scsi_disk *sdkp,
|
||||
|
Reference in New Issue
Block a user