Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 28 Mar 2007 18:55:47 GMT
From:      Scott Long <scottl@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 116764 for review
Message-ID:  <200703281855.l2SItlu2011136@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=116764

Change 116764 by scottl@scottl-x64 on 2007/03/28 18:55:25

	Lock the xpt_rescan functions.

Affected files ...

.. //depot/projects/scottl-camlock/src/sys/cam/cam_xpt.c#51 edit

Differences ...

==== //depot/projects/scottl-camlock/src/sys/cam/cam_xpt.c#51 (text+ko) ====

@@ -247,6 +247,9 @@
 	STAILQ_HEAD(highpowerlist, ccb_hdr)	highpowerq;
 	int			num_highpower;
 
+	/* queue for handling async rescan requests. */
+	TAILQ_HEAD(, ccb_hdr) ccb_scanq;
+
 	/* Registered busses */
 	TAILQ_HEAD(,cam_eb)	xpt_busses;
 	u_int			bus_generation;
@@ -1405,22 +1408,40 @@
 }
 
 /* thread to handle bus rescans */
-static TAILQ_HEAD(, ccb_hdr) ccb_scanq;
 static void
 xpt_scanner_thread(void *dummy)
 {
-	mtx_lock(&Giant);
+	cam_isrq_t	queue;
+	union ccb	*ccb;
+	struct cam_sim	*sim;
+
 	for (;;) {
-		union ccb *ccb;
-		tsleep(&ccb_scanq, PRIBIO, "ccb_scanq", 0);
-		while ((ccb = (union ccb *)TAILQ_FIRST(&ccb_scanq)) != NULL) {
-			TAILQ_REMOVE(&ccb_scanq, &ccb->ccb_h, sim_links.tqe);
+		/*
+		 * Wait for a rescan request to come in.  When it does, splice
+		 * it onto a queue from local storage so that the xpt lock
+		 * doesn't need to be held while the requests are being
+		 * processed.
+		 */
+		xpt_lock_buses();
+		msleep(&xsoftc.ccb_scanq, &xsoftc.xpt_lock, PRIBIO,
+		    "ccb_scanq", 0);
+		TAILQ_INIT(&queue);
+		TAILQ_CONCAT(&queue, &xsoftc.ccb_scanq, sim_links.tqe);
+		xpt_unlock_buses();
+
+		while ((ccb = (union ccb *)TAILQ_FIRST(&queue)) != NULL) {
+			TAILQ_REMOVE(&queue, &ccb->ccb_h, sim_links.tqe);
+
+			sim = ccb->ccb_h.path->bus->sim;
+			mtx_lock(sim->mtx);
+
 			ccb->ccb_h.func_code = XPT_SCAN_BUS;
 			ccb->ccb_h.cbfcnp = xptdone;
 			xpt_setup_ccb(&ccb->ccb_h, ccb->ccb_h.path, 5);
 			cam_periph_runccb(ccb, NULL, 0, 0, NULL);
 			xpt_free_path(ccb->ccb_h.path);
 			xpt_free_ccb(ccb);
+			mtx_unlock(sim->mtx);
 		}
 	}
 }
@@ -1429,20 +1450,23 @@
 xpt_rescan(union ccb *ccb)
 {
 	struct ccb_hdr *hdr;
-	GIANT_REQUIRED;
+
 	/*
 	 * Don't make duplicate entries for the same paths.
 	 */
-	TAILQ_FOREACH(hdr, &ccb_scanq, sim_links.tqe) {
+	xpt_lock_buses();
+	TAILQ_FOREACH(hdr, &xsoftc.ccb_scanq, sim_links.tqe) {
 		if (xpt_path_comp(hdr->path, ccb->ccb_h.path) == 0) {
+			xpt_unlock_buses();
 			xpt_print(ccb->ccb_h.path, "rescan already queued\n");
 			xpt_free_path(ccb->ccb_h.path);
 			xpt_free_ccb(ccb);
 			return;
 		}
 	}
-	TAILQ_INSERT_TAIL(&ccb_scanq, &ccb->ccb_h, sim_links.tqe);
-	wakeup(&ccb_scanq);
+	TAILQ_INSERT_TAIL(&xsoftc.ccb_scanq, &ccb->ccb_h, sim_links.tqe);
+	wakeup(&xsoftc.ccb_scanq);
+	xpt_unlock_buses();
 }
 
 /* Functions accessed by the peripheral drivers */
@@ -1456,7 +1480,7 @@
 
 	TAILQ_INIT(&xsoftc.xpt_busses);
 	TAILQ_INIT(&cam_bioq);
-	TAILQ_INIT(&ccb_scanq);
+	TAILQ_INIT(&xsoftc.ccb_scanq);
 	STAILQ_INIT(&xsoftc.highpowerq);
 	xsoftc.num_highpower = CAM_MAX_HIGHPOWER;
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200703281855.l2SItlu2011136>