Skip to content

Commit 7926d51

Browse files
scsi: sd: Use READ(16) when reading block zero on large capacity disks
Commit 321da3d ("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). Link: https://bugzilla.kernel.org/show_bug.cgi?id=218890 Link: https://lore.kernel.org/r/70dd7ae0-b6b1-48e1-bb59-53b7c7f18274@rowland.harvard.edu Link: https://lore.kernel.org/r/20240605022521.3960956-1-martin.petersen@oracle.com Fixes: 321da3d ("scsi: sd: usb_storage: uas: Access media prior to querying device properties") Cc: stable@vger.kernel.org Reported-by: Pierre Tomon <pierretom+12@ik.me> Suggested-by: Alan Stern <stern@rowland.harvard.edu> Tested-by: Pierre Tomon <pierretom+12@ik.me> Reviewed-by: Bart Van Assche <bvanassche@acm.org> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent d53b681 commit 7926d51

File tree

1 file changed

+12
-5
lines changed

1 file changed

+12
-5
lines changed

drivers/scsi/sd.c

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3565,16 +3565,23 @@ static bool sd_validate_opt_xfer_size(struct scsi_disk *sdkp,
35653565

35663566
static void sd_read_block_zero(struct scsi_disk *sdkp)
35673567
{
3568-
unsigned int buf_len = sdkp->device->sector_size;
3569-
char *buffer, cmd[10] = { };
3568+
struct scsi_device *sdev = sdkp->device;
3569+
unsigned int buf_len = sdev->sector_size;
3570+
u8 *buffer, cmd[16] = { };
35703571

35713572
buffer = kmalloc(buf_len, GFP_KERNEL);
35723573
if (!buffer)
35733574
return;
35743575

3575-
cmd[0] = READ_10;
3576-
put_unaligned_be32(0, &cmd[2]); /* Logical block address 0 */
3577-
put_unaligned_be16(1, &cmd[7]); /* Transfer 1 logical block */
3576+
if (sdev->use_16_for_rw) {
3577+
cmd[0] = READ_16;
3578+
put_unaligned_be64(0, &cmd[2]); /* Logical block address 0 */
3579+
put_unaligned_be32(1, &cmd[10]);/* Transfer 1 logical block */
3580+
} else {
3581+
cmd[0] = READ_10;
3582+
put_unaligned_be32(0, &cmd[2]); /* Logical block address 0 */
3583+
put_unaligned_be16(1, &cmd[7]); /* Transfer 1 logical block */
3584+
}
35783585

35793586
scsi_execute_cmd(sdkp->device, cmd, REQ_OP_DRV_IN, buffer, buf_len,
35803587
SD_TIMEOUT, sdkp->max_retries, NULL);

0 commit comments

Comments
 (0)