aboutsummaryrefslogtreecommitdiff
path: root/sys/cam
diff options
context:
space:
mode:
authorConrad Meyer <cem@FreeBSD.org>2016-10-31 23:09:52 +0000
committerConrad Meyer <cem@FreeBSD.org>2016-10-31 23:09:52 +0000
commit8532d381a91f1e201ab95ab7f913b723e8912571 (patch)
tree38a4d4d75a173395017b59aa5d986d25e29e841a /sys/cam
parent2d5386cc2c570cf781c45cc948a800c8f8d4f0d0 (diff)
downloadsrc-8532d381a91f1e201ab95ab7f913b723e8912571.tar.gz
src-8532d381a91f1e201ab95ab7f913b723e8912571.zip
Add BUF_TRACKING and FULL_BUF_TRACKING buffer debugging
Upstream the BUF_TRACKING and FULL_BUF_TRACKING buffer debugging code. This can be handy in tracking down what code touched hung bios and bufs last. The full history is especially useful, but adds enough bloat that it shouldn't be enabled in release builds. Function names (or arbitrary string constants) are tracked in a fixed-size ring in bufs. Bios gain a pointer to the upper buf for tracking. SCSI CCBs gain a pointer to the upper bio for tracking. Reviewed by: markj Sponsored by: Dell EMC Isilon Differential Revision: https://reviews.freebsd.org/D8366
Notes
Notes: svn path=/head/; revision=308155
Diffstat (limited to 'sys/cam')
-rw-r--r--sys/cam/cam_ccb.h6
-rw-r--r--sys/cam/cam_periph.c5
-rw-r--r--sys/cam/cam_xpt.c17
-rw-r--r--sys/cam/scsi/scsi_da.c15
4 files changed, 43 insertions, 0 deletions
diff --git a/sys/cam/cam_ccb.h b/sys/cam/cam_ccb.h
index 9ec266e84cc1..b638ab1dba9f 100644
--- a/sys/cam/cam_ccb.h
+++ b/sys/cam/cam_ccb.h
@@ -744,6 +744,9 @@ struct ccb_scsiio {
#define CAM_TAG_ACTION_NONE 0x00
u_int tag_id; /* tag id from initator (target mode) */
u_int init_id; /* initiator id of who selected */
+#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING)
+ struct bio *bio; /* Associated bio */
+#endif
};
static __inline uint8_t *
@@ -1335,6 +1338,9 @@ cam_fill_csio(struct ccb_scsiio *csio, u_int32_t retries,
csio->sense_len = sense_len;
csio->cdb_len = cdb_len;
csio->tag_action = tag_action;
+#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING)
+ csio->bio = NULL;
+#endif
}
static __inline void
diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c
index 942a6c30376f..ae4134504b9c 100644
--- a/sys/cam/cam_periph.c
+++ b/sys/cam/cam_periph.c
@@ -1427,6 +1427,11 @@ camperiphscsisenseerror(union ccb *ccb, union ccb **orig,
union ccb *orig_ccb = ccb;
int error, recoveryccb;
+#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING)
+ if (ccb->ccb_h.func_code == XPT_SCSI_IO && ccb->csio.bio != NULL)
+ biotrack(ccb->csio.bio, __func__);
+#endif
+
periph = xpt_path_periph(ccb->ccb_h.path);
recoveryccb = (ccb->ccb_h.cbfcnp == camperiphdone);
if ((periph->flags & CAM_PERIPH_RECOVERY_INPROG) && !recoveryccb) {
diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
index cfca7807c781..34018052ed60 100644
--- a/sys/cam/cam_xpt.c
+++ b/sys/cam/cam_xpt.c
@@ -31,6 +31,7 @@
__FBSDID("$FreeBSD$");
#include <sys/param.h>
+#include <sys/bio.h>
#include <sys/bus.h>
#include <sys/systm.h>
#include <sys/types.h>
@@ -4471,6 +4472,12 @@ xpt_done(union ccb *done_ccb)
struct cam_doneq *queue;
int run, hash;
+#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING)
+ if (done_ccb->ccb_h.func_code == XPT_SCSI_IO &&
+ done_ccb->csio.bio != NULL)
+ biotrack(done_ccb->csio.bio, __func__);
+#endif
+
CAM_DEBUG(done_ccb->ccb_h.path, CAM_DEBUG_TRACE,
("xpt_done: func= %#x %s status %#x\n",
done_ccb->ccb_h.func_code,
@@ -5189,6 +5196,16 @@ xpt_done_process(struct ccb_hdr *ccb_h)
struct cam_devq *devq;
struct mtx *mtx = NULL;
+#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING)
+ struct ccb_scsiio *csio;
+
+ if (ccb_h->func_code == XPT_SCSI_IO) {
+ csio = &((union ccb *)ccb_h)->csio;
+ if (csio->bio != NULL)
+ biotrack(csio->bio, __func__);
+ }
+#endif
+
if (ccb_h->flags & CAM_HIGH_POWER) {
struct highpowerlist *hphead;
struct cam_ed *device;
diff --git a/sys/cam/scsi/scsi_da.c b/sys/cam/scsi/scsi_da.c
index 977ac8d6252b..16d8ef7b07ca 100644
--- a/sys/cam/scsi/scsi_da.c
+++ b/sys/cam/scsi/scsi_da.c
@@ -2949,6 +2949,8 @@ more:
void *data_ptr;
int rw_op;
+ biotrack(bp, __func__);
+
if (bp->bio_cmd == BIO_WRITE) {
softc->flags |= DA_FLAG_DIRTY;
rw_op = SCSI_RW_WRITE;
@@ -2976,6 +2978,9 @@ more:
/*dxfer_len*/ bp->bio_bcount,
/*sense_len*/SSD_FULL_SIZE,
da_default_timeout * 1000);
+#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING)
+ start_ccb->csio.bio = bp;
+#endif
break;
}
case BIO_FLUSH:
@@ -4008,6 +4013,10 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
CAM_DEBUG(periph->path, CAM_DEBUG_TRACE, ("dadone\n"));
csio = &done_ccb->csio;
+#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING)
+ if (csio->bio != NULL)
+ biotrack(csio->bio, __func__);
+#endif
state = csio->ccb_h.ccb_state & DA_CCB_TYPE_MASK;
switch (state) {
case DA_CCB_BUFFER_IO:
@@ -4106,6 +4115,7 @@ dadone(struct cam_periph *periph, union ccb *done_ccb)
}
}
+ biotrack(bp, __func__);
LIST_REMOVE(&done_ccb->ccb_h, periph_links.le);
if (LIST_EMPTY(&softc->pending_ccbs))
softc->flags |= DA_FLAG_WAS_OTAG;
@@ -5219,6 +5229,11 @@ daerror(union ccb *ccb, u_int32_t cam_flags, u_int32_t sense_flags)
struct cam_periph *periph;
int error, error_code, sense_key, asc, ascq;
+#if defined(BUF_TRACKING) || defined(FULL_BUF_TRACKING)
+ if (ccb->csio.bio != NULL)
+ biotrack(ccb->csio.bio, __func__);
+#endif
+
periph = xpt_path_periph(ccb->ccb_h.path);
softc = (struct da_softc *)periph->softc;