PERFORCE change 82512 for review

Scott Long scottl at FreeBSD.org
Wed Aug 24 22:13:51 GMT 2005


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

Change 82512 by scottl at scottl-junior on 2005/08/24 22:12:48

	       Start adding the topology lock to cam_periph.c.  This covers reference
	       counting of the periph as well as global periph list operations.

Affected files ...

.. //depot/projects/scottl-camlock/src/sys/cam/cam_periph.c#5 edit

Differences ...

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

@@ -121,7 +121,6 @@
 	lun_id_t	lun_id;
 	cam_status	status;
 	u_int		init_level;
-	int s;
 
 	init_level = 0;
 	/*
@@ -186,7 +185,7 @@
 	if (status != CAM_REQ_CMP)
 		goto failure;
 
-	s = splsoftcam();
+	mtx_lock(&cam_topo_lock);
 	cur_periph = TAILQ_FIRST(&(*p_drv)->units);
 	while (cur_periph != NULL
 	    && cur_periph->unit_number < periph->unit_number)
@@ -198,9 +197,8 @@
 		TAILQ_INSERT_TAIL(&(*p_drv)->units, periph, unit_links);
 		(*p_drv)->generation++;
 	}
+	mtx_unlock(&cam_topo_lock);
 
-	splx(s);
-
 	init_level++;
 
 	status = periph_ctor(periph, arg);
@@ -214,9 +212,9 @@
 		/* Initialized successfully */
 		break;
 	case 3:
-		s = splsoftcam();
+		mtx_lock(&cam_topo_lock);
 		TAILQ_REMOVE(&(*p_drv)->units, periph, unit_links);
-		splx(s);
+		mtx_unlock(&cam_topo_lock);
 		xpt_remove_periph(periph);
 		/* FALLTHROUGH */
 	case 2:
@@ -244,21 +242,20 @@
 {
 	struct periph_driver **p_drv;
 	struct cam_periph *periph;
-	int s;
 
 	for (p_drv = periph_drivers; *p_drv != NULL; p_drv++) {
 
 		if (name != NULL && (strcmp((*p_drv)->driver_name, name) != 0))
 			continue;
 
-		s = splsoftcam();
+		mtx_lock(&cam_topo_lock);
 		TAILQ_FOREACH(periph, &(*p_drv)->units, unit_links) {
 			if (xpt_path_comp(periph->path, path) == 0) {
-				splx(s);
+				mtx_unlock(&cam_topo_lock);
 				return(periph);
 			}
 		}
-		splx(s);
+		mtx_unlock(&cam_topo_lock);
 		if (name != NULL)
 			return(NULL);
 	}
@@ -268,14 +265,14 @@
 cam_status
 cam_periph_acquire(struct cam_periph *periph)
 {
-	int s;
 
 	if (periph == NULL)
 		return(CAM_REQ_CMP_ERR);
 
-	s = splsoftcam();
+	/* XXX atomic increment instead? */
+	mtx_lock(&cam_topo_lock);
 	periph->refcount++;
-	splx(s);
+	mtx_unlock(&cam_topo_lock);
 
 	return(CAM_REQ_CMP);
 }
@@ -283,17 +280,17 @@
 void
 cam_periph_release(struct cam_periph *periph)
 {
-	int s;
 
 	if (periph == NULL)
 		return;
 
-	s = splsoftcam();
+	/* camperiphfree() will release the mutex. */
+	mtx_lock(&cam_topo_lock);
 	if ((--periph->refcount == 0)
 	 && (periph->flags & CAM_PERIPH_INVALID)) {
 		camperiphfree(periph);
-	}
-	splx(s);
+	} else
+		mtx_unlock(&cam_topo_lock);
 
 }
 
@@ -311,11 +308,10 @@
 {
 	struct	cam_periph *periph;
 	char	*periph_name;
-	int	s;
 	int	i, val, dunit, r;
 	const char *dname, *strval;
 
-	s = splsoftcam();
+	mtx_lock(&cam_topo_lock);
 	periph_name = p_drv->driver_name;
 	for (;;newunit++) {
 
@@ -361,7 +357,7 @@
 		if (r != 0)
 			break;
 	}
-	splx(s);
+	mtx_unlock(&cam_topo_lock);
 	return (newunit);
 }
 
@@ -418,7 +414,6 @@
 {
 	int s;
 
-	s = splsoftcam();
 	/*
 	 * We only call this routine the first time a peripheral is
 	 * invalidated.  The oninvalidate() routine is always called at
@@ -431,36 +426,43 @@
 	periph->flags |= CAM_PERIPH_INVALID;
 	periph->flags &= ~CAM_PERIPH_NEW_DEV_FOUND;
 
+	/* camperiphfree() will release the mutex. */
+	mtx_lock(&cam_topo_lock);
 	if (periph->refcount == 0)
 		camperiphfree(periph);
-	else if (periph->refcount < 0)
+	else if (periph->refcount < 0) {
+		mtx_unlock(&cam_topo_lock);
 		printf("cam_invalidate_periph: refcount < 0!!\n");
-	splx(s);
+	}
 }
 
+/*
+ * The topology lock must be held on entry and will be released before return.
+ */
 static void
 camperiphfree(struct cam_periph *periph)
 {
-	int s;
 	struct periph_driver **p_drv;
 
+	mtx_assert(&cam_topo_lock, MTX_OWNED);
+
 	for (p_drv = periph_drivers; *p_drv != NULL; p_drv++) {
-		if (strcmp((*p_drv)->driver_name, periph->periph_name) == 0)
+		if (strcmp((*p_drv)->driver_name, periph->periph_name) == 0) {
+			TAILQ_REMOVE(&(*p_drv)->units, periph, unit_links);
+			(*p_drv)->generation++;
 			break;
+		}
 	}
+	mtx_unlock(&cam_topo_lock);
+
 	if (*p_drv == NULL) {
 		printf("camperiphfree: attempt to free non-existant periph\n");
 		return;
 	}
-	
+
 	if (periph->periph_dtor != NULL)
 		periph->periph_dtor(periph);
 	
-	s = splsoftcam();
-	TAILQ_REMOVE(&(*p_drv)->units, periph, unit_links);
-	(*p_drv)->generation++;
-	splx(s);
-
 	xpt_remove_periph(periph);
 
 	if (periph->flags & CAM_PERIPH_NEW_DEV_FOUND) {


More information about the p4-projects mailing list