summaryrefslogtreecommitdiffstats
path: root/sys/cam/scsi
diff options
context:
space:
mode:
authormjacob <mjacob@FreeBSD.org>2010-06-08 22:46:44 +0000
committermjacob <mjacob@FreeBSD.org>2010-06-08 22:46:44 +0000
commit8b02ad35641ab3ca8092806e526711b792290349 (patch)
treedadc61aaae361e7066ba7817b58e4c6760680a6c /sys/cam/scsi
parentd16c7840fb2be941c8009cfd9e3a8c2c55c09290 (diff)
downloadFreeBSD-src-8b02ad35641ab3ca8092806e526711b792290349.zip
FreeBSD-src-8b02ad35641ab3ca8092806e526711b792290349.tar.gz
Rearrange how things are done to avoid dereferencing stale pointers in
the case of immediate unconfigure after configure. Hold the periph an extra count while we have the task to create sysctl context outstanding so that the periph doesn't go away unexpectedly. Sponsored by: Panasas Reviewed by: scsi@ MFC after: 1 month
Diffstat (limited to 'sys/cam/scsi')
-rw-r--r--sys/cam/scsi/scsi_da.c62
1 files changed, 32 insertions, 30 deletions
diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c
index 986648a..7095eeb 100644
--- a/sys/cam/scsi/scsi_da.c
+++ b/sys/cam/scsi/scsi_da.c
@@ -998,11 +998,6 @@ dacleanup(struct cam_periph *periph)
xpt_print(periph->path, "can't remove sysctl context\n");
}
- /*
- * Nullify our periph pointer here to try and catch
- * race conditions in callbacks/downcalls.
- */
- softc->disk->d_drv1 = NULL;
disk_destroy(softc->disk);
callout_drain(&softc->sendordered_c);
free(softc, M_DEVBUF);
@@ -1082,8 +1077,13 @@ dasysctlinit(void *context, int pending)
struct ccb_trans_settings cts;
periph = (struct cam_periph *)context;
- if (cam_periph_acquire(periph) != CAM_REQ_CMP)
+ /*
+ * periph was held for us when this task was enqueued
+ */
+ if (periph->flags & CAM_PERIPH_INVALID) {
+ cam_periph_release(periph);
return;
+ }
softc = (struct da_softc *)periph->softc;
snprintf(tmpstr, sizeof(tmpstr), "CAM DA unit %d", periph->unit_number);
@@ -1263,29 +1263,6 @@ daregister(struct cam_periph *periph, void *arg)
* Register this media as a disk
*/
- mtx_unlock(periph->sim->mtx);
- softc->disk = disk_alloc();
- softc->disk->d_open = daopen;
- softc->disk->d_close = daclose;
- softc->disk->d_strategy = dastrategy;
- softc->disk->d_dump = dadump;
- softc->disk->d_name = "da";
- softc->disk->d_drv1 = periph;
- if (cpi.maxio == 0)
- softc->disk->d_maxsize = DFLTPHYS; /* traditional default */
- else if (cpi.maxio > MAXPHYS)
- softc->disk->d_maxsize = MAXPHYS; /* for safety */
- else
- softc->disk->d_maxsize = cpi.maxio;
- softc->disk->d_unit = periph->unit_number;
- softc->disk->d_flags = 0;
- if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0)
- softc->disk->d_flags |= DISKFLAG_CANFLUSHCACHE;
- strlcpy(softc->disk->d_ident, cgd->serial_num,
- MIN(sizeof(softc->disk->d_ident), cgd->serial_num_len + 1));
- disk_create(softc->disk, DISK_VERSION);
- mtx_lock(periph->sim->mtx);
-
/*
* Add async callbacks for bus reset and
* bus device reset calls. I don't bother
@@ -1303,7 +1280,6 @@ daregister(struct cam_periph *periph, void *arg)
* the end of probe.
*/
(void)cam_periph_hold(periph, PRIBIO);
- xpt_schedule(periph, CAM_PRIORITY_DEV);
/*
* Schedule a periodic event to occasionally send an
@@ -1314,6 +1290,31 @@ daregister(struct cam_periph *periph, void *arg)
(DA_DEFAULT_TIMEOUT * hz) / DA_ORDEREDTAG_INTERVAL,
dasendorderedtag, softc);
+ mtx_unlock(periph->sim->mtx);
+ softc->disk = disk_alloc();
+ softc->disk->d_open = daopen;
+ softc->disk->d_close = daclose;
+ softc->disk->d_strategy = dastrategy;
+ softc->disk->d_dump = dadump;
+ softc->disk->d_name = "da";
+ softc->disk->d_drv1 = periph;
+ if (cpi.maxio == 0)
+ softc->disk->d_maxsize = DFLTPHYS; /* traditional default */
+ else if (cpi.maxio > MAXPHYS)
+ softc->disk->d_maxsize = MAXPHYS; /* for safety */
+ else
+ softc->disk->d_maxsize = cpi.maxio;
+ softc->disk->d_unit = periph->unit_number;
+ softc->disk->d_flags = 0;
+ if ((softc->quirks & DA_Q_NO_SYNC_CACHE) == 0)
+ softc->disk->d_flags |= DISKFLAG_CANFLUSHCACHE;
+ strlcpy(softc->disk->d_ident, cgd->serial_num,
+ MIN(sizeof(softc->disk->d_ident), cgd->serial_num_len + 1));
+ disk_create(softc->disk, DISK_VERSION);
+ mtx_lock(periph->sim->mtx);
+
+ xpt_schedule(periph, CAM_PRIORITY_DEV);
+
return(CAM_REQ_CMP);
}
@@ -1773,6 +1774,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
* Create our sysctl variables, now that we know
* we have successfully attached.
*/
+ (void) cam_periph_acquire(periph); /* increase the refcount */
taskqueue_enqueue(taskqueue_thread,&softc->sysctl_task);
}
softc->state = DA_STATE_NORMAL;
OpenPOWER on IntegriCloud