aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlan Stern <stern@rowland.harvard.edu>2016-01-20 11:26:01 -0500
committerJames Bottomley <James.Bottomley@HansenPartnership.com>2016-01-26 20:24:16 -0500
commit13b4389143413a1f18127c07f72c74cad5b563e8 (patch)
tree8b18c39922c06b2a569e669adaacbf503500af00
parent92e963f50fc74041b5e9e744c330dca48e04f08d (diff)
SCSI: fix crashes in sd and sr runtime PM
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>
-rw-r--r--drivers/scsi/sd.c7
-rw-r--r--drivers/scsi/sr.c4
2 files changed, 9 insertions, 2 deletions
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index 4e08d1cd704d..84fa4c46eaa6 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -3268,8 +3268,8 @@ static int sd_suspend_common(struct device *dev, bool ignore_stop_errors)
3268 struct scsi_disk *sdkp = dev_get_drvdata(dev); 3268 struct scsi_disk *sdkp = dev_get_drvdata(dev);
3269 int ret = 0; 3269 int ret = 0;
3270 3270
3271 if (!sdkp) 3271 if (!sdkp) /* E.g.: runtime suspend following sd_remove() */
3272 return 0; /* this can happen */ 3272 return 0;
3273 3273
3274 if (sdkp->WCE && sdkp->media_present) { 3274 if (sdkp->WCE && sdkp->media_present) {
3275 sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n"); 3275 sd_printk(KERN_NOTICE, sdkp, "Synchronizing SCSI cache\n");
@@ -3308,6 +3308,9 @@ static int sd_resume(struct device *dev)
3308{ 3308{
3309 struct scsi_disk *sdkp = dev_get_drvdata(dev); 3309 struct scsi_disk *sdkp = dev_get_drvdata(dev);
3310 3310
3311 if (!sdkp) /* E.g.: runtime resume at the start of sd_probe() */
3312 return 0;
3313
3311 if (!sdkp->device->manage_start_stop) 3314 if (!sdkp->device->manage_start_stop)
3312 return 0; 3315 return 0;
3313 3316
diff --git a/drivers/scsi/sr.c b/drivers/scsi/sr.c
index 8bd54a64efd6..64c867405ad4 100644
--- a/drivers/scsi/sr.c
+++ b/drivers/scsi/sr.c
@@ -144,6 +144,9 @@ static int sr_runtime_suspend(struct device *dev)
144{ 144{
145 struct scsi_cd *cd = dev_get_drvdata(dev); 145 struct scsi_cd *cd = dev_get_drvdata(dev);
146 146
147 if (!cd) /* E.g.: runtime suspend following sr_remove() */
148 return 0;
149
147 if (cd->media_present) 150 if (cd->media_present)
148 return -EBUSY; 151 return -EBUSY;
149 else 152 else
@@ -985,6 +988,7 @@ static int sr_remove(struct device *dev)
985 scsi_autopm_get_device(cd->device); 988 scsi_autopm_get_device(cd->device);
986 989
987 del_gendisk(cd->disk); 990 del_gendisk(cd->disk);
991 dev_set_drvdata(dev, NULL);
988 992
989 mutex_lock(&sr_ref_mutex); 993 mutex_lock(&sr_ref_mutex);
990 kref_put(&cd->kref, sr_kref_release); 994 kref_put(&cd->kref, sr_kref_release);