Date: Sat, 14 Apr 2007 05:36:00 GMT From: Scott Long <scottl@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 118078 for review Message-ID: <200704140536.l3E5a0wX063841@repoman.freebsd.org>
next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=118078 Change 118078 by scottl@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:
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200704140536.l3E5a0wX063841>
