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