aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWarner Losh <imp@FreeBSD.org>2026-01-08 06:20:34 +0000
committerWarner Losh <imp@FreeBSD.org>2026-01-08 06:20:34 +0000
commitcd1aa5f9917cc7de255e854954c818e5ef3e9c9b (patch)
tree3f6a9faeecd6cc5d3c9e975c5c9189da05298cb0
parentefb77950fdd6fb03dc172a44b3875948609b7804 (diff)
-rw-r--r--tools/cam/README9
-rw-r--r--tools/cam/cam_all_but_scsi.d89
2 files changed, 98 insertions, 0 deletions
diff --git a/tools/cam/README b/tools/cam/README
new file mode 100644
index 000000000000..fd93ccd15e1f
--- /dev/null
+++ b/tools/cam/README
@@ -0,0 +1,9 @@
+This directory has snippets of what will eventually become camio. This program
+can take an expression for the types of things to trace, and then custom write a
+dtrace script to do that.
+
+camio is a d-traced tcpdump-like program for examining CAM traffic (and
+therefore I/O and other traffic to storage media) that written during covid, but
+with fbp providers that recent clang optimizations make unuseable, hence the
+shift to the cam provider, but retooling them and finishing the grammar will
+take some time (but these scripts are useful today).
diff --git a/tools/cam/cam_all_but_scsi.d b/tools/cam/cam_all_but_scsi.d
new file mode 100644
index 000000000000..a20d7fa0cba9
--- /dev/null
+++ b/tools/cam/cam_all_but_scsi.d
@@ -0,0 +1,89 @@
+#!/usr/sbin/dtrace -s
+
+/* Sample use of the cam dtrace provider */
+
+/*
+ * Trace all the non I/O commands flowing through CAM
+ */
+
+dtrace:::BEGIN
+{
+}
+
+/*
+ * There's two choke points in CAM. We can intercept the request on the way down
+ * in xpt_action, just before it's sent to the SIM. This can be a good place to
+ * see what's going on before it happens. However, most I/O happens quite
+ * quickly, this isn't much of an advantage. The other place is on completion
+ * when the transaction is finally done. The retry mechanism is built into the
+ * periph driver, which is responsible for submitting the request.
+ *
+ * cam::xpt_action is a single logical point that handles both xpt_action and
+ * xpt_action_direct. Thie example hooks into it. The style is funky because
+ * D doesn't have looping or generalized if constructs.
+ *
+ * The 'trace' context local variable controls printing of different types
+ * of results. This is all controlled by camio.lua.
+ */
+
+
+/*
+ * CAM queues a CCB to the SIM in xpt_action. Save interesting bits
+ * for later winnowing.
+ */
+/* fbt::xpt_action_default:entry */
+cam::xpt:action
+{
+ this->ccb = ((union ccb *)arg0);
+ this->func = this->ccb->ccb_h.func_code & 0xff;
+ this->periph = this->ccb->ccb_h.path->periph;
+ this->bus = this->ccb->ccb_h.path->bus;
+ this->target = this->ccb->ccb_h.path->target;
+ this->device = this->ccb->ccb_h.path->device;
+ this->trace = 1;
+}
+
+/*
+ * Omit the I/O CCBs. Go ahead and pass the other semi I/O enclosure
+ * commands, though.
+ */
+cam::xpt:action
+/this->func == XPT_SCSI_IO || this->func == XPT_NVME_IO || this->func == XPT_NVME_ADMIN || this->func == XPT_ATA_IO/
+{
+ this->trace = 0;
+}
+
+/*
+ * Print out the non I/O and non ASYNC commands here.
+ */
+cam::xpt:action
+/this->trace && this->func != XPT_ASYNC/
+{
+ printf("(%s%d:%s%d:%d:%d:%d): %s",
+ this->periph == NULL ? "noperiph" : stringof(this->periph->periph_name),
+ this->periph == NULL ? 0 : this->periph->unit_number,
+ this->bus == NULL ? "nobus" : this->bus->sim->sim_name,
+ this->bus == NULL ? 0 : this->bus->sim->unit_number,
+ this->bus == NULL ? 0 : this->bus->sim->bus_id,
+ this->target == NULL ? 0 : this->target->target_id,
+ this->device == NULL ? 0 : this->device->lun_id,
+ xpt_action_string[this->func]);
+}
+
+/*
+ * For async calls, print out the async message type.
+ */
+cam::xpt:action
+/this->trace && this->func == XPT_ASYNC/
+{
+ printf("(%s%d:%s%d:%d:%d:%d): %s %s",
+ this->periph == NULL ? "noperiph" : stringof(this->periph->periph_name),
+ this->periph == NULL ? 0 : this->periph->unit_number,
+ this->bus == NULL ? "nobus" : this->bus->sim->sim_name,
+ this->bus == NULL ? 0 : this->bus->sim->unit_number,
+ this->bus == NULL ? 0 : this->bus->sim->bus_id,
+ this->target == NULL ? 0 : this->target->target_id,
+ this->device == NULL ? 0 : this->device->lun_id,
+ xpt_action_string[this->func],
+ xpt_async_string[this->ccb->casync.async_code]);
+}