From owner-p4-projects@FreeBSD.ORG Sat Apr 14 05:36:01 2007 Return-Path: X-Original-To: p4-projects@freebsd.org Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id 2AB6116A408; Sat, 14 Apr 2007 05:36:01 +0000 (UTC) X-Original-To: perforce@freebsd.org Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [69.147.83.52]) by hub.freebsd.org (Postfix) with ESMTP id 0012F16A406 for ; Sat, 14 Apr 2007 05:36:00 +0000 (UTC) (envelope-from scottl@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [69.147.83.41]) by mx1.freebsd.org (Postfix) with ESMTP id E7DAC13C45E for ; Sat, 14 Apr 2007 05:36:00 +0000 (UTC) (envelope-from scottl@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.13.8/8.13.8) with ESMTP id l3E5a0Q3063844 for ; Sat, 14 Apr 2007 05:36:00 GMT (envelope-from scottl@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.13.8/8.13.8/Submit) id l3E5a0wX063841 for perforce@freebsd.org; Sat, 14 Apr 2007 05:36:00 GMT (envelope-from scottl@freebsd.org) Date: Sat, 14 Apr 2007 05:36:00 GMT Message-Id: <200704140536.l3E5a0wX063841@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to scottl@freebsd.org using -f From: Scott Long To: Perforce Change Reviews Cc: Subject: PERFORCE change 118078 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sat, 14 Apr 2007 05:36:01 -0000 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: