From: Matthew Dillon Date: Fri, 18 Jul 2008 00:08:23 +0000 (+0000) Subject: MFC CAM fixes for the 2.0 release. X-Git-Tag: v2.0.1~79 X-Git-Url: https://gitweb.dragonflybsd.org/~mneumann/dragonfly.git/commitdiff_plain/dc4302add540c68a15d29a58c20bfda1638c9a49 MFC CAM fixes for the 2.0 release. --- diff --git a/sys/bus/cam/cam_periph.c b/sys/bus/cam/cam_periph.c index 57804fdbc1..f7766250fc 100644 --- a/sys/bus/cam/cam_periph.c +++ b/sys/bus/cam/cam_periph.c @@ -27,7 +27,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/cam/cam_periph.c,v 1.70 2008/02/12 11:07:33 raj Exp $ - * $DragonFly: src/sys/bus/cam/cam_periph.c,v 1.40 2008/05/18 20:30:19 pavalos Exp $ + * $DragonFly: src/sys/bus/cam/cam_periph.c,v 1.40.2.1 2008/07/18 00:08:22 dillon Exp $ */ #include @@ -328,18 +328,24 @@ cam_periph_hold(struct cam_periph *periph, int flags) } void -cam_periph_unhold(struct cam_periph *periph) +cam_periph_unhold(struct cam_periph *periph, int unlock) { + struct cam_sim *sim; sim_lock_assert_owned(periph->sim->lock); - periph->flags &= ~CAM_PERIPH_LOCKED; if ((periph->flags & CAM_PERIPH_LOCK_WANTED) != 0) { periph->flags &= ~CAM_PERIPH_LOCK_WANTED; wakeup(periph); } - - cam_periph_release(periph); + if (unlock) { + sim = periph->sim; + cam_periph_release(periph); + /* periph may be garbage now */ + CAM_SIM_UNLOCK(sim); + } else { + cam_periph_release(periph); + } } /* @@ -758,9 +764,10 @@ cam_periph_ccbwait(union ccb *ccb) struct cam_sim *sim; sim = xpt_path_sim(ccb->ccb_h.path); - if ((ccb->ccb_h.pinfo.index != CAM_UNQUEUED_INDEX) - || ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG)) + while ((ccb->ccb_h.pinfo.index != CAM_UNQUEUED_INDEX) + || ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG)) { sim_lock_sleep(&ccb->ccb_h.cbfcnp, 0, "cbwait", 0, sim->lock); + } } int diff --git a/sys/bus/cam/cam_periph.h b/sys/bus/cam/cam_periph.h index d9c27a84a0..e2ade26d98 100644 --- a/sys/bus/cam/cam_periph.h +++ b/sys/bus/cam/cam_periph.h @@ -26,7 +26,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/cam/cam_periph.h,v 1.18 2007/04/19 22:46:26 scottl Exp $ - * $DragonFly: src/sys/bus/cam/cam_periph.h,v 1.11 2008/05/18 20:30:19 pavalos Exp $ + * $DragonFly: src/sys/bus/cam/cam_periph.h,v 1.11.2.1 2008/07/18 00:08:22 dillon Exp $ */ #ifndef _CAM_CAM_PERIPH_H @@ -144,7 +144,7 @@ struct cam_periph *cam_periph_find(struct cam_path *path, char *name); cam_status cam_periph_acquire(struct cam_periph *periph); void cam_periph_release(struct cam_periph *periph); int cam_periph_hold(struct cam_periph *periph, int flags); -void cam_periph_unhold(struct cam_periph *periph); +void cam_periph_unhold(struct cam_periph *periph, int unlock); void cam_periph_invalidate(struct cam_periph *periph); int cam_periph_mapmem(union ccb *ccb, struct cam_periph_map_info *mapinfo); diff --git a/sys/bus/cam/cam_sim.c b/sys/bus/cam/cam_sim.c index 81448c9958..fe93de2f1e 100644 --- a/sys/bus/cam/cam_sim.c +++ b/sys/bus/cam/cam_sim.c @@ -26,7 +26,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/cam/cam_sim.c,v 1.3 1999/08/28 00:40:42 peter Exp $ - * $DragonFly: src/sys/bus/cam/cam_sim.c,v 1.12 2008/06/29 19:15:34 dillon Exp $ + * $DragonFly: src/sys/bus/cam/cam_sim.c,v 1.12.2.1 2008/07/18 00:08:22 dillon Exp $ */ #include @@ -69,13 +69,27 @@ cam_sim_unlock(sim_lock *lock) lockmgr(lock, LK_RELEASE); } +/* + * lock can be NULL if sim was &dead_sim + */ void sim_lock_assert_owned(sim_lock *lock) { - if (lock == &sim_mplock) - ASSERT_MP_LOCK_HELD(curthread); - else - KKASSERT(lockstatus(lock, curthread) != 0); + if (lock) { + if (lock == &sim_mplock) + ASSERT_MP_LOCK_HELD(curthread); + else + KKASSERT(lockstatus(lock, curthread) != 0); + } +} + +void +sim_lock_assert_unowned(sim_lock *lock) +{ + if (lock) { + if (lock != &sim_mplock) + KKASSERT(lockstatus(lock, curthread) == 0); + } } int diff --git a/sys/bus/cam/cam_sim.h b/sys/bus/cam/cam_sim.h index c8fcc52d90..77ff571d8b 100644 --- a/sys/bus/cam/cam_sim.h +++ b/sys/bus/cam/cam_sim.h @@ -26,7 +26,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/cam/cam_sim.h,v 1.4 1999/12/29 04:54:27 peter Exp $ - * $DragonFly: src/sys/bus/cam/cam_sim.h,v 1.8 2008/06/29 19:15:34 dillon Exp $ + * $DragonFly: src/sys/bus/cam/cam_sim.h,v 1.8.2.1 2008/07/18 00:08:22 dillon Exp $ */ #ifndef _CAM_CAM_SIM_H @@ -59,6 +59,7 @@ extern sim_lock sim_mplock; void cam_sim_lock(sim_lock *lock); void cam_sim_unlock(sim_lock *lock); void sim_lock_assert_owned(sim_lock *lock); +void sim_lock_assert_unowned(sim_lock *lock); int sim_lock_sleep(void *ident, int flags, const char *wmesg, int timo, sim_lock *lock); struct cam_devq * cam_simq_alloc(u_int32_t max_sim_transactions); @@ -120,6 +121,7 @@ struct cam_sim { #define CAM_SIM_REL_TIMEOUT_PENDING 0x01 #define CAM_SIM_MPSAFE 0x02 #define CAM_SIM_ON_DONEQ 0x04 +#define CAM_SIM_DEREGISTERED 0x08 struct callout callout; struct cam_devq *devq; /* Device Queue to use for this SIM */ int refcount; /* References to the sim */ diff --git a/sys/bus/cam/cam_xpt.c b/sys/bus/cam/cam_xpt.c index 168ffc2047..e6deabfa37 100644 --- a/sys/bus/cam/cam_xpt.c +++ b/sys/bus/cam/cam_xpt.c @@ -27,7 +27,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/cam/cam_xpt.c,v 1.80.2.18 2002/12/09 17:31:55 gibbs Exp $ - * $DragonFly: src/sys/bus/cam/cam_xpt.c,v 1.66 2008/06/29 19:15:34 dillon Exp $ + * $DragonFly: src/sys/bus/cam/cam_xpt.c,v 1.66.2.1 2008/07/18 00:08:22 dillon Exp $ */ #include #include @@ -696,13 +696,8 @@ static void dead_sim_action(struct cam_sim *sim, union ccb *ccb); static void dead_sim_poll(struct cam_sim *sim); /* Dummy SIM that is used when the real one has gone. */ -static struct cam_sim cam_dead_sim = { - .sim_action = dead_sim_action, - .sim_poll = dead_sim_poll, - .sim_name = "dead_sim", -}; - -#define SIM_DEAD(sim) ((sim) == &cam_dead_sim) +static struct cam_sim cam_dead_sim; +static struct lock cam_dead_lock; /* Storage for debugging datastructures */ #ifdef CAMDEBUG @@ -1472,6 +1467,16 @@ xpt_init(void *dummy) lockinit(&xsoftc.xpt_lock, "XPT lock", 0, LK_CANRECURSE); lockinit(&xsoftc.xpt_topo_lock, "XPT topology lock", 0, LK_CANRECURSE); + SLIST_INIT(&cam_dead_sim.ccb_freeq); + TAILQ_INIT(&cam_dead_sim.sim_doneq); + spin_init(&cam_dead_sim.sim_spin); + cam_dead_sim.sim_action = dead_sim_action; + cam_dead_sim.sim_poll = dead_sim_poll; + cam_dead_sim.sim_name = "dead_sim"; + cam_dead_sim.lock = &cam_dead_lock; + lockinit(&cam_dead_lock, "XPT dead_sim lock", 0, LK_CANRECURSE); + cam_dead_sim.flags |= CAM_SIM_DEREGISTERED; + /* * The xpt layer is, itself, the equivelent of a SIM. * Allow 16 ccbs in the ccb pool for it. This should @@ -3021,7 +3026,7 @@ xpt_action(union ccb *start_ccb) path = start_ccb->ccb_h.path; sim = path->bus->sim; - if (SIM_DEAD(sim)) { + if (sim == &cam_dead_sim) { /* The SIM has gone; just execute the CCB directly. */ cam_ccbq_send_ccb(&path->device->ccbq, start_ccb); (*(sim->sim_action))(sim, start_ccb); @@ -3610,7 +3615,7 @@ xpt_schedule(struct cam_periph *perph, u_int32_t new_priority) new_priority); } runq = 0; - } else if (SIM_DEAD(perph->path->bus->sim)) { + } else if (perph->path->bus->sim == &cam_dead_sim) { /* The SIM is gone so just call periph_start directly. */ work_ccb = xpt_get_ccb(perph->path->device); if (work_ccb == NULL) @@ -4249,7 +4254,9 @@ xpt_release_ccb(union ccb *free_ccb) if (sim->ccb_count > sim->max_ccbs) { xpt_free_ccb(free_ccb); sim->ccb_count--; - } else { + } else if (sim == &cam_dead_sim) { + xpt_free_ccb(free_ccb); + } else { SLIST_INSERT_HEAD(&sim->ccb_freeq, &free_ccb->ccb_h, xpt_links.sle); } @@ -4339,6 +4346,7 @@ int32_t xpt_bus_deregister(path_id_t pathid) { struct cam_path bus_path; + struct cam_et *target; struct cam_ed *device; struct cam_ed_qinfo *qinfo; struct cam_devq *devq; @@ -4346,6 +4354,7 @@ xpt_bus_deregister(path_id_t pathid) struct cam_sim *ccbsim; union ccb *work_ccb; cam_status status; + int retries = 0; status = xpt_compile_path(&bus_path, NULL, pathid, CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD); @@ -4362,12 +4371,19 @@ xpt_bus_deregister(path_id_t pathid) xpt_async(AC_LOST_DEVICE, &bus_path, NULL); xpt_async(AC_PATH_DEREGISTERED, &bus_path, NULL); - /* The SIM may be gone, so use a dummy SIM for any stray operations. */ + /* + * Mark the SIM as having been deregistered. This prevents + * certain operations from re-queueing to it, stops new devices + * from being added, etc. + */ devq = bus_path.bus->sim->devq; ccbsim = bus_path.bus->sim; - bus_path.bus->sim = &cam_dead_sim; + ccbsim->flags |= CAM_SIM_DEREGISTERED; - /* Execute any pending operations now. */ +again: + /* + * Execute any pending operations now. + */ while ((qinfo = (struct cam_ed_qinfo *)camq_remove(&devq->send_queue, CAMQ_HEAD)) != NULL || (qinfo = (struct cam_ed_qinfo *)camq_remove(&devq->alloc_queue, @@ -4389,15 +4405,58 @@ xpt_bus_deregister(path_id_t pathid) } while (work_ccb != NULL || periph != NULL); } - /* Make sure all completed CCBs are processed. */ + /* + * Make sure all completed CCBs are processed. + */ while (!TAILQ_EMPTY(&ccbsim->sim_doneq)) { camisr_runqueue(ccbsim); + } + + /* + * Check for requeues, reissues asyncs if necessary + */ + if (CAMQ_GET_HEAD(&devq->send_queue)) + kprintf("camq: devq send_queue still in use\n"); + if (CAMQ_GET_HEAD(&devq->alloc_queue)) + kprintf("camq: devq alloc_queue still in use\n"); + if (CAMQ_GET_HEAD(&devq->send_queue) || + CAMQ_GET_HEAD(&devq->alloc_queue)) { + if (++retries < 5) { + xpt_async(AC_LOST_DEVICE, &bus_path, NULL); + xpt_async(AC_PATH_DEREGISTERED, &bus_path, NULL); + goto again; + } + } - /* Repeat the async's for the benefit of any new devices. */ - xpt_async(AC_LOST_DEVICE, &bus_path, NULL); - xpt_async(AC_PATH_DEREGISTERED, &bus_path, NULL); + /* + * Retarget the bus and all cached sim pointers to dead_sim. + * + * Various CAM subsystems may be holding on to targets, devices, + * and/or peripherals and may attempt to use the sim pointer cached + * in some of these structures during close. + */ + bus_path.bus->sim = &cam_dead_sim; + TAILQ_FOREACH(target, &bus_path.bus->et_entries, links) { + TAILQ_FOREACH(device, &target->ed_entries, links) { + device->sim = &cam_dead_sim; + SLIST_FOREACH(periph, &device->periphs, periph_links) { + periph->sim = &cam_dead_sim; + } + } } + /* + * Repeat the async's for the benefit of any new devices, such as + * might be created from completed probes. Any new device + * ops will run on dead_sim. + * + * XXX There are probably races :-( + */ + CAM_SIM_LOCK(&cam_dead_sim); + xpt_async(AC_LOST_DEVICE, &bus_path, NULL); + xpt_async(AC_PATH_DEREGISTERED, &bus_path, NULL); + CAM_SIM_UNLOCK(&cam_dead_sim); + /* Release the reference count held while registered. */ xpt_release_bus(bus_path.bus); xpt_release_path(&bus_path); @@ -4959,13 +5018,18 @@ xpt_alloc_device(struct cam_eb *bus, struct cam_et *target, lun_id_t lun_id) struct cam_devq *devq; cam_status status; - if (SIM_DEAD(bus->sim)) + /* + * Disallow new devices while trying to deregister a sim + */ + if (bus->sim->flags & CAM_SIM_DEREGISTERED) return (NULL); - /* Make space for us in the device queue on our bus */ - if (bus->sim->devq == NULL) - return(NULL); + /* + * Make space for us in the device queue on our bus + */ devq = bus->sim->devq; + if (devq == NULL) + return(NULL); status = cam_devq_resize(devq, devq->alloc_queue.array_size + 1); if (status != CAM_REQ_CMP) { @@ -5077,9 +5141,8 @@ xpt_release_device(struct cam_eb *bus, struct cam_et *target, TAILQ_REMOVE(&target->ed_entries, device,links); target->generation++; bus->sim->max_ccbs -= device->ccbq.devq_openings; - if (!SIM_DEAD(bus->sim)) { + if ((devq = bus->sim->devq) != NULL) { /* Release our slot in the devq */ - devq = bus->sim->devq; cam_devq_resize(devq, devq->alloc_queue.array_size - 1); } camq_fini(&device->drvq); @@ -7199,7 +7262,10 @@ camisr_runqueue(struct cam_sim *sim) cam_ccbq_ccb_done(&dev->ccbq, (union ccb *)ccb_h); - if (!SIM_DEAD(ccb_h->path->bus->sim)) { + /* + * devq may be NULL if this is cam_dead_sim + */ + if (ccb_h->path->bus->sim->devq) { ccb_h->path->bus->sim->devq->send_active--; ccb_h->path->bus->sim->devq->send_openings++; } @@ -7248,12 +7314,18 @@ camisr_runqueue(struct cam_sim *sim) spin_unlock_wr(&sim->sim_spin); } +/* + * The dead_sim isn't completely hooked into CAM, we have to make sure + * the doneq is cleared after calling xpt_done() so cam_periph_ccbwait() + * doesn't block. + */ static void dead_sim_action(struct cam_sim *sim, union ccb *ccb) { ccb->ccb_h.status = CAM_DEV_NOT_THERE; xpt_done(ccb); + camisr_runqueue(sim); } static void diff --git a/sys/bus/cam/scsi/scsi_cd.c b/sys/bus/cam/scsi/scsi_cd.c index 1060b4eeef..455c89e8a1 100644 --- a/sys/bus/cam/scsi/scsi_cd.c +++ b/sys/bus/cam/scsi/scsi_cd.c @@ -25,7 +25,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/cam/scsi/scsi_cd.c,v 1.31.2.16 2003/10/21 22:26:11 thomas Exp $ - * $DragonFly: src/sys/bus/cam/scsi/scsi_cd.c,v 1.43 2008/05/23 19:46:37 dillon Exp $ + * $DragonFly: src/sys/bus/cam/scsi/scsi_cd.c,v 1.43.2.1 2008/07/18 00:08:23 dillon Exp $ */ /* * Portions of this driver taken from the original FreeBSD cd driver. @@ -1022,8 +1022,7 @@ cdopen(struct dev_open_args *ap) error = cdcheckmedia(periph); CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("leaving cdopen\n")); - cam_periph_unhold(periph); - cam_periph_unlock(periph); + cam_periph_unhold(periph, 1); /* stays acquired */ return (0); @@ -1070,8 +1069,7 @@ cdclose(struct dev_close_args *ap) */ softc->flags &= ~(CD_FLAG_VALID_MEDIA|CD_FLAG_VALID_TOC|CD_FLAG_OPEN); - cam_periph_unhold(periph); - cam_periph_unlock(periph); + cam_periph_unhold(periph, 1); cam_periph_release(periph); return (0); @@ -1809,7 +1807,7 @@ cddone(struct cam_periph *periph, union ccb *done_ccb) * operation. */ xpt_release_ccb(done_ccb); - cam_periph_unhold(periph); + cam_periph_unhold(periph, 0); return; } case CD_CCB_WAITING: @@ -1899,8 +1897,7 @@ cdioctl(struct dev_ioctl_args *ap) && (IOCGROUP(ap->a_cmd) == 'c')) { error = cdcheckmedia(periph); if (error != 0) { - cam_periph_unhold(periph); - cam_periph_unlock(periph); + cam_periph_unhold(periph, 1); return (error); } } @@ -2719,11 +2716,8 @@ cdioctl(struct dev_ioctl_args *ap) } cam_periph_lock(periph); - cam_periph_unhold(periph); - CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("leaving cdioctl\n")); - - cam_periph_unlock(periph); + cam_periph_unhold(periph, 1); return (error); } diff --git a/sys/bus/cam/scsi/scsi_ch.c b/sys/bus/cam/scsi/scsi_ch.c index dc5de891ad..d2357634b2 100644 --- a/sys/bus/cam/scsi/scsi_ch.c +++ b/sys/bus/cam/scsi/scsi_ch.c @@ -25,7 +25,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/cam/scsi/scsi_ch.c,v 1.20.2.2 2000/10/31 08:09:49 dwmalone Exp $ - * $DragonFly: src/sys/bus/cam/scsi/scsi_ch.c,v 1.27 2008/05/18 20:30:20 pavalos Exp $ + * $DragonFly: src/sys/bus/cam/scsi/scsi_ch.c,v 1.27.2.1 2008/07/18 00:08:23 dillon Exp $ */ /* * Derived from the NetBSD SCSI changer driver. @@ -424,14 +424,12 @@ chopen(struct dev_open_args *ap) */ if ((error = chgetparams(periph)) != 0) { softc->flags &= ~CH_FLAG_OPEN; - cam_periph_unlock(periph); + cam_periph_unhold(periph, 1); cam_periph_release(periph); - return(error); + } else { + cam_periph_unhold(periph, 1); } - cam_periph_unhold(periph); - cam_periph_unlock(periph); - return(error); } @@ -645,7 +643,7 @@ chdone(struct cam_periph *periph, union ccb *done_ccb) * operation. */ xpt_release_ccb(done_ccb); - cam_periph_unhold(periph); + cam_periph_unhold(periph, 0); return; } case CH_CCB_WAITING: diff --git a/sys/bus/cam/scsi/scsi_da.c b/sys/bus/cam/scsi/scsi_da.c index a2162a9259..667dfd0fa2 100644 --- a/sys/bus/cam/scsi/scsi_da.c +++ b/sys/bus/cam/scsi/scsi_da.c @@ -26,7 +26,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/cam/scsi/scsi_da.c,v 1.42.2.46 2003/10/21 22:18:19 thomas Exp $ - * $DragonFly: src/sys/bus/cam/scsi/scsi_da.c,v 1.57 2008/07/12 20:36:06 pavalos Exp $ + * $DragonFly: src/sys/bus/cam/scsi/scsi_da.c,v 1.57.2.1 2008/07/18 00:08:23 dillon Exp $ */ #include @@ -791,8 +791,7 @@ daopen(struct dev_open_args *ap) softc->flags &= ~DA_FLAG_OPEN; cam_periph_release(periph); } - cam_periph_unhold(periph); - cam_periph_unlock(periph); + cam_periph_unhold(periph, 1); return (error); } @@ -889,8 +888,7 @@ daclose(struct dev_close_args *ap) xpt_print(periph->path, "daclose() called on an already closed device!\n"); } - cam_periph_unhold(periph); - cam_periph_unlock(periph); + cam_periph_unhold(periph, 1); return (0); } @@ -1177,6 +1175,7 @@ dacleanup(struct cam_periph *periph) && sysctl_ctx_free(&softc->sysctl_ctx) != 0) { xpt_print(periph->path, "can't remove sysctl context\n"); } + periph->softc = NULL; if (softc->disk.d_rawdev) { cam_periph_unlock(periph); disk_destroy(&softc->disk); @@ -1909,7 +1908,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb) * operation. */ xpt_release_ccb(done_ccb); - cam_periph_unhold(periph); + cam_periph_unhold(periph, 0); return; } case DA_CCB_WAITING: diff --git a/sys/bus/cam/scsi/scsi_sa.c b/sys/bus/cam/scsi/scsi_sa.c index 50c5f58aa0..68dddc56fd 100644 --- a/sys/bus/cam/scsi/scsi_sa.c +++ b/sys/bus/cam/scsi/scsi_sa.c @@ -1,6 +1,6 @@ /* * $FreeBSD: src/sys/cam/scsi/scsi_sa.c,v 1.45.2.13 2002/12/17 17:08:50 trhodes Exp $ - * $DragonFly: src/sys/bus/cam/scsi/scsi_sa.c,v 1.35 2008/05/18 20:30:20 pavalos Exp $ + * $DragonFly: src/sys/bus/cam/scsi/scsi_sa.c,v 1.35.2.1 2008/07/18 00:08:23 dillon Exp $ * * Implementation of SCSI Sequential Access Peripheral driver for CAM. * @@ -497,15 +497,13 @@ saopen(struct dev_open_args *ap) if (error && (ap->a_oflags & O_NONBLOCK)) { softc->flags |= SA_FLAG_OPEN; softc->open_pending_mount = 1; - cam_periph_unhold(periph); - cam_periph_unlock(periph); + cam_periph_unhold(periph, 1); return (0); } } if (error) { - cam_periph_unhold(periph); - cam_periph_unlock(periph); + cam_periph_unhold(periph, 1); cam_periph_release(periph); return (error); } @@ -513,8 +511,7 @@ saopen(struct dev_open_args *ap) saprevent(periph, PR_PREVENT); softc->flags |= SA_FLAG_OPEN; - cam_periph_unhold(periph); - cam_periph_unlock(periph); + cam_periph_unhold(periph, 1); return (error); } @@ -669,8 +666,7 @@ saclose(struct dev_close_args *ap) if ((softc->flags & SA_FLAG_TAPE_MOUNTED) == 0) sareservereleaseunit(periph, FALSE); - cam_periph_unhold(periph); - cam_periph_unlock(periph); + cam_periph_unhold(periph, 1); cam_periph_release(periph); return (error); @@ -835,7 +831,7 @@ saioctl(struct dev_ioctl_args *ap) struct cam_periph *periph; struct sa_softc *softc; scsi_space_code spaceop; - int didlockperiph = 0; + int didholdperiph = 0; int unit; int mode; int error = 0; @@ -880,7 +876,7 @@ saioctl(struct dev_ioctl_args *ap) if (error != 0) { return (error); } - didlockperiph = 1; + didholdperiph = 1; } break; @@ -916,7 +912,7 @@ saioctl(struct dev_ioctl_args *ap) if (error != 0) { return (error); } - didlockperiph = 1; + didholdperiph = 1; break; default: @@ -999,13 +995,13 @@ saioctl(struct dev_ioctl_args *ap) */ if (softc->last_resid_was_io) { if ((g->mt_resid = (short) softc->last_io_resid) != 0) { - if (SA_IS_CTRL(dev) == 0 || didlockperiph) { + if (SA_IS_CTRL(dev) == 0 || didholdperiph) { softc->last_io_resid = 0; } } } else { if ((g->mt_resid = (short)softc->last_ctl_resid) != 0) { - if (SA_IS_CTRL(dev) == 0 || didlockperiph) { + if (SA_IS_CTRL(dev) == 0 || didholdperiph) { softc->last_ctl_resid = 0; } } @@ -1034,7 +1030,7 @@ saioctl(struct dev_ioctl_args *ap) sizeof (sep->ctl_cdb)); if ((SA_IS_CTRL(dev) == 0 && softc->open_pending_mount) || - didlockperiph) + didholdperiph) bzero((caddr_t) &softc->errinfo, sizeof (softc->errinfo)); error = 0; @@ -1340,10 +1336,10 @@ saioctl(struct dev_ioctl_args *ap) break; } } - if (didlockperiph) { - cam_periph_unhold(periph); - } - cam_periph_unlock(periph); + if (didholdperiph) + cam_periph_unhold(periph, 1); + else + cam_periph_unlock(periph); return (error); } diff --git a/sys/bus/cam/scsi/scsi_target.c b/sys/bus/cam/scsi/scsi_target.c index 819a49ace8..c2fc8a7d45 100644 --- a/sys/bus/cam/scsi/scsi_target.c +++ b/sys/bus/cam/scsi/scsi_target.c @@ -27,7 +27,7 @@ * SUCH DAMAGE. * * $FreeBSD: src/sys/cam/scsi/scsi_target.c,v 1.22.2.7 2003/02/18 22:07:10 njl Exp $ - * $DragonFly: src/sys/bus/cam/scsi/scsi_target.c,v 1.19 2008/05/18 20:30:20 pavalos Exp $ + * $DragonFly: src/sys/bus/cam/scsi/scsi_target.c,v 1.19.2.1 2008/07/18 00:08:23 dillon Exp $ */ #include @@ -374,7 +374,7 @@ targreadfilt(struct knote *kn, long hint) int retval; softc = (struct targ_softc *)kn->kn_hook; - cam_periph_unlock(softc->periph); + cam_periph_lock(softc->periph); retval = !TAILQ_EMPTY(&softc->user_ccb_queue) || !TAILQ_EMPTY(&softc->abort_queue); cam_periph_unlock(softc->periph);