diff options
author | njl <njl@FreeBSD.org> | 2003-09-04 16:30:03 +0000 |
---|---|---|
committer | njl <njl@FreeBSD.org> | 2003-09-04 16:30:03 +0000 |
commit | 657b53c623f5bca13deb8635bd9576243958912c (patch) | |
tree | 52cdc3ddbfa474aa07bc6192384e79b64a7424f3 /sys | |
parent | c54c55a75cfcc2fdea6cd7efcc88e89cae29f87b (diff) | |
download | FreeBSD-src-657b53c623f5bca13deb8635bd9576243958912c.zip FreeBSD-src-657b53c623f5bca13deb8635bd9576243958912c.tar.gz |
Calling KNOTE with locks held may result in recursion when it calls back
into targreadfilt(). Unlock around calls to notify_user(). If an application
is sending CCBs while the endpoint is shutting down, this may result in
incomplete disable. A more complete solution will come with a "dying" flag.
Submitted by: simokawa
Diffstat (limited to 'sys')
-rw-r--r-- | sys/cam/scsi/scsi_target.c | 15 |
1 files changed, 13 insertions, 2 deletions
diff --git a/sys/cam/scsi/scsi_target.c b/sys/cam/scsi/scsi_target.c index 4f9187a..ec8894d 100644 --- a/sys/cam/scsi/scsi_target.c +++ b/sys/cam/scsi/scsi_target.c @@ -823,6 +823,7 @@ targdone(struct cam_periph *periph, union ccb *done_ccb) case XPT_CONT_TARGET_IO: TAILQ_INSERT_TAIL(&softc->user_ccb_queue, &done_ccb->ccb_h, periph_links.tqe); + TARG_UNLOCK(softc); notify_user(softc); break; default: @@ -830,7 +831,6 @@ targdone(struct cam_periph *periph, union ccb *done_ccb) done_ccb->ccb_h.func_code); /* NOTREACHED */ } - TARG_UNLOCK(softc); } /* Return CCBs to the user from the user queue and abort queue */ @@ -1096,8 +1096,19 @@ abort_all_pending(struct targ_softc *softc) /* If we aborted anything from the work queue, wakeup user. */ if (!TAILQ_EMPTY(&softc->user_ccb_queue) - || !TAILQ_EMPTY(&softc->abort_queue)) + || !TAILQ_EMPTY(&softc->abort_queue)) { + /* + * XXX KNOTE calls back into targreadfilt, causing a + * lock recursion. So unlock around calls to it although + * this may open up a race allowing a user to submit + * another CCB after we have aborted all pending ones + * A better approach is to mark the softc as dying + * under lock and check for this in targstart(). + */ + TARG_UNLOCK(softc); notify_user(softc); + TARG_LOCK(softc); + } } /* Notify the user that data is ready */ |