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
This commit is contained in:
mav 2012-05-29 11:22:40 +00:00
parent fdd7d585a8
commit ff66e936dd
2 changed files with 21 additions and 11 deletions

View File

@ -1327,9 +1327,9 @@ device_fail: if ((path->device->flags & CAM_DEV_UNCONFIGURED) == 0)
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",

View File

@ -1706,9 +1706,9 @@ probedone(struct cam_periph *periph, union ccb *done_ccb)
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",