Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F148277704
D14040.id38421.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
9 KB
Referenced Files
None
Subscribers
None
D14040.id38421.diff
View Options
Index: sys/cam/cam_xpt.c
===================================================================
--- sys/cam/cam_xpt.c
+++ sys/cam/cam_xpt.c
@@ -5374,8 +5374,8 @@
static void
xpt_done_process(struct ccb_hdr *ccb_h)
{
- struct cam_sim *sim;
- struct cam_devq *devq;
+ struct cam_sim *sim = NULL;
+ struct cam_devq *devq = NULL;
struct mtx *mtx = NULL;
#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING)
@@ -5418,9 +5418,15 @@
mtx_unlock(&xsoftc.xpt_highpower_lock);
}
- sim = ccb_h->path->bus->sim;
+ /*
+ * Insulate against a race where the periph is destroyed
+ * but CCBs are still not all processed.
+ */
+ if (ccb_h->path->bus)
+ sim = ccb_h->path->bus->sim;
if (ccb_h->status & CAM_RELEASE_SIMQ) {
+ KASSERT(sim, "sim missing for CAM_RELEASE_SIMQ request");
xpt_release_simq(sim, /*run_queue*/FALSE);
ccb_h->status &= ~CAM_RELEASE_SIMQ;
}
@@ -5431,10 +5437,13 @@
ccb_h->status &= ~CAM_DEV_QFRZN;
}
- devq = sim->devq;
if ((ccb_h->func_code & XPT_FC_USER_CCB) == 0) {
struct cam_ed *dev = ccb_h->path->device;
+ if (sim)
+ devq = sim->devq;
+ KASSERT(devq, "sim missing for XPT_FC_USER_CCB request");
+
mtx_lock(&devq->send_mtx);
devq->send_active--;
devq->send_openings++;
Index: sys/cam/scsi/scsi_da.c
===================================================================
--- sys/cam/scsi/scsi_da.c
+++ sys/cam/scsi/scsi_da.c
@@ -51,6 +51,7 @@
#include <sys/sbuf.h>
#include <geom/geom.h>
#include <geom/geom_disk.h>
+#include <machine/atomic.h>
#endif /* _KERNEL */
#ifndef _KERNEL
@@ -291,6 +292,18 @@
#define DA_WORK_TUR (1 << 16)
+typedef enum {
+ DA_REF_OPEN,
+ DA_REF_OPEN_HOLD,
+ DA_REF_CLOSE_HOLD,
+ DA_REF_PROBE_HOLD,
+ DA_REF_TUR,
+ DA_REF_GEOM,
+ DA_REF_SYSCTL,
+ DA_REF_REPROBE,
+ DA_REF_MAX /* KEEP LAST */
+} da_ref_token;
+
struct da_softc {
struct cam_iosched_softc *cam_iosched;
struct bio_queue_head delete_run_queue;
@@ -335,6 +348,7 @@
uint8_t unmap_buf[UNMAP_BUF_SIZE];
struct scsi_read_capacity_data_long rcaplong;
struct callout mediapoll_c;
+ int ref_flags[DA_REF_MAX];
#ifdef CAM_IO_STATS
struct sysctl_ctx_list sysctl_stats_ctx;
struct sysctl_oid *sysctl_stats_tree;
@@ -1469,6 +1483,80 @@
static MALLOC_DEFINE(M_SCSIDA, "scsi_da", "scsi_da buffers");
+static inline int
+da_periph_hold(struct cam_periph *periph, int priority, da_ref_token token)
+{
+ int err = cam_periph_hold(periph, priority);
+
+ if (err == 0) {
+ int cnt;
+ struct da_softc *softc = periph->softc;
+
+ cnt = atomic_fetchadd_int(&softc->ref_flags[token], 1);
+ if (cnt != 0)
+ panic("Re-holding for reason %d, cnt = %d", token, cnt);
+ }
+ return (err);
+}
+
+static inline void
+da_periph_unhold(struct cam_periph *periph, da_ref_token token)
+{
+ int cnt;
+ struct da_softc *softc = periph->softc;
+
+ cam_periph_unhold(periph);
+ cnt = atomic_fetchadd_int(&softc->ref_flags[token], -1);
+ if (cnt != 1)
+ panic("Unholding %d with cnt = %d", token, cnt);
+}
+
+static inline int
+da_periph_acquire(struct cam_periph *periph, da_ref_token token)
+{
+ int err = cam_periph_acquire(periph);
+
+ if (err == 0) {
+ int cnt;
+ struct da_softc *softc = periph->softc;
+
+ cnt = atomic_fetchadd_int(&softc->ref_flags[token], 1);
+ if (cnt != 0)
+ panic("Re-refing for reason %d, cnt = %d", token, cnt);
+ }
+ return (err);
+}
+
+static inline void
+da_periph_release(struct cam_periph *periph, da_ref_token token)
+{
+ int cnt;
+ struct da_softc *softc = periph->softc;
+
+ cam_periph_release(periph);
+ cnt = atomic_fetchadd_int(&softc->ref_flags[token], -1);
+ if (cnt != 1)
+ panic("Unholding %d with cnt = %d", token, cnt);
+}
+
+static inline void
+da_periph_release_locked(struct cam_periph *periph, da_ref_token token)
+{
+ int cnt;
+ struct da_softc *softc = periph->softc;
+
+ cam_periph_release_locked(periph);
+ cnt = atomic_fetchadd_int(&softc->ref_flags[token], -1);
+ if (cnt != 1)
+ panic("Unholding %d with cnt = %d", token, cnt);
+}
+
+#define cam_periph_hold POISON
+#define cam_periph_unhold POISON
+#define cam_periph_acquire POISON
+#define cam_periph_release POISON
+#define cam_periph_release_locked POISON
+
static int
daopen(struct disk *dp)
{
@@ -1477,14 +1565,14 @@
int error;
periph = (struct cam_periph *)dp->d_drv1;
- if (cam_periph_acquire(periph) != CAM_REQ_CMP) {
+ if (da_periph_acquire(periph, DA_REF_OPEN) != CAM_REQ_CMP) {
return (ENXIO);
}
cam_periph_lock(periph);
- if ((error = cam_periph_hold(periph, PRIBIO|PCATCH)) != 0) {
+ if ((error = da_periph_hold(periph, PRIBIO|PCATCH, DA_REF_OPEN_HOLD)) != 0) {
cam_periph_unlock(periph);
- cam_periph_release(periph);
+ da_periph_release(periph, DA_REF_OPEN);
return (error);
}
@@ -1512,11 +1600,11 @@
softc->flags |= DA_FLAG_OPEN;
}
- cam_periph_unhold(periph);
+ da_periph_unhold(periph, DA_REF_OPEN_HOLD);
cam_periph_unlock(periph);
if (error != 0)
- cam_periph_release(periph);
+ da_periph_release(periph, DA_REF_OPEN);
return (error);
}
@@ -1534,7 +1622,7 @@
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE | CAM_DEBUG_PERIPH,
("daclose\n"));
- if (cam_periph_hold(periph, PRIBIO) == 0) {
+ if (da_periph_hold(periph, PRIBIO, DA_REF_CLOSE_HOLD) == 0) {
/* Flush disk cache. */
if ((softc->flags & DA_FLAG_DIRTY) != 0 &&
@@ -1557,7 +1645,7 @@
(softc->quirks & DA_Q_NO_PREVENT) == 0)
daprevent(periph, PR_ALLOW);
- cam_periph_unhold(periph);
+ da_periph_unhold(periph, DA_REF_CLOSE_HOLD);
}
/*
@@ -1572,7 +1660,7 @@
while (softc->refcount != 0)
cam_periph_sleep(periph, &softc->refcount, PRIBIO, "daclose", 1);
cam_periph_unlock(periph);
- cam_periph_release(periph);
+ da_periph_release(periph, DA_REF_OPEN);
return (0);
}
@@ -1750,7 +1838,7 @@
struct cam_periph *periph;
periph = (struct cam_periph *)dp->d_drv1;
- cam_periph_release(periph);
+ da_periph_release(periph, DA_REF_GEOM);
}
static void
@@ -1910,7 +1998,7 @@
case AC_SCSI_AEN:
softc = (struct da_softc *)periph->softc;
if (!cam_iosched_has_work_flags(softc->cam_iosched, DA_WORK_TUR)) {
- if (cam_periph_acquire(periph) == CAM_REQ_CMP) {
+ if (da_periph_acquire(periph, DA_REF_TUR) == CAM_REQ_CMP) {
cam_iosched_set_work_flags(softc->cam_iosched, DA_WORK_TUR);
daschedule(periph);
}
@@ -1955,7 +2043,7 @@
* periph was held for us when this task was enqueued
*/
if (periph->flags & CAM_PERIPH_INVALID) {
- cam_periph_release(periph);
+ da_periph_release(periph, DA_REF_SYSCTL);
return;
}
@@ -1970,7 +2058,7 @@
CTLFLAG_RD, 0, tmpstr, "device_index");
if (softc->sysctl_tree == NULL) {
printf("dasysctlinit: unable to allocate sysctl tree\n");
- cam_periph_release(periph);
+ da_periph_release(periph, DA_REF_SYSCTL);
return;
}
@@ -2052,7 +2140,7 @@
xpt_action((union ccb *)&cts);
cam_periph_unlock(periph);
if (cts.ccb_h.status != CAM_REQ_CMP) {
- cam_periph_release(periph);
+ da_periph_release(periph, DA_REF_SYSCTL);
return;
}
if (cts.protocol == PROTO_SCSI && cts.transport == XPORT_FC) {
@@ -2103,7 +2191,7 @@
cam_iosched_sysctl_init(softc->cam_iosched, &softc->sysctl_ctx,
softc->sysctl_tree);
- cam_periph_release(periph);
+ da_periph_release(periph, DA_REF_SYSCTL);
}
static int
@@ -2269,9 +2357,9 @@
wakeup(&softc->disk->d_mediasize);
if ((softc->flags & DA_FLAG_ANNOUNCED) == 0) {
softc->flags |= DA_FLAG_ANNOUNCED;
- cam_periph_unhold(periph);
+ da_periph_unhold(periph, DA_REF_PROBE_HOLD);
} else
- cam_periph_release_locked(periph);
+ da_periph_release_locked(periph, DA_REF_REPROBE);
}
static void
@@ -2484,8 +2572,10 @@
* Take an exclusive refcount on the periph while dastart is called
* to finish the probe. The reference will be dropped in dadone at
* the end of probe.
+ *
+ * XXX if cam_periph_hold returns an error, we don't hold a refcount.
*/
- (void)cam_periph_hold(periph, PRIBIO);
+ (void)da_periph_hold(periph, PRIBIO, DA_REF_PROBE_HOLD);
/*
* Schedule a periodic event to occasionally send an
@@ -2579,7 +2669,7 @@
* We'll release this reference once GEOM calls us back (via
* dadiskgonecb()) telling us that our provider has been freed.
*/
- if (cam_periph_acquire(periph) != CAM_REQ_CMP) {
+ if (da_periph_acquire(periph, DA_REF_GEOM) != CAM_REQ_CMP) {
xpt_print(periph->path, "%s: lost periph during "
"registration!\n", __func__);
cam_periph_lock(periph);
@@ -2965,7 +3055,7 @@
if (cam_iosched_has_work_flags(softc->cam_iosched, DA_WORK_TUR)) {
cam_iosched_clr_work_flags(softc->cam_iosched, DA_WORK_TUR);
- cam_periph_release_locked(periph);
+ da_periph_release_locked(periph, DA_REF_TUR);
}
if ((bp->bio_flags & BIO_ORDERED) != 0 ||
@@ -4547,7 +4637,7 @@
* we have successfully attached.
*/
/* increase the refcount */
- if (cam_periph_acquire(periph) == CAM_REQ_CMP) {
+ if (da_periph_acquire(periph, DA_REF_SYSCTL) == CAM_REQ_CMP) {
taskqueue_enqueue(taskqueue_thread,
&softc->sysctl_task);
@@ -5392,7 +5482,7 @@
/*getcount_only*/0);
}
xpt_release_ccb(done_ccb);
- cam_periph_release_locked(periph);
+ da_periph_release_locked(periph, DA_REF_TUR);
return;
}
default:
@@ -5413,7 +5503,7 @@
if (softc->state != DA_STATE_NORMAL)
return;
- status = cam_periph_acquire(periph);
+ status = da_periph_acquire(periph, DA_REF_REPROBE);
KASSERT(status == CAM_REQ_CMP,
("dareprobe: cam_periph_acquire failed"));
@@ -5513,7 +5603,7 @@
if (!cam_iosched_has_work_flags(softc->cam_iosched, DA_WORK_TUR) &&
LIST_EMPTY(&softc->pending_ccbs)) {
- if (cam_periph_acquire(periph) == CAM_REQ_CMP) {
+ if (da_periph_acquire(periph, DA_REF_TUR) == CAM_REQ_CMP) {
cam_iosched_set_work_flags(softc->cam_iosched, DA_WORK_TUR);
daschedule(periph);
}
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Tue, Mar 17, 11:17 PM (2 h, 39 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29858346
Default Alt Text
D14040.id38421.diff (9 KB)
Attached To
Mode
D14040: Debugging for arrival / depature code.
Attached
Detach File
Event Timeline
Log In to Comment