mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-08 03:40:35 +09:00
ata: libata-scsi: Fix ata_scsi_dev_rescan() error path
commit 79336504781e7fee5ddaf046dcc186c8dfdf60b1 upstream.
Commit 0c76106cb975 ("scsi: sd: Fix TCG OPAL unlock on system resume")
incorrectly handles failures of scsi_resume_device() in
ata_scsi_dev_rescan(), leading to a double call to
spin_unlock_irqrestore() to unlock a device port. Fix this by redefining
the goto labels used in case of errors and only unlock the port
scsi_scan_mutex when scsi_resume_device() fails.
Bug found with the Smatch static checker warning:
drivers/ata/libata-scsi.c:4774 ata_scsi_dev_rescan()
error: double unlocked 'ap->lock' (orig line 4757)
Reported-by: Dan Carpenter <dan.carpenter@linaro.org>
Fixes: 0c76106cb975 ("scsi: sd: Fix TCG OPAL unlock on system resume")
Cc: stable@vger.kernel.org
Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
Reviewed-by: Niklas Cassel <cassel@kernel.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
ca5962bdc5
commit
0559b2d759
@@ -4667,7 +4667,7 @@ void ata_scsi_dev_rescan(struct work_struct *work)
|
|||||||
* bail out.
|
* bail out.
|
||||||
*/
|
*/
|
||||||
if (ap->pflags & ATA_PFLAG_SUSPENDED)
|
if (ap->pflags & ATA_PFLAG_SUSPENDED)
|
||||||
goto unlock;
|
goto unlock_ap;
|
||||||
|
|
||||||
if (!sdev)
|
if (!sdev)
|
||||||
continue;
|
continue;
|
||||||
@@ -4680,7 +4680,7 @@ void ata_scsi_dev_rescan(struct work_struct *work)
|
|||||||
if (do_resume) {
|
if (do_resume) {
|
||||||
ret = scsi_resume_device(sdev);
|
ret = scsi_resume_device(sdev);
|
||||||
if (ret == -EWOULDBLOCK)
|
if (ret == -EWOULDBLOCK)
|
||||||
goto unlock;
|
goto unlock_scan;
|
||||||
dev->flags &= ~ATA_DFLAG_RESUMING;
|
dev->flags &= ~ATA_DFLAG_RESUMING;
|
||||||
}
|
}
|
||||||
ret = scsi_rescan_device(sdev);
|
ret = scsi_rescan_device(sdev);
|
||||||
@@ -4688,12 +4688,13 @@ void ata_scsi_dev_rescan(struct work_struct *work)
|
|||||||
spin_lock_irqsave(ap->lock, flags);
|
spin_lock_irqsave(ap->lock, flags);
|
||||||
|
|
||||||
if (ret)
|
if (ret)
|
||||||
goto unlock;
|
goto unlock_ap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unlock:
|
unlock_ap:
|
||||||
spin_unlock_irqrestore(ap->lock, flags);
|
spin_unlock_irqrestore(ap->lock, flags);
|
||||||
|
unlock_scan:
|
||||||
mutex_unlock(&ap->scsi_scan_mutex);
|
mutex_unlock(&ap->scsi_scan_mutex);
|
||||||
|
|
||||||
/* Reschedule with a delay if scsi_rescan_device() returned an error */
|
/* Reschedule with a delay if scsi_rescan_device() returned an error */
|
||||||
|
|||||||
Reference in New Issue
Block a user