Re: [PATCH] scsi: sd: usb_storage: uas: Access media prior to querying device properties

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Tue, Feb 13, 2024 at 9:33 AM Martin K. Petersen
<martin.petersen@xxxxxxxxxx> wrote:
>
> It has been observed that some USB/UAS devices return generic
> properties hardcoded in firmware for mode pages and vital product data
> for a period of time after a device has been discovered. The reported
> properties are either garbage or they do not accurately reflect the
> properties of the physical storage device attached in the case of a
> bridge.
>
> Prior to commit 1e029397d12f ("scsi: sd: Reorganize DIF/DIX code to
> avoid calling revalidate twice") we would call revalidate several
> times during device discovery. As a result, incorrect values would
> eventually get replaced with ones accurately describing the attached
> storage. When we did away with the redundant revalidate pass, several
> cases were reported where devices reported nonsensical values or would
> end up in write-protected state.
>
> An initial attempt at addressing this issue involved introducing a
> delayed second revalidate invocation. However, this approach still
> left some devices reporting incorrect characteristics.
>
> Tasos Sahanidis debugged the problem further and identified that
> introducing a READ operation prior to MODE SENSE fixed the problem and
> that it wasn't a timing issue. Issuing a READ appears to cause the
> devices to update their SCSI pages to reflect the actual properties of
> the storage media. Device properties like vendor, model, and storage
> capacity appear to be correctly reported from the get-go. It is
> unclear why these device defer populating the remaining
> characteristics.
>
> Match the behavior of a well known commercial operating system and
> trigger a READ operation prior to querying device characteristics to
> force the device to populate mode pages and VPDs.
>
> The additional READ is triggered by a flag set in the USB storage and
> UAS drivers. We avoid issuing the READ for other transport classes
> since some storage devices identify Linux through our particular
> discovery command sequence.
>
> Cc: <stable@xxxxxxxxxxxxxxx>
> Fixes: 1e029397d12f ("scsi: sd: Reorganize DIF/DIX code to avoid calling revalidate twice")
> Reported-by: Tasos Sahanidis <tasos@xxxxxxxxxxxx>
> Signed-off-by: Martin K. Petersen <martin.petersen@xxxxxxxxxx>
> ---
>  drivers/scsi/sd.c              | 27 ++++++++++++++++++++++++++-
>  drivers/usb/storage/scsiglue.c |  7 +++++++
>  drivers/usb/storage/uas.c      |  7 +++++++
>  include/scsi/scsi_device.h     |  1 +
>  4 files changed, 41 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
> index 530918cbfce2..c284628f702c 100644
> --- a/drivers/scsi/sd.c
> +++ b/drivers/scsi/sd.c
> @@ -3405,6 +3405,24 @@ static bool sd_validate_opt_xfer_size(struct scsi_disk *sdkp,
>         return true;
>  }
>
> +static void sd_read_block_zero(struct scsi_disk *sdkp)
> +{
> +       unsigned int buf_len = sdkp->device->sector_size;
> +       char *buffer, cmd[10] = { };
> +
> +       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 */
> +
> +       scsi_execute_cmd(sdkp->device, cmd, REQ_OP_DRV_IN, buffer, buf_len,
> +                        SD_TIMEOUT, sdkp->max_retries, NULL);
> +       kfree(buffer);
> +}
> +
>  /**
>   *     sd_revalidate_disk - called the first time a new disk is seen,
>   *     performs disk spin up, read_capacity, etc.
> @@ -3444,7 +3462,14 @@ static int sd_revalidate_disk(struct gendisk *disk)
>          */
>         if (sdkp->media_present) {
>                 sd_read_capacity(sdkp, buffer);
> -
> +               /*
> +                * Some USB/UAS devices return generic values for mode pages
> +                * and VPDs until the media has been accessed. Trigger a READ
> +                * operation to force the device to populate mode pages and
> +                * VPDs.
> +                */
> +               if (sdp->read_before_ms)
> +                       sd_read_block_zero(sdkp);
>                 /*
>                  * set the default to rotational.  All non-rotational devices
>                  * support the block characteristics VPD page, which will
> diff --git a/drivers/usb/storage/scsiglue.c b/drivers/usb/storage/scsiglue.c
> index c54e9805da53..12cf9940e5b6 100644
> --- a/drivers/usb/storage/scsiglue.c
> +++ b/drivers/usb/storage/scsiglue.c
> @@ -179,6 +179,13 @@ static int slave_configure(struct scsi_device *sdev)
>                  */
>                 sdev->use_192_bytes_for_3f = 1;
>
> +               /*
> +                * Some devices report generic values until the media has been
> +                * accessed. Force a READ(10) prior to querying device
> +                * characteristics.
> +                */
> +               sdev->read_before_ms = 1;
> +
>                 /*
>                  * Some devices don't like MODE SENSE with page=0x3f,
>                  * which is the command used for checking if a device
> diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
> index 696bb0b23599..299a6767b7b3 100644
> --- a/drivers/usb/storage/uas.c
> +++ b/drivers/usb/storage/uas.c
> @@ -878,6 +878,13 @@ static int uas_slave_configure(struct scsi_device *sdev)
>         if (devinfo->flags & US_FL_CAPACITY_HEURISTICS)
>                 sdev->guess_capacity = 1;
>
> +       /*
> +        * Some devices report generic values until the media has been
> +        * accessed. Force a READ(10) prior to querying device
> +        * characteristics.
> +        */
> +       sdev->read_before_ms = 1;
> +
>         /*
>          * Some devices don't like MODE SENSE with page=0x3f,
>          * which is the command used for checking if a device
> diff --git a/include/scsi/scsi_device.h b/include/scsi/scsi_device.h
> index 10480eb582b2..cb019c80763b 100644
> --- a/include/scsi/scsi_device.h
> +++ b/include/scsi/scsi_device.h
> @@ -202,6 +202,7 @@ struct scsi_device {
>         unsigned use_10_for_rw:1; /* first try 10-byte read / write */
>         unsigned use_10_for_ms:1; /* first try 10-byte mode sense/select */
>         unsigned set_dbd_for_ms:1; /* Set "DBD" field in mode sense */
> +       unsigned read_before_ms:1;      /* perform a READ before MODE SENSE */
>         unsigned no_report_opcodes:1;   /* no REPORT SUPPORTED OPERATION CODES */
>         unsigned no_write_same:1;       /* no WRITE SAME command */
>         unsigned use_16_for_rw:1; /* Use read/write(16) over read/write(10) */
> --
> 2.42.1
>
>

So the READ CAPACITY is correct but the VPD pages etc are not?  OK.

Reviewed-by: Ewan D. Milne <emilne@xxxxxxxxxx>






[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [SCSI Target Devel]     [Linux SCSI Target Infrastructure]     [Kernel Newbies]     [IDE]     [Security]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Linux RAID]     [Linux ATA RAID]     [Linux IIO]     [Samba]     [Device Mapper]

  Powered by Linux