• Martin K. Petersen's avatar
    scsi: core: Query VPD size before getting full page · c92a6b5d
    Martin K. Petersen authored
    We currently default to 255 bytes when fetching VPD pages during discovery.
    However, we have had a few devices that are known to wedge if the requested
    buffer exceeds a certain size. See commit af73623f ("[SCSI] sd: Reduce
    buffer size for vpd request") which works around one example of this
    problem in the SCSI disk driver.
    
    With commit d188b067 ("scsi: core: Add sysfs attributes for VPD pages
    0h and 89h") we now risk triggering the same issue in the generic midlayer
    code.
    
    The problem with the ATA VPD page in particular is that the SCSI portion of
    the page is trailed by 512 bytes of verbatim ATA Identify Device
    information.  However, not all controllers actually provide the additional
    512 bytes and will lock up if one asks for more than the 64 bytes
    containing the SCSI protocol fields.
    
    Instead of picking a new, somewhat arbitrary, number of bytes for the VPD
    buffer size, start fetching the 4-byte header for each page. The header
    contains the size of the page as far as the device is concerned. We can use
    the reported size to specify the correct allocation length when
    subsequently fetching the full page.
    
    The header validation is done by a new helper function scsi_get_vpd_size()
    and both scsi_get_vpd_page() and scsi_get_vpd_buf() now rely on this to
    query the page size.
    
    In addition, scsi_get_vpd_page() is simplified to mirror the logic in
    scsi_get_vpd_page(). This involves removing the Supported VPD Pages lookup
    prior to attempting to query a page. There does not appear any evidence,
    even in the oldest SCSI specs, that this step is required. We already rely
    on scsi_get_vpd_page() throughout the stack and this function never
    consulted the Supported VPD Pages. Since this has not caused any problems
    it should be safe to remove the precondition from scsi_get_vpd_page().
    
    Instrumented runs also revealed that the Supported VPD Pages lookup had
    little effect since the device page index often was larger than the
    supplied buffer size. As a result, inquiries frequently bypassed the index
    check and went through the "If we ran off the end of the buffer, give us
    the benefit of the doubt" code path which assumed the page was present
    despite not being listed. The revised code takes both the page size
    reported by the device as well as the size of the buffer provided by the
    scsi_get_vpd_page() caller into account.
    
    Link: https://lore.kernel.org/r/20220302053559.32147-3-martin.petersen@oracle.com
    Fixes: d188b067 ("scsi: core: Add sysfs attributes for VPD pages 0h and 89h")
    Reported-by: default avatarMaciej W. Rozycki <macro@orcam.me.uk>
    Tested-by: default avatarMaciej W. Rozycki <macro@orcam.me.uk>
    Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
    Signed-off-by: default avatarMartin K. Petersen <martin.petersen@oracle.com>
    c92a6b5d
scsi.c 22.8 KB