diff options
Diffstat (limited to 'drivers/scsi/sd.c')
| -rw-r--r-- | drivers/scsi/sd.c | 54 | 
1 files changed, 30 insertions, 24 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 255da53e5a0..1dd4d840769 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -1196,19 +1196,10 @@ static int sd_done(struct scsi_cmnd *SCpnt)  		SCpnt->result = 0;  		memset(SCpnt->sense_buffer, 0, SCSI_SENSE_BUFFERSIZE);  		break; -	case ABORTED_COMMAND: -		if (sshdr.asc == 0x10) { /* DIF: Disk detected corruption */ -			scsi_print_result(SCpnt); -			scsi_print_sense("sd", SCpnt); +	case ABORTED_COMMAND: /* DIF: Target detected corruption */ +	case ILLEGAL_REQUEST: /* DIX: Host detected corruption */ +		if (sshdr.asc == 0x10)  			good_bytes = sd_completed_bytes(SCpnt); -		} -		break; -	case ILLEGAL_REQUEST: -		if (sshdr.asc == 0x10) { /* DIX: HBA detected corruption */ -			scsi_print_result(SCpnt); -			scsi_print_sense("sd", SCpnt); -			good_bytes = sd_completed_bytes(SCpnt); -		}  		break;  	default:  		break; @@ -1218,8 +1209,19 @@ static int sd_done(struct scsi_cmnd *SCpnt)  		sd_dif_complete(SCpnt, good_bytes);  	if (scsi_host_dif_capable(sdkp->device->host, sdkp->protection_type) -	    == SD_DIF_TYPE2_PROTECTION && SCpnt->cmnd != SCpnt->request->cmd) +	    == SD_DIF_TYPE2_PROTECTION && SCpnt->cmnd != SCpnt->request->cmd) { + +		/* We have to print a failed command here as the +		 * extended CDB gets freed before scsi_io_completion() +		 * is called. +		 */ +		if (result) +			scsi_print_command(SCpnt); +  		mempool_free(SCpnt->cmnd, sd_cdb_pool); +		SCpnt->cmnd = NULL; +		SCpnt->cmd_len = 0; +	}  	return good_bytes;  } @@ -1946,13 +1948,13 @@ static void sd_read_block_limits(struct scsi_disk *sdkp)  {  	struct request_queue *q = sdkp->disk->queue;  	unsigned int sector_sz = sdkp->device->sector_size; -	char *buffer; +	const int vpd_len = 32; +	unsigned char *buffer = kmalloc(vpd_len, GFP_KERNEL); -	/* Block Limits VPD */ -	buffer = scsi_get_vpd_page(sdkp->device, 0xb0); - -	if (buffer == NULL) -		return; +	if (!buffer || +	    /* Block Limits VPD */ +	    scsi_get_vpd_page(sdkp->device, 0xb0, buffer, vpd_len)) +		goto out;  	blk_queue_io_min(sdkp->disk->queue,  			 get_unaligned_be16(&buffer[6]) * sector_sz); @@ -1984,6 +1986,7 @@ static void sd_read_block_limits(struct scsi_disk *sdkp)  				get_unaligned_be32(&buffer[32]) & ~(1 << 31);  	} + out:  	kfree(buffer);  } @@ -1993,20 +1996,23 @@ static void sd_read_block_limits(struct scsi_disk *sdkp)   */  static void sd_read_block_characteristics(struct scsi_disk *sdkp)  { -	char *buffer; +	unsigned char *buffer;  	u16 rot; +	const int vpd_len = 32; -	/* Block Device Characteristics VPD */ -	buffer = scsi_get_vpd_page(sdkp->device, 0xb1); +	buffer = kmalloc(vpd_len, GFP_KERNEL); -	if (buffer == NULL) -		return; +	if (!buffer || +	    /* Block Device Characteristics VPD */ +	    scsi_get_vpd_page(sdkp->device, 0xb1, buffer, vpd_len)) +		goto out;  	rot = get_unaligned_be16(&buffer[4]);  	if (rot == 1)  		queue_flag_set_unlocked(QUEUE_FLAG_NONROT, sdkp->disk->queue); + out:  	kfree(buffer);  }  |