Skip to content

Commit 3b83486

Browse files
mikechristiemartinkpetersen
authored andcommitted
scsi: sd: Fix sshdr use in sd_suspend_common()
If scsi_execute_cmd() returns < 0, it doesn't initialize the sshdr, so we shouldn't access the sshdr. If it returns 0, then the cmd executed successfully, so there is no need to check the sshdr. sd_sync_cache() will only access the sshdr if it's been setup because it calls scsi_status_is_check_condition() before accessing it. However, the sd_sync_cache() caller, sd_suspend_common(), does not check. sd_suspend_common() is only checking for ILLEGAL_REQUEST which it's using to determine if the command is supported. If it's not it just ignores the error. So to fix its sshdr use this patch just moves that check to sd_sync_cache() where it converts ILLEGAL_REQUEST to success/0. sd_suspend_common() was ignoring that error and sd_shutdown() doesn't check for errors so there will be no behavior changes. Signed-off-by: Mike Christie <michael.christie@oracle.com> Link: https://lore.kernel.org/r/20231106231304.5694-2-michael.christie@oracle.com Reviewed-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Martin Wilck <mwilck@suse.com> Reviewed-by: Bart Van Assche <bvanassche@acm.org> Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>
1 parent 037fbd3 commit 3b83486

File tree

1 file changed

+23
-30
lines changed

1 file changed

+23
-30
lines changed

drivers/scsi/sd.c

Lines changed: 23 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1565,24 +1565,21 @@ static unsigned int sd_check_events(struct gendisk *disk, unsigned int clearing)
15651565
return disk_changed ? DISK_EVENT_MEDIA_CHANGE : 0;
15661566
}
15671567

1568-
static int sd_sync_cache(struct scsi_disk *sdkp, struct scsi_sense_hdr *sshdr)
1568+
static int sd_sync_cache(struct scsi_disk *sdkp)
15691569
{
15701570
int retries, res;
15711571
struct scsi_device *sdp = sdkp->device;
15721572
const int timeout = sdp->request_queue->rq_timeout
15731573
* SD_FLUSH_TIMEOUT_MULTIPLIER;
1574-
struct scsi_sense_hdr my_sshdr;
1574+
struct scsi_sense_hdr sshdr;
15751575
const struct scsi_exec_args exec_args = {
15761576
.req_flags = BLK_MQ_REQ_PM,
1577-
/* caller might not be interested in sense, but we need it */
1578-
.sshdr = sshdr ? : &my_sshdr,
1577+
.sshdr = &sshdr,
15791578
};
15801579

15811580
if (!scsi_device_online(sdp))
15821581
return -ENODEV;
15831582

1584-
sshdr = exec_args.sshdr;
1585-
15861583
for (retries = 3; retries > 0; --retries) {
15871584
unsigned char cmd[16] = { 0 };
15881585

@@ -1607,15 +1604,23 @@ static int sd_sync_cache(struct scsi_disk *sdkp, struct scsi_sense_hdr *sshdr)
16071604
return res;
16081605

16091606
if (scsi_status_is_check_condition(res) &&
1610-
scsi_sense_valid(sshdr)) {
1611-
sd_print_sense_hdr(sdkp, sshdr);
1607+
scsi_sense_valid(&sshdr)) {
1608+
sd_print_sense_hdr(sdkp, &sshdr);
16121609

16131610
/* we need to evaluate the error return */
1614-
if (sshdr->asc == 0x3a || /* medium not present */
1615-
sshdr->asc == 0x20 || /* invalid command */
1616-
(sshdr->asc == 0x74 && sshdr->ascq == 0x71)) /* drive is password locked */
1611+
if (sshdr.asc == 0x3a || /* medium not present */
1612+
sshdr.asc == 0x20 || /* invalid command */
1613+
(sshdr.asc == 0x74 && sshdr.ascq == 0x71)) /* drive is password locked */
16171614
/* this is no error here */
16181615
return 0;
1616+
/*
1617+
* This drive doesn't support sync and there's not much
1618+
* we can do because this is called during shutdown
1619+
* or suspend so just return success so those operations
1620+
* can proceed.
1621+
*/
1622+
if (sshdr.sense_key == ILLEGAL_REQUEST)
1623+
return 0;
16191624
}
16201625

16211626
switch (host_byte(res)) {
@@ -3774,7 +3779,7 @@ static void sd_shutdown(struct device *dev)
37743779

37753780
if (sdkp->WCE && sdkp->media_present) {
37763781
sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
3777-
sd_sync_cache(sdkp, NULL);
3782+
sd_sync_cache(sdkp);
37783783
}
37793784

37803785
if (system_state != SYSTEM_RESTART && sdkp->device->manage_start_stop) {
@@ -3786,7 +3791,6 @@ static void sd_shutdown(struct device *dev)
37863791
static int sd_suspend_common(struct device *dev, bool ignore_stop_errors)
37873792
{
37883793
struct scsi_disk *sdkp = dev_get_drvdata(dev);
3789-
struct scsi_sense_hdr sshdr;
37903794
int ret = 0;
37913795

37923796
if (!sdkp) /* E.g.: runtime suspend following sd_remove() */
@@ -3795,24 +3799,13 @@ static int sd_suspend_common(struct device *dev, bool ignore_stop_errors)
37953799
if (sdkp->WCE && sdkp->media_present) {
37963800
if (!sdkp->device->silence_suspend)
37973801
sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
3798-
ret = sd_sync_cache(sdkp, &sshdr);
3799-
3800-
if (ret) {
3801-
/* ignore OFFLINE device */
3802-
if (ret == -ENODEV)
3803-
return 0;
3804-
3805-
if (!scsi_sense_valid(&sshdr) ||
3806-
sshdr.sense_key != ILLEGAL_REQUEST)
3807-
return ret;
3802+
ret = sd_sync_cache(sdkp);
3803+
/* ignore OFFLINE device */
3804+
if (ret == -ENODEV)
3805+
return 0;
38083806

3809-
/*
3810-
* sshdr.sense_key == ILLEGAL_REQUEST means this drive
3811-
* doesn't support sync. There's not much to do and
3812-
* suspend shouldn't fail.
3813-
*/
3814-
ret = 0;
3815-
}
3807+
if (ret)
3808+
return ret;
38163809
}
38173810

38183811
if (sdkp->device->manage_start_stop) {

0 commit comments

Comments
 (0)