public inbox for linux-scsi@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH] sd: fix race between rescan and remove
@ 2005-11-03 15:54 Alan Stern
  2005-11-04  2:08 ` James Bottomley
  0 siblings, 1 reply; 4+ messages in thread
From: Alan Stern @ 2005-11-03 15:54 UTC (permalink / raw)
  To: James Bottomley; +Cc: SCSI development list

James:

When the well-known open/remove race was fixed in sd.c, a closely-related
race between rescan and remove was ignored.  Probably because rescan gets 
called from an unusual pathway (via sysfs).  It's easy for this race to
trigger an oops, especially if you unplug a USB storage device while a
user program continually writes to the "rescan" attribute file.

This patch (as597) fixes the race by making the rescan routine acquire the 
appropriate references.  It also cleans up the code scsi_disk_get 
somewhat.  This resolves Bugzilla entry #5237.

Alan Stern



Signed-off-by: Alan Stern <stern@rowland.harvard.edu>

---

Do you think this is appropriate for 2.6.14.stable?

Index: usb-2.6/drivers/scsi/sd.c
===================================================================
--- usb-2.6.orig/drivers/scsi/sd.c
+++ usb-2.6/drivers/scsi/sd.c
@@ -182,19 +182,29 @@ static struct scsi_disk *scsi_disk_get(s
 	struct scsi_disk *sdkp = NULL;
 
 	down(&sd_ref_sem);
-	if (disk->private_data == NULL)
-		goto out;
-	sdkp = scsi_disk(disk);
-	kref_get(&sdkp->kref);
-	if (scsi_device_get(sdkp->device))
-		goto out_put;
+	if (disk->private_data) {
+		sdkp = scsi_disk(disk);
+		if (scsi_device_get(sdkp->device) == 0)
+			kref_get(&sdkp->kref);
+		else
+			sdkp = NULL;
+	}
 	up(&sd_ref_sem);
 	return sdkp;
+}
 
- out_put:
-	kref_put(&sdkp->kref, scsi_disk_release);
-	sdkp = NULL;
- out:
+static struct scsi_disk *scsi_disk_get_from_dev(struct device *dev)
+{
+	struct scsi_disk *sdkp;
+
+	down(&sd_ref_sem);
+	sdkp = dev_get_drvdata(dev);
+	if (sdkp) {
+		if (scsi_device_get(sdkp->device) == 0)
+			kref_get(&sdkp->kref);
+		else
+			sdkp = NULL;
+	}
 	up(&sd_ref_sem);
 	return sdkp;
 }
@@ -769,8 +779,13 @@ static int sd_prepare_flush(request_queu
 
 static void sd_rescan(struct device *dev)
 {
-	struct scsi_disk *sdkp = dev_get_drvdata(dev);
-	sd_revalidate_disk(sdkp->disk);
+	struct scsi_disk *sdkp;
+
+	sdkp = scsi_disk_get_from_dev(dev);
+	if (sdkp) {
+		sd_revalidate_disk(sdkp->disk);
+		scsi_disk_put(sdkp);
+	}
 }
 
 


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2005-11-04 17:45 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-11-03 15:54 [PATCH] sd: fix race between rescan and remove Alan Stern
2005-11-04  2:08 ` James Bottomley
2005-11-04 16:40   ` Alan Stern
2005-11-04 17:45     ` James Bottomley

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox