PERFORCE change 118078 for review

Scott Long scottl at FreeBSD.org
Sat Apr 14 05:36:01 UTC 2007


http://perforce.freebsd.org/chv.cgi?CH=118078

Change 118078 by scottl at scottl-x64 on 2007/04/14 05:35:26

	Add cam_periph_block|unblock.  This generates an exclusive lock on a
	periph instance that will cause cam_periph_lock() to sleep until the
	reference is released.  Its primary use at the moment is to protect
	the periph probe sequence from other threads opening the device.
	An SX lock is not used because the blocking thread may return to
	userland before unblocking.

Affected files ...

.. //depot/projects/scottl-camlock/src/sys/cam/cam_periph.c#18 edit
.. //depot/projects/scottl-camlock/src/sys/cam/cam_periph.h#11 edit
.. //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_cd.c#17 edit
.. //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_ch.c#11 edit
.. //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_da.c#29 edit

Differences ...

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

@@ -165,10 +165,12 @@
 	
 	init_level++;
 
+	xpt_lock_buses();
 	for (p_drv = periph_drivers; *p_drv != NULL; p_drv++) {
 		if (strcmp((*p_drv)->driver_name, name) == 0)
 			break;
 	}
+	xpt_unlock_buses();
 
 	sim = xpt_path_sim(path);
 	path_id = xpt_path_path_id(path);
@@ -307,6 +309,30 @@
 
 }
 
+void
+cam_periph_block(struct cam_periph *periph)
+{
+
+	mtx_assert(periph->sim->mtx, MA_OWNED);
+
+	cam_periph_acquire(periph);
+	periph->flags |= CAM_PERIPH_LOCKED;
+}
+
+void
+cam_periph_unblock(struct cam_periph *periph)
+{
+
+	mtx_assert(periph->sim->mtx, MA_OWNED);
+
+	periph->flags &= ~CAM_PERIPH_LOCKED;
+	if (periph->flags &CAM_PERIPH_LOCK_WANTED) {
+		periph->flags &= ~CAM_PERIPH_LOCK_WANTED;
+		wakeup(periph);
+	}
+	cam_periph_release(periph);
+}
+
 /*
  * Look for the next unit number that is not currently in use for this
  * peripheral type starting at "newunit".  Also exclude unit numbers that
@@ -506,9 +532,16 @@
 void
 cam_periph_lock(struct cam_periph *periph)
 {
+	struct mtx *mtx;
 
-	mtx_lock(periph->sim->mtx);
-	periph->flags |= CAM_PERIPH_LOCKED;
+	mtx = periph->sim->mtx;
+	mtx_lock(mtx);
+	if (periph->flags & CAM_PERIPH_LOCKED) {
+		periph->flags |= CAM_PERIPH_LOCK_WANTED;
+		if (mtx == &Giant)
+			mtx = NULL;
+		msleep(periph, mtx, PCATCH, "periph", 0);
+	};
 }
 
 /*
@@ -518,7 +551,6 @@
 cam_periph_unlock(struct cam_periph *periph)
 {
 
-	periph->flags &= ~CAM_PERIPH_LOCKED;
 	mtx_unlock(periph->sim->mtx);
 }
 

==== //depot/projects/scottl-camlock/src/sys/cam/cam_periph.h#11 (text+ko) ====

@@ -142,6 +142,8 @@
 void		cam_periph_unlock(struct cam_periph *periph);
 cam_status	cam_periph_acquire(struct cam_periph *periph);
 void		cam_periph_release(struct cam_periph *periph);
+void		cam_periph_block(struct cam_periph *periph);
+void		cam_periph_unblock(struct cam_periph *periph);
 void		cam_periph_invalidate(struct cam_periph *periph);
 int		cam_periph_mapmem(union ccb *ccb,
 				  struct cam_periph_map_info *mapinfo);

==== //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_cd.c#17 (text+ko) ====

@@ -977,7 +977,7 @@
 cdregisterexit:
 
 	/* Refcount this periph now that it's been created. */
-	(void)cam_periph_acquire(periph); 
+	cam_periph_block(periph);
 
 	if ((softc->flags & CD_FLAG_CHANGER) == 0)
 		xpt_schedule(periph, /*priority*/5);
@@ -1784,7 +1784,7 @@
 		 * operation.
 		 */
 		xpt_release_ccb(done_ccb);
-		cam_periph_release(periph);
+		cam_periph_unblock(periph);
 		return;
 	}
 	case CD_CCB_WAITING:

==== //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_ch.c#11 (text+ko) ====

@@ -393,7 +393,7 @@
 	xpt_action((union ccb *)&csa);
 
 	/* Refcount this periph now that it's been created. */
-	(void)cam_periph_acquire(periph);
+	cam_periph_block(periph);
 	xpt_schedule(periph, /*priority*/5);
 
 	return(CAM_REQ_CMP);
@@ -655,7 +655,7 @@
 		 * operation.
 		 */
 		xpt_release_ccb(done_ccb);
-		cam_periph_release(periph);
+		cam_periph_unblock(periph);
 		return;
 	}
 	case CH_CCB_WAITING:

==== //depot/projects/scottl-camlock/src/sys/cam/scsi/scsi_da.c#29 (text+ko) ====

@@ -1201,10 +1201,11 @@
 	xpt_action((union ccb *)&csa);
 
 	/*
-	 * Refcount the periph while dastart is called to finish the probe.
-	 * The reference will be dropped in dadone at the end of probe.
+	 * Take an exclusive refcount on the periph while dastart is called
+	 * to finish the probe.  The reference will be dropped in dadone at
+	 * the end of probe.
 	 */
-	(void)cam_periph_acquire(periph);
+	cam_periph_block(periph);
 	xpt_schedule(periph, /*priority*/5);
 
 	/*
@@ -1226,7 +1227,6 @@
 
 	softc = (struct da_softc *)periph->softc;
 
-	
 	switch (softc->state) {
 	case DA_STATE_NORMAL:
 	{
@@ -1687,7 +1687,7 @@
 		 * operation.
 		 */
 		xpt_release_ccb(done_ccb);
-		cam_periph_release(periph);
+		cam_periph_unblock(periph);
 		return;
 	}
 	case DA_CCB_WAITING:


More information about the p4-projects mailing list