aboutsummaryrefslogtreecommitdiffstats
path: root/sys/cam/nvme/nvme_da.c
diff options
context:
space:
mode:
authorWarner Losh <imp@FreeBSD.org>2018-05-24 16:31:18 +0000
committerWarner Losh <imp@FreeBSD.org>2018-05-24 16:31:18 +0000
commitb1988d44b3aa483248ad66f4fe4abde99c84eec3 (patch)
treea55face80929000055bb5948ed1cd3e0a4c627cf /sys/cam/nvme/nvme_da.c
parent5f77b8a88b5e22cb5068f2e8d3ab3518634b1f45 (diff)
downloadsrc-b1988d44b3aa483248ad66f4fe4abde99c84eec3.tar.gz
src-b1988d44b3aa483248ad66f4fe4abde99c84eec3.zip
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
Notes
Notes: svn path=/head/; revision=334166
Diffstat (limited to 'sys/cam/nvme/nvme_da.c')
-rw-r--r--sys/cam/nvme/nvme_da.c11
1 files changed, 5 insertions, 6 deletions
diff --git a/sys/cam/nvme/nvme_da.c b/sys/cam/nvme/nvme_da.c
index 76e60be3ed93..f83a038506aa 100644
--- a/sys/cam/nvme/nvme_da.c
+++ b/sys/cam/nvme/nvme_da.c
@@ -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_ccb)
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: