Author: markj
Date: Sat Nov  5 20:22:12 2016
New Revision: 308351
URL: https://svnweb.freebsd.org/changeset/base/308351

Log:
  MFC r306529:
  cam_periph_ccbwait could return while ccb in progress

Modified:
  stable/11/sys/cam/cam_periph.c
  stable/11/sys/cam/cam_periph.h
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/cam/cam_periph.c
==============================================================================
--- stable/11/sys/cam/cam_periph.c      Sat Nov  5 20:15:58 2016        
(r308350)
+++ stable/11/sys/cam/cam_periph.c      Sat Nov  5 20:22:12 2016        
(r308351)
@@ -975,16 +975,6 @@ cam_periph_unmapmem(union ccb *ccb, stru
        PRELE(curproc);
 }
 
-void
-cam_periph_ccbwait(union ccb *ccb)
-{
-
-       if ((ccb->ccb_h.pinfo.index != CAM_UNQUEUED_INDEX)
-        || ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INPROG))
-               xpt_path_sleep(ccb->ccb_h.path, &ccb->ccb_h.cbfcnp, PRIBIO,
-                   "cbwait", 0);
-}
-
 int
 cam_periph_ioctl(struct cam_periph *periph, u_long cmd, caddr_t addr,
                 int (*error_routine)(union ccb *ccb, 
@@ -1048,13 +1038,38 @@ cam_periph_ioctl(struct cam_periph *peri
 }
 
 static void
+cam_periph_done_panic(struct cam_periph *periph, union ccb *done_ccb)
+{
+
+       panic("%s: already done with ccb %p", __func__, done_ccb);
+}
+
+static void
 cam_periph_done(struct cam_periph *periph, union ccb *done_ccb)
 {
 
        /* Caller will release the CCB */
+       xpt_path_assert(done_ccb->ccb_h.path, MA_OWNED);
+       done_ccb->ccb_h.cbfcnp = cam_periph_done_panic;
        wakeup(&done_ccb->ccb_h.cbfcnp);
 }
 
+static void
+cam_periph_ccbwait(union ccb *ccb)
+{
+
+       if ((ccb->ccb_h.func_code & XPT_FC_QUEUED) != 0) {
+               while (ccb->ccb_h.cbfcnp != cam_periph_done_panic)
+                       xpt_path_sleep(ccb->ccb_h.path, &ccb->ccb_h.cbfcnp,
+                           PRIBIO, "cbwait", 0);
+       }
+       KASSERT(ccb->ccb_h.pinfo.index == CAM_UNQUEUED_INDEX &&
+           (ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_INPROG,
+           ("%s: proceeding with incomplete ccb: ccb=%p, func_code=%#x, "
+            "status=%#x, index=%d", __func__, ccb, ccb->ccb_h.func_code,
+            ccb->ccb_h.status, ccb->ccb_h.pinfo.index));
+}
+
 int
 cam_periph_runccb(union ccb *ccb,
                  int (*error_routine)(union ccb *ccb,
@@ -1069,6 +1084,9 @@ cam_periph_runccb(union ccb *ccb,
  
        starttime = NULL;
        xpt_path_assert(ccb->ccb_h.path, MA_OWNED);
+       KASSERT((ccb->ccb_h.flags & CAM_UNLOCKED) == 0,
+           ("%s: ccb=%p, func_code=%#x, flags=%#x", __func__, ccb,
+            ccb->ccb_h.func_code, ccb->ccb_h.flags));
 
        /*
         * If the user has supplied a stats structure, and if we understand
@@ -1088,9 +1106,10 @@ cam_periph_runccb(union ccb *ccb,
                cam_periph_ccbwait(ccb);
                if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP)
                        error = 0;
-               else if (error_routine != NULL)
+               else if (error_routine != NULL) {
+                       ccb->ccb_h.cbfcnp = cam_periph_done;
                        error = (*error_routine)(ccb, camflags, sense_flags);
-               else
+               } else
                        error = 0;
 
        } while (error == ERESTART);

Modified: stable/11/sys/cam/cam_periph.h
==============================================================================
--- stable/11/sys/cam/cam_periph.h      Sat Nov  5 20:15:58 2016        
(r308350)
+++ stable/11/sys/cam/cam_periph.h      Sat Nov  5 20:22:12 2016        
(r308351)
@@ -166,7 +166,6 @@ void                cam_periph_unmapmem(union ccb *ccb
                                    struct cam_periph_map_info *mapinfo);
 union ccb      *cam_periph_getccb(struct cam_periph *periph,
                                   u_int32_t priority);
-void           cam_periph_ccbwait(union ccb *ccb);
 int            cam_periph_runccb(union ccb *ccb,
                                  int (*error_routine)(union ccb *ccb,
                                                       cam_flags camflags,
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to