Author: imp
Date: Thu May 24 16:31:18 2018
New Revision: 334166
URL: https://svnweb.freebsd.org/changeset/base/334166

Log:
  We can't release the refcount outside of the periph lock.
  
  We're dropping the periph lock then dropping the refcount. However,
  that violates the locking protocol and is racy. This seems to be
  the cause of weird occasional panics with a bogus assert.
  
  Sponsored by: Netflix
  Differential Revision: https://reviews.freebsd.org/D15517

Modified:
  head/sys/cam/nvme/nvme_da.c

Modified: head/sys/cam/nvme/nvme_da.c
==============================================================================
--- head/sys/cam/nvme/nvme_da.c Thu May 24 16:25:18 2018        (r334165)
+++ head/sys/cam/nvme/nvme_da.c Thu May 24 16:31:18 2018        (r334166)
@@ -336,6 +336,8 @@ ndaclose(struct disk *dp)
 
        while (softc->refcount != 0)
                cam_periph_sleep(periph, &softc->refcount, PRIBIO, "ndaclose", 
1);
+       KASSERT(softc->outstanding_cmds == 0,
+           ("nda %d outstanding commands", softc->outstanding_cmds));
        cam_periph_unlock(periph);
        cam_periph_release(periph);
        return (0);     
@@ -986,10 +988,11 @@ ndastart(struct cam_periph *periph, union ccb *start_c
 out:
                start_ccb->ccb_h.flags |= CAM_UNLOCKED;
                softc->outstanding_cmds++;
-               softc->refcount++;
+               softc->refcount++;                      /* For submission only 
*/
                cam_periph_unlock(periph);
                xpt_action(start_ccb);
                cam_periph_lock(periph);
+               softc->refcount--;                      /* Submission done */
 
                /* May have more work to do, so ensure we stay scheduled */
                ndaschedule(periph);
@@ -1085,6 +1088,7 @@ ndadone(struct cam_periph *periph, union ccb *done_ccb
                        bp1 = TAILQ_FIRST(&queue);
                        cam_iosched_bio_complete(softc->cam_iosched, bp1, 
done_ccb);
                        xpt_release_ccb(done_ccb);
+                       softc->outstanding_cmds--;
                        ndaschedule(periph);
                        cam_periph_unlock(periph);
                        while ((bp2 = TAILQ_FIRST(&queue)) != NULL) {
@@ -1100,11 +1104,6 @@ ndadone(struct cam_periph *periph, union ccb *done_ccb
                                biodone(bp2);
                        }
                }
-               /*
-                * Release the periph refcount taken in mdastart() for each CCB.
-                */
-               KASSERT(softc->refcount >= 1, ("ndadone softc %p refcount %d", 
softc, softc->refcount));
-               softc->refcount--;
                return;
        }
        case NDA_CCB_DUMP:
_______________________________________________
svn-src-head@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to