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