MFC CAM fixes for the 2.0 release.
authorMatthew Dillon <dillon@dragonflybsd.org>
Fri, 18 Jul 2008 00:08:23 +0000 (18 00:08 +0000)
committerMatthew Dillon <dillon@dragonflybsd.org>
Fri, 18 Jul 2008 00:08:23 +0000 (18 00:08 +0000)
sys/bus/cam/cam_periph.c
sys/bus/cam/cam_periph.h
sys/bus/cam/cam_sim.c
sys/bus/cam/cam_sim.h
sys/bus/cam/cam_xpt.c
sys/bus/cam/scsi/scsi_cd.c
sys/bus/cam/scsi/scsi_ch.c
sys/bus/cam/scsi/scsi_da.c
sys/bus/cam/scsi/scsi_sa.c
sys/bus/cam/scsi/scsi_target.c

index 57804fd..f776625 100644 (file)
@@ -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 <sys/param.h>
@@ -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
index d9c27a8..e2ade26 100644 (file)
@@ -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);
index 81448c9..fe93de2 100644 (file)
@@ -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 <sys/param.h>
@@ -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
index c8fcc52..77ff571 100644 (file)
@@ -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 */
index 168ffc2..e6deabf 100644 (file)
@@ -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 <sys/param.h>
 #include <sys/systm.h>
@@ -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
index 1060b4e..455c89e 100644 (file)
@@ -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);
 }
index dc5de89..d235763 100644 (file)
@@ -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:
index a2162a9..667dfd0 100644 (file)
@@ -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 <sys/param.h>
@@ -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:
index 50c5f58..68dddc5 100644 (file)
@@ -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);
 }
 
index 819a49a..c2fc8a7 100644 (file)
@@ -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 <sys/param.h>
@@ -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);