Message ID | 20240605022521.3960956-1-martin.petersen@oracle.com (mailing list archive) |
---|---|
State | Accepted |
Headers | show |
Series | [v2] scsi: sd: Use READ(16) when reading block zero on large capacity disks | expand |
On 6/4/24 20:25, Martin K. Petersen wrote: > Commit 321da3dc1f3c ("scsi: sd: usb_storage: uas: Access media prior > to querying device properties") triggered a read to LBA 0 before > attempting to inquire about device characteristics. This was done > because some protocol bridge devices will return generic values until > an attached storage device's media has been accessed. > > Pierre Tomon reported that this change caused problems on a large > capacity external drive connected via a bridge device. The bridge in > question does not appear to implement the READ(10) command. > > Issue a READ(16) instead of READ(10) when a device has been identified > as preferring 16-byte commands (use_16_for_rw heuristic). Reviewed-by: Bart Van Assche <bvanassche@acm.org>
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c index 65cdc8b77e35..22f8841eb5eb 100644 --- a/drivers/scsi/sd.c +++ b/drivers/scsi/sd.c @@ -3572,16 +3572,23 @@ static bool sd_validate_opt_xfer_size(struct scsi_disk *sdkp, static void sd_read_block_zero(struct scsi_disk *sdkp) { - unsigned int buf_len = sdkp->device->sector_size; - char *buffer, cmd[10] = { }; + struct scsi_device *sdev = sdkp->device; + unsigned int buf_len = sdev->sector_size; + u8 *buffer, cmd[16] = { }; buffer = kmalloc(buf_len, GFP_KERNEL); if (!buffer) return; - cmd[0] = READ_10; - put_unaligned_be32(0, &cmd[2]); /* Logical block address 0 */ - put_unaligned_be16(1, &cmd[7]); /* Transfer 1 logical block */ + if (sdev->use_16_for_rw) { + cmd[0] = READ_16; + put_unaligned_be64(0, &cmd[2]); /* Logical block address 0 */ + put_unaligned_be32(1, &cmd[10]);/* Transfer 1 logical block */ + } else { + cmd[0] = READ_10; + put_unaligned_be32(0, &cmd[2]); /* Logical block address 0 */ + put_unaligned_be16(1, &cmd[7]); /* Transfer 1 logical block */ + } scsi_execute_cmd(sdkp->device, cmd, REQ_OP_DRV_IN, buffer, buf_len, SD_TIMEOUT, sdkp->max_retries, NULL);