Fix data race in scsi cd driver.
There is a data race between cdsysctlinit and cdcheckmedia. Both functions change softc->flags without synchronization. Submitted by: Arseny Smalyuk <smalukav@gmail.com> MFC after: 2 weeks Differential Revision: https://reviews.freebsd.org/D31726
This commit is contained in:
parent
2d78130185
commit
e76786909c
@ -371,6 +371,7 @@ cdoninvalidate(struct cam_periph *periph)
|
||||
{
|
||||
struct cd_softc *softc;
|
||||
|
||||
cam_periph_assert(periph, MA_OWNED);
|
||||
softc = (struct cd_softc *)periph->softc;
|
||||
|
||||
/*
|
||||
@ -451,7 +452,7 @@ cdasync(void *callback_arg, u_int32_t code,
|
||||
printf("cdasync: Unable to attach new device "
|
||||
"due to status 0x%x\n", status);
|
||||
|
||||
break;
|
||||
return;
|
||||
}
|
||||
case AC_UNIT_ATTENTION:
|
||||
{
|
||||
@ -471,10 +472,10 @@ cdasync(void *callback_arg, u_int32_t code,
|
||||
if (asc == 0x28 && ascq == 0x00)
|
||||
disk_media_changed(softc->disk, M_NOWAIT);
|
||||
}
|
||||
cam_periph_async(periph, code, path, arg);
|
||||
break;
|
||||
}
|
||||
case AC_SCSI_AEN:
|
||||
cam_periph_assert(periph, MA_OWNED);
|
||||
softc = (struct cd_softc *)periph->softc;
|
||||
if (softc->state == CD_STATE_NORMAL && !softc->tur) {
|
||||
if (cam_periph_acquire(periph) == 0) {
|
||||
@ -488,6 +489,7 @@ cdasync(void *callback_arg, u_int32_t code,
|
||||
{
|
||||
struct ccb_hdr *ccbh;
|
||||
|
||||
cam_periph_assert(periph, MA_OWNED);
|
||||
softc = (struct cd_softc *)periph->softc;
|
||||
/*
|
||||
* Don't fail on the expected unit attention
|
||||
@ -496,12 +498,13 @@ cdasync(void *callback_arg, u_int32_t code,
|
||||
softc->flags |= CD_FLAG_RETRY_UA;
|
||||
LIST_FOREACH(ccbh, &softc->pending_ccbs, periph_links.le)
|
||||
ccbh->ccb_state |= CD_CCB_RETRY_UA;
|
||||
/* FALLTHROUGH */
|
||||
}
|
||||
default:
|
||||
cam_periph_async(periph, code, path, arg);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
cam_periph_async(periph, code, path, arg);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -520,7 +523,9 @@ cdsysctlinit(void *context, int pending)
|
||||
snprintf(tmpstr2, sizeof(tmpstr2), "%d", periph->unit_number);
|
||||
|
||||
sysctl_ctx_init(&softc->sysctl_ctx);
|
||||
cam_periph_lock(periph);
|
||||
softc->flags |= CD_FLAG_SCTX_INIT;
|
||||
cam_periph_unlock(periph);
|
||||
softc->sysctl_tree = SYSCTL_ADD_NODE_WITH_LABEL(&softc->sysctl_ctx,
|
||||
SYSCTL_STATIC_CHILDREN(_kern_cam_cd), OID_AUTO,
|
||||
tmpstr2, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, tmpstr,
|
||||
@ -899,6 +904,7 @@ cdstart(struct cam_periph *periph, union ccb *start_ccb)
|
||||
struct bio *bp;
|
||||
struct ccb_scsiio *csio;
|
||||
|
||||
cam_periph_assert(periph, MA_OWNED);
|
||||
softc = (struct cd_softc *)periph->softc;
|
||||
|
||||
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cdstart\n"));
|
||||
@ -1143,6 +1149,7 @@ cddone(struct cam_periph *periph, union ccb *done_ccb)
|
||||
|
||||
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cddone\n"));
|
||||
|
||||
cam_periph_assert(periph, MA_OWNED);
|
||||
softc = (struct cd_softc *)periph->softc;
|
||||
csio = &done_ccb->csio;
|
||||
|
||||
@ -2624,6 +2631,7 @@ cdprevent(struct cam_periph *periph, int action)
|
||||
|
||||
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("entering cdprevent\n"));
|
||||
|
||||
cam_periph_assert(periph, MA_OWNED);
|
||||
softc = (struct cd_softc *)periph->softc;
|
||||
|
||||
if (((action == PR_ALLOW)
|
||||
@ -2661,6 +2669,7 @@ cdmediaprobedone(struct cam_periph *periph)
|
||||
{
|
||||
struct cd_softc *softc;
|
||||
|
||||
cam_periph_assert(periph, MA_OWNED);
|
||||
softc = (struct cd_softc *)periph->softc;
|
||||
|
||||
softc->flags &= ~CD_FLAG_MEDIA_SCAN_ACT;
|
||||
@ -2682,6 +2691,7 @@ cdcheckmedia(struct cam_periph *periph, int do_wait)
|
||||
struct cd_softc *softc;
|
||||
int error;
|
||||
|
||||
cam_periph_assert(periph, MA_OWNED);
|
||||
softc = (struct cd_softc *)periph->softc;
|
||||
error = 0;
|
||||
|
||||
@ -3071,13 +3081,14 @@ cderror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
|
||||
periph = xpt_path_periph(ccb->ccb_h.path);
|
||||
softc = (struct cd_softc *)periph->softc;
|
||||
|
||||
error = 0;
|
||||
cam_periph_assert(periph, MA_OWNED);
|
||||
|
||||
/*
|
||||
* We use a status of CAM_REQ_INVALID as shorthand -- if a 6 byte
|
||||
* CDB comes back with this particular error, try transforming it
|
||||
* into the 10 byte version.
|
||||
*/
|
||||
error = 0;
|
||||
if ((ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_INVALID) {
|
||||
error = cd6byteworkaround(ccb);
|
||||
} else if (scsi_extract_sense_ccb(ccb,
|
||||
|
Loading…
Reference in New Issue
Block a user