Skip to content

Commit 72add98

Browse files
committed
scsi: core: Consult supported VPD page list prior to fetching page
jira LE-2349 Rebuild_History Non-Buildable kernel-4.18.0-553.37.1.el8_10 commit-author Martin K. Petersen <martin.petersen@oracle.com> commit b5fc07a Commit c92a6b5 ("scsi: core: Query VPD size before getting full page") removed the logic which checks whether a VPD page is present on the supported pages list before asking for the page itself. That was done because SPC helpfully states "The Supported VPD Pages VPD page list may or may not include all the VPD pages that are able to be returned by the device server". Testing had revealed a few devices that supported some of the 0xBn pages but didn't actually list them in page 0. Julian Sikorski bisected a problem with his drive resetting during discovery to the commit above. As it turns out, this particular drive firmware will crash if we attempt to fetch page 0xB9. Various approaches were attempted to work around this. In the end, reinstating the logic that consults VPD page 0 before fetching any other page was the path of least resistance. A firmware update for the devices which originally compelled us to remove the check has since been released. Link: https://lore.kernel.org/r/20240214221411.2888112-1-martin.petersen@oracle.com Fixes: c92a6b5 ("scsi: core: Query VPD size before getting full page") Cc: stable@vger.kernel.org Cc: Bart Van Assche <bvanassche@acm.org> Reported-by: Julian Sikorski <belegdol@gmail.com> Tested-by: Julian Sikorski <belegdol@gmail.com> Reviewed-by: Lee Duncan <lee.duncan@suse.com> Reviewed-by: Bart Van Assche <bvanassche@acm.org> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com> (cherry picked from commit b5fc07a) Signed-off-by: Jonathan Maple <jmaple@ciq.com>
1 parent ced9f6b commit 72add98

File tree

2 files changed

+20
-6
lines changed

2 files changed

+20
-6
lines changed

drivers/scsi/scsi.c

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -379,21 +379,39 @@ static int scsi_vpd_inquiry(struct scsi_device *sdev, unsigned char *buffer,
379379
return result + 4;
380380
}
381381

382+
enum scsi_vpd_parameters {
383+
SCSI_VPD_HEADER_SIZE = 4,
384+
SCSI_VPD_LIST_SIZE = 36,
385+
};
386+
382387
static int scsi_get_vpd_size(struct scsi_device *sdev, u8 page)
383388
{
384-
unsigned char vpd_header[SCSI_VPD_HEADER_SIZE] __aligned(4);
389+
unsigned char vpd[SCSI_VPD_LIST_SIZE] __aligned(4);
385390
int result;
386391

387392
if (sdev->no_vpd_size)
388393
return SCSI_DEFAULT_VPD_LEN;
389394

395+
/*
396+
* Fetch the supported pages VPD and validate that the requested page
397+
* number is present.
398+
*/
399+
if (page != 0) {
400+
result = scsi_vpd_inquiry(sdev, vpd, 0, sizeof(vpd));
401+
if (result < SCSI_VPD_HEADER_SIZE)
402+
return 0;
403+
404+
result -= SCSI_VPD_HEADER_SIZE;
405+
if (!memchr(&vpd[SCSI_VPD_HEADER_SIZE], page, result))
406+
return 0;
407+
}
390408
/*
391409
* Fetch the VPD page header to find out how big the page
392410
* is. This is done to prevent problems on legacy devices
393411
* which can not handle allocation lengths as large as
394412
* potentially requested by the caller.
395413
*/
396-
result = scsi_vpd_inquiry(sdev, vpd_header, page, sizeof(vpd_header));
414+
result = scsi_vpd_inquiry(sdev, vpd, page, SCSI_VPD_HEADER_SIZE);
397415
if (result < 0)
398416
return 0;
399417

include/scsi/scsi_device.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -101,10 +101,6 @@ struct scsi_vpd {
101101
unsigned char data[];
102102
};
103103

104-
enum scsi_vpd_parameters {
105-
SCSI_VPD_HEADER_SIZE = 4,
106-
};
107-
108104
struct scsi_device {
109105
struct Scsi_Host *host;
110106
struct request_queue *request_queue;

0 commit comments

Comments
 (0)