Skip to content

Commit

Permalink
SCSI: fix crashes in sd and sr runtime PM
Browse files Browse the repository at this point in the history
Runtime suspend during driver probe and removal can cause problems.
The driver's runtime_suspend or runtime_resume callbacks may invoked
before the driver has finished binding to the device or after the
driver has unbound from the device.

This problem shows up with the sd and sr drivers, and can cause disk
or CD/DVD drives to become unusable as a result.  The fix is simple.
The drivers store a pointer to the scsi_disk or scsi_cd structure as
their private device data when probing is finished, so we simply have
to be sure to clear the private data during removal and test it during
runtime suspend/resume.

This fixes <https://bugs.debian.org/801925>.

Signed-off-by: Alan Stern <stern@rowland.harvard.edu>
Reported-by: Paul Menzel <paul.menzel@giantmonkey.de>
Reported-by: Erich Schubert <erich@debian.org>
Reported-by: Alexandre Rossi <alexandre.rossi@gmail.com>
Tested-by: Paul Menzel <paul.menzel@giantmonkey.de>
Tested-by: Erich Schubert <erich@debian.org>
CC: <stable@vger.kernel.org>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
  • Loading branch information
Alan Stern authored and James Bottomley committed Jan 27, 2016
1 parent 92e963f commit 13b4389
Show file tree
Hide file tree
Showing 2 changed files with 9 additions and 2 deletions.
7 changes: 5 additions & 2 deletions drivers/scsi/sd.c
Original file line number Diff line number Diff line change
Expand Up @@ -3268,8 +3268,8 @@ static int sd_suspend_common(struct device *dev, bool ignore_stop_errors)
struct scsi_disk *sdkp = dev_get_drvdata(dev);
int ret = 0;

if (!sdkp)
return 0; /* this can happen */
if (!sdkp) /* E.g.: runtime suspend following sd_remove() */
return 0;

if (sdkp->WCE && sdkp->media_present) {
sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
Expand Down Expand Up @@ -3308,6 +3308,9 @@ static int sd_resume(struct device *dev)
{
struct scsi_disk *sdkp = dev_get_drvdata(dev);

if (!sdkp) /* E.g.: runtime resume at the start of sd_probe() */
return 0;

if (!sdkp->device->manage_start_stop)
return 0;

Expand Down
4 changes: 4 additions & 0 deletions drivers/scsi/sr.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ static int sr_runtime_suspend(struct device *dev)
{
struct scsi_cd *cd = dev_get_drvdata(dev);

if (!cd) /* E.g.: runtime suspend following sr_remove() */
return 0;

if (cd->media_present)
return -EBUSY;
else
Expand Down Expand Up @@ -985,6 +988,7 @@ static int sr_remove(struct device *dev)
scsi_autopm_get_device(cd->device);

del_gendisk(cd->disk);
dev_set_drvdata(dev, NULL);

mutex_lock(&sr_ref_mutex);
kref_put(&cd->kref, sr_kref_release);
Expand Down

0 comments on commit 13b4389

Please sign in to comment.