summaryrefslogtreecommitdiffstats
path: root/sys/cam
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2012-05-29 11:22:40 +0000
committermav <mav@FreeBSD.org>2012-05-29 11:22:40 +0000
commitff66e936dd305e4b4b5e2bdab0b958a7d4d17278 (patch)
tree2235b3d44403e7b2e1da608e4c68d2be4066f774 /sys/cam
parentfdd7d585a873a693d950b84af0afe3b9f8551313 (diff)
downloadFreeBSD-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.c17
-rw-r--r--sys/cam/scsi/scsi_xpt.c15
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",
OpenPOWER on IntegriCloud