Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F148341702
D14040.id38453.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
10 KB
Referenced Files
None
Subscribers
None
D14040.id38453.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,31 @@
#define DA_WORK_TUR (1 << 16)
+typedef enum {
+ DA_REF_OPEN = 1,
+ 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;
+
+const char *da_ref_text[] = {
+ "bogus",
+ "open",
+ "open hold",
+ "close hold",
+ "reprobe hold",
+ "Test Unit Ready",
+ "Geom",
+ "sysctl",
+ "reprobe",
+ "max -- also bogus"
+};
+
struct da_softc {
struct cam_iosched_softc *cam_iosched;
struct bio_queue_head delete_run_queue;
@@ -335,6 +361,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 +1496,105 @@
static MALLOC_DEFINE(M_SCSIDA, "scsi_da", "scsi_da buffers");
+#define CAM_PERIPH_PRINT(p, fmt...) xpt_print((p)->path, ##fmt)
+//#define CAM_PERIPH_PRINT(p, fmt...)
+
+static inline void
+token_sanity(da_ref_token token)
+{
+ if ((unsigned)token >= DA_REF_MAX)
+ panic("Bad token value passed in %d\n", token);
+}
+
+static inline int
+da_periph_hold(struct cam_periph *periph, int priority, da_ref_token token)
+{
+ int err = cam_periph_hold(periph, priority);
+
+ token_sanity(token);
+ CAM_PERIPH_PRINT(periph, "Holding device %s (%d): %d\n",
+ da_ref_text[token], token, err);
+ 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;
+
+ token_sanity(token);
+ cam_periph_unhold(periph);
+ CAM_PERIPH_PRINT(periph, "Unholding device %s (%d)\n",
+ da_ref_text[token], token);
+ 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);
+
+ token_sanity(token);
+ CAM_PERIPH_PRINT(periph, "acquiring device %s (%d): %d\n",
+ da_ref_text[token], token, err);
+ if (err == CAM_REQ_CMP) {
+ 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;
+
+ token_sanity(token);
+ cam_periph_release(periph);
+ CAM_PERIPH_PRINT(periph, "releasing device %s (%d)\n",
+ da_ref_text[token], token);
+ 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;
+
+ token_sanity(token);
+ cam_periph_release_locked(periph);
+ CAM_PERIPH_PRINT(periph, "releasing device (locked) %s (%d)\n",
+ da_ref_text[token], token);
+ 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 +1603,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 +1638,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 +1660,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 +1683,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 +1698,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 +1876,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 +2036,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 +2081,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 +2096,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 +2178,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 +2229,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 +2395,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 +2610,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 +2707,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 +3093,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 +4675,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 +5520,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 +5541,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 +5641,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
Wed, Mar 18, 6:21 AM (8 h, 12 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
29848974
Default Alt Text
D14040.id38453.diff (10 KB)
Attached To
Mode
D14040: Debugging for arrival / depature code.
Attached
Detach File
Event Timeline
Log In to Comment