Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

scsi: sd: Use READ(16) when reading block zero on large capacity disks

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).

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: 321da3dc1f3c ("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>

+12 -5
+12 -5
drivers/scsi/sd.c
··· 3565 3565 3566 3566 static void sd_read_block_zero(struct scsi_disk *sdkp) 3567 3567 { 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] = { }; 3570 3571 3571 3572 buffer = kmalloc(buf_len, GFP_KERNEL); 3572 3573 if (!buffer) 3573 3574 return; 3574 3575 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 + } 3578 3585 3579 3586 scsi_execute_cmd(sdkp->device, cmd, REQ_OP_DRV_IN, buffer, buf_len, 3580 3587 SD_TIMEOUT, sdkp->max_retries, NULL);