git: 1a7151f79664 - main - cam: Add probes for xpt actions

From: Warner Losh <imp_at_FreeBSD.org>
Date: Thu, 08 Jan 2026 06:24:35 UTC
The branch main has been updated by imp:

URL: https://cgit.FreeBSD.org/src/commit/?id=1a7151f79664644b2e7c8e69427be8b846e9c1a4

commit 1a7151f79664644b2e7c8e69427be8b846e9c1a4
Author:     Warner Losh <imp@FreeBSD.org>
AuthorDate: 2026-01-08 06:19:10 +0000
Commit:     Warner Losh <imp@FreeBSD.org>
CommitDate: 2026-01-08 06:19:10 +0000

    cam: Add probes for xpt actions
    
    cam::xpt:action(union ccb *)
    cam::xpt:done((union ccb *)
    cam::xpt:async-cb(void *cbarg, uint32_t async_code, struct cam_path
            *path, void *async_arg);
    
    Called when xpt_action(), xpt_done*() and the xpt async callbacks are
    called.
    
    Sponsored by:           Netflix
    Reviewed by:            adrian
    Differential Revision:  https://reviews.freebsd.org/D54469
---
 share/man/man4/Makefile     |  1 +
 share/man/man4/dtrace_cam.4 | 42 ++++++++++++++++++++++++++++++++++++++++++
 sys/cam/cam_xpt.c           | 22 +++++++++++++++++++++-
 3 files changed, 64 insertions(+), 1 deletion(-)

diff --git a/share/man/man4/Makefile b/share/man/man4/Makefile
index 5ee6eedd89ee..23bb8495975b 100644
--- a/share/man/man4/Makefile
+++ b/share/man/man4/Makefile
@@ -1009,6 +1009,7 @@ _ccd.4=		ccd.4
 .if ${MK_CDDL} != "no"
 _dtrace_provs=	dtrace_audit.4 \
 		dtrace_callout_execute.4 \
+		dtrace_cam.4 \
 		dtrace_dtrace.4 \
 		dtrace_fbt.4 \
 		dtrace_io.4 \
diff --git a/share/man/man4/dtrace_cam.4 b/share/man/man4/dtrace_cam.4
new file mode 100644
index 000000000000..e5b7ae34c391
--- /dev/null
+++ b/share/man/man4/dtrace_cam.4
@@ -0,0 +1,42 @@
+.\" Copyright (c) 2026 Netflix, Inc
+.\"
+.\" SPDX-License-Identifier: BSD-2-Clause
+.\"
+.Dd December 26, 2025
+.Dt DTRACE_CAM 4
+.Os
+.Sh NAME
+.Nm dtrace_cam
+.Nd a DTrace provider for tracing events related to CAM
+.Sh SYNOPSIS
+.Fn cam::xpt:action "union ccb *ccn"
+.Fn cam::xpt:done "union ccb *ccb"
+.Fn cam::xpt:async-cb "void *cbarg" "uint32_t async_code" "struct cam_path *path" "void *async_Arg"
+.Sh DESCRIPTION
+The
+.Nm cam
+provider allows the tracing of CAM events.
+The
+.Fn cam::xpt_action
+probe fires when a CAM Control Block (ccb) is submitted to a CAM SIM driver.
+The
+.Fn cam::xpt:done
+probe fires when that request completes.
+The
+.Fn cam::xpt:async-cb
+probe fires just before an async callback is called.
+.Sh ARGUMENTS
+.Sh FILES
+.Sh EXAMPLES
+.Sh SEE ALSO
+.Xr dtrace 1 ,
+.Xr SDT 9
+.Sh HISTORY
+The
+.Nm cam
+provider first appeared in
+.Fx
+15.1 and 16.0.
+.Sh AUTHORS
+This manual page was written by
+.An Warner Losh Aq Mt imp@FreeBSD.org .
diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
index ecf06045ed90..8b42fb2ca6c5 100644
--- a/sys/cam/cam_xpt.c
+++ b/sys/cam/cam_xpt.c
@@ -70,6 +70,12 @@
 #include <cam/scsi/scsi_pass.h>
 
 
+/* SDT Probes */
+SDT_PROBE_DEFINE1(cam, , xpt, action, "union ccb *");
+SDT_PROBE_DEFINE1(cam, , xpt, done, "union ccb *");
+SDT_PROBE_DEFINE4(cam, , xpt, async__cb, "void *", "uint32_t",
+    "struct cam_path *", "void *");
+
 /* Wild guess based on not wanting to grow the stack too much */
 #define XPT_PRINT_MAXLEN	512
 #ifdef PRINTF_BUFR_SIZE
@@ -2479,6 +2485,8 @@ xptsetasyncfunc(struct cam_ed *device, void *arg)
 			 device->target->target_id,
 			 device->lun_id);
 	xpt_gdev_type(&cgd, &path);
+	CAM_PROBE4(xpt, async__cb, csa->callback_arg,
+	    AC_FOUND_DEVICE, &path, &cgd);
 	csa->callback(csa->callback_arg,
 			    AC_FOUND_DEVICE,
 			    &path, &cgd);
@@ -2500,6 +2508,8 @@ xptsetasyncbusfunc(struct cam_eb *bus, void *arg)
 			 CAM_LUN_WILDCARD);
 	xpt_path_lock(&path);
 	xpt_path_inq(&cpi, &path);
+	CAM_PROBE4(xpt, async__cb, csa->callback_arg,
+	    AC_PATH_REGISTERED, &path, &cpi);
 	csa->callback(csa->callback_arg,
 			    AC_PATH_REGISTERED,
 			    &path, &cpi);
@@ -2526,6 +2536,7 @@ xpt_action(union ccb *start_ccb)
 	    start_ccb->ccb_h.pinfo.priority != CAM_PRIORITY_NONE,
 	    ("%s: queued ccb and CAM_PRIORITY_NONE illegal.", __func__));
 
+	CAM_PROBE1(xpt, action, start_ccb);
 	start_ccb->ccb_h.status = CAM_REQ_INPROG;
 	(*(start_ccb->ccb_h.path->bus->xport->ops->action))(start_ccb);
 }
@@ -4260,6 +4271,8 @@ xpt_async_bcast(struct async_list *async_head,
 			    path->device->sim->mtx : NULL;
 			if (mtx)
 				mtx_lock(mtx);
+			CAM_PROBE4(xpt, async__cb, cur_entry->callback_arg,
+			    async_code, path, async_arg);
 			cur_entry->callback(cur_entry->callback_arg,
 					    async_code, path,
 					    async_arg);
@@ -4499,8 +4512,10 @@ xpt_done(union ccb *done_ccb)
 		done_ccb->ccb_h.func_code,
 		xpt_action_name(done_ccb->ccb_h.func_code),
 		done_ccb->ccb_h.status));
-	if ((done_ccb->ccb_h.func_code & XPT_FC_QUEUED) == 0)
+	if ((done_ccb->ccb_h.func_code & XPT_FC_QUEUED) == 0) {
+		CAM_PROBE1(xpt, done, done_ccb);
 		return;
+	}
 
 	/* Store the time the ccb was in the sim */
 	done_ccb->ccb_h.qos.periph_data = cam_iosched_delta_t(done_ccb->ccb_h.qos.periph_data);
@@ -5376,6 +5391,11 @@ xpt_done_process(struct ccb_hdr *ccb_h)
 		}
 	}
 
+	/*
+	 * Call as late as possible. Do we want an early one too before the
+	 * unfreeze / releases above?
+	 */
+	CAM_PROBE1(xpt, done, (union ccb *)ccb_h);	/* container_of? */
 	/* Call the peripheral driver's callback */
 	ccb_h->pinfo.index = CAM_UNQUEUED_INDEX;
 	(*ccb_h->cbfcnp)(ccb_h->path->periph, (union ccb *)ccb_h);