diff options
author | mav <mav@FreeBSD.org> | 2012-05-29 11:22:40 +0000 |
---|---|---|
committer | mav <mav@FreeBSD.org> | 2012-05-29 11:22:40 +0000 |
commit | ff66e936dd305e4b4b5e2bdab0b958a7d4d17278 (patch) | |
tree | 2235b3d44403e7b2e1da608e4c68d2be4066f774 /sys/cam | |
parent | fdd7d585a873a693d950b84af0afe3b9f8551313 (diff) | |
download | FreeBSD-src-ff66e936dd305e4b4b5e2bdab0b958a7d4d17278.zip FreeBSD-src-ff66e936dd305e4b4b5e2bdab0b958a7d4d17278.tar.gz |
Plug request and references leak caused by race between invalidated
ond probe periph destruction and new incoming probe request.
This at least caused problems with SATA Port Multipliers hot-plug.
MFC after: 2 weeks
Diffstat (limited to 'sys/cam')
-rw-r--r-- | sys/cam/ata/ata_xpt.c | 17 | ||||
-rw-r--r-- | sys/cam/scsi/scsi_xpt.c | 15 |
2 files changed, 21 insertions, 11 deletions
diff --git a/sys/cam/ata/ata_xpt.c b/sys/cam/ata/ata_xpt.c index dd8b901..ee2e409 100644 --- a/sys/cam/ata/ata_xpt.c +++ b/sys/cam/ata/ata_xpt.c @@ -1327,9 +1327,9 @@ done: done_ccb->ccb_h.status = found ? CAM_REQ_CMP : CAM_REQ_CMP_ERR; xpt_done(done_ccb); } + cam_periph_invalidate(periph); cam_release_devq(periph->path, RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_XPT + 1, FALSE); - cam_periph_invalidate(periph); cam_periph_release_locked(periph); } @@ -1580,12 +1580,17 @@ ata_scan_lun(struct cam_periph *periph, struct cam_path *path, } if ((old_periph = cam_periph_find(path, "aprobe")) != NULL) { - probe_softc *softc; + if ((old_periph->flags & CAM_PERIPH_INVALID) == 0) { + probe_softc *softc; - softc = (probe_softc *)old_periph->softc; - TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->ccb_h, - periph_links.tqe); - softc->restart = 1; + softc = (probe_softc *)old_periph->softc; + TAILQ_INSERT_TAIL(&softc->request_ccbs, + &request_ccb->ccb_h, periph_links.tqe); + softc->restart = 1; + } else { + request_ccb->ccb_h.status = CAM_REQ_CMP_ERR; + xpt_done(request_ccb); + } } else { status = cam_periph_alloc(proberegister, NULL, probecleanup, probestart, "aprobe", diff --git a/sys/cam/scsi/scsi_xpt.c b/sys/cam/scsi/scsi_xpt.c index ce72180..cdcff53 100644 --- a/sys/cam/scsi/scsi_xpt.c +++ b/sys/cam/scsi/scsi_xpt.c @@ -1706,9 +1706,9 @@ probe_device_check: done_ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(done_ccb); if (TAILQ_FIRST(&softc->request_ccbs) == NULL) { + cam_periph_invalidate(periph); cam_release_devq(periph->path, RELSIM_RELEASE_RUNLEVEL, 0, CAM_RL_XPT + 1, FALSE); - cam_periph_invalidate(periph); cam_periph_release_locked(periph); } else { probeschedule(periph); @@ -2274,11 +2274,16 @@ scsi_scan_lun(struct cam_periph *periph, struct cam_path *path, } if ((old_periph = cam_periph_find(path, "probe")) != NULL) { - probe_softc *softc; + if ((old_periph->flags & CAM_PERIPH_INVALID) == 0) { + probe_softc *softc; - softc = (probe_softc *)old_periph->softc; - TAILQ_INSERT_TAIL(&softc->request_ccbs, &request_ccb->ccb_h, - periph_links.tqe); + softc = (probe_softc *)old_periph->softc; + TAILQ_INSERT_TAIL(&softc->request_ccbs, + &request_ccb->ccb_h, periph_links.tqe); + } else { + request_ccb->ccb_h.status = CAM_REQ_CMP_ERR; + xpt_done(request_ccb); + } } else { status = cam_periph_alloc(proberegister, NULL, probecleanup, probestart, "probe", |