git: a67354f213f8 - main - cam: Refactor cam_periph_devctl_notify init/fini bits

From: Warner Losh <imp_at_FreeBSD.org>
Date: Fri, 11 Sep 2026 05:32:38 UTC
The branch main has been updated by imp:

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

commit a67354f213f83327cc4357db02985985c9c8db27
Author:     Warner Losh <wlosh@netflix.com>
AuthorDate: 2026-09-11 05:13:02 +0000
Commit:     Warner Losh <imp@FreeBSD.org>
CommitDate: 2026-09-11 05:13:02 +0000

    cam: Refactor cam_periph_devctl_notify init/fini bits
    
    To be able to create other kinds of devctl notifications that don't flow
    through cam_periph_devctl_notify, refactor out the header / trailers we
    do and the sbuf life cycle management. No functional change.
    
    Sponsored by:           Netflix
    Differential Revision:  https://reviews.freebsd.org/D58526
---
 sys/cam/cam_periph.c | 68 +++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 51 insertions(+), 17 deletions(-)

diff --git a/sys/cam/cam_periph.c b/sys/cam/cam_periph.c
index 6fa5fa4a60d6..e34971a8e4ff 100644
--- a/sys/cam/cam_periph.c
+++ b/sys/cam/cam_periph.c
@@ -91,6 +91,10 @@ static	int		camperiphscsisenseerror(union ccb *ccb,
 					        uint32_t *action,
 					        const char **action_string);
 static void		cam_periph_devctl_notify(union ccb *ccb);
+static char		*cam_periph_devctl_sb_init(struct sbuf *sb,
+			    struct cam_periph *periph);
+static void		cam_periph_devctl_sb_fini(struct sbuf *sb, char *sbmsg,
+			    const char *type);
 
 static int nperiph_drivers;
 static int initialized = 0;
@@ -2110,32 +2114,65 @@ cam_periph_error(union ccb *ccb, cam_flags camflags,
 
 #define CAM_PERIPH_DEVD_MSG_SIZE	1024
 
-static void
-cam_periph_devctl_notify(union ccb *ccb)
+/*
+ * Allocate and initialize an sbuf for a devctl notification, populating it
+ * with the device name and serial number.  Returns the malloc'd backing
+ * buffer, or NULL on allocation failure.  On success, the caller can append
+ * additional fields to sb before calling cam_periph_devctl_sb_fini().
+ */
+static char *
+cam_periph_devctl_sb_init(struct sbuf *sb, struct cam_periph *periph)
 {
-	struct cam_periph *periph;
 	struct ccb_getdev *cgd;
-	struct sbuf sb;
-	char *sbmsg, *type;
+	char *sbmsg;
 
 	sbmsg = malloc(CAM_PERIPH_DEVD_MSG_SIZE, M_CAMPERIPH, M_NOWAIT);
 	if (sbmsg == NULL)
-		return;
+		return (NULL);
 
-	sbuf_new(&sb, sbmsg, CAM_PERIPH_DEVD_MSG_SIZE, SBUF_FIXEDLEN);
+	sbuf_new(sb, sbmsg, CAM_PERIPH_DEVD_MSG_SIZE, SBUF_FIXEDLEN);
 
-	periph = xpt_path_periph(ccb->ccb_h.path);
-	sbuf_printf(&sb, "device=%s%d ", periph->periph_name,
+	sbuf_printf(sb, "device=%s%d ", periph->periph_name,
 	    periph->unit_number);
 
-	sbuf_cat(&sb, "serial=\"");
+	sbuf_cat(sb, "serial=\"");
 	if ((cgd = (struct ccb_getdev *)xpt_alloc_ccb_nowait()) != NULL) {
-		xpt_gdev_type(cgd, ccb->ccb_h.path);
+		xpt_gdev_type(cgd, periph->path);
 		if (cgd->ccb_h.status == CAM_REQ_CMP)
-			sbuf_bcat(&sb, cgd->serial_num, cgd->serial_num_len);
+			sbuf_bcat(sb, cgd->serial_num, cgd->serial_num_len);
 		xpt_free_ccb((union ccb *)cgd);
 	}
-	sbuf_cat(&sb, "\" ");
+	sbuf_cat(sb, "\" ");
+
+	return (sbmsg);
+}
+
+/*
+ * Finish and send a devctl notification, then clean up the sbuf and its
+ * backing buffer.
+ */
+static void
+cam_periph_devctl_sb_fini(struct sbuf *sb, char *sbmsg, const char *type)
+{
+
+	if (sbuf_finish(sb) == 0)
+		devctl_notify("CAM", "periph", type, sbuf_data(sb));
+	sbuf_delete(sb);
+	free(sbmsg, M_CAMPERIPH);
+}
+
+static void
+cam_periph_devctl_notify(union ccb *ccb)
+{
+	struct cam_periph *periph;
+	struct sbuf sb;
+	char *sbmsg, *type;
+
+	periph = xpt_path_periph(ccb->ccb_h.path);
+	sbmsg = cam_periph_devctl_sb_init(&sb, periph);
+	if (sbmsg == NULL)
+		return;
+
 	sbuf_printf(&sb, "cam_status=\"0x%x\" ", ccb->ccb_h.status);
 
 	switch (ccb->ccb_h.status & CAM_STATUS_MASK) {
@@ -2199,10 +2236,7 @@ cam_periph_devctl_notify(union ccb *ccb)
 		break;
 	}
 
-	if (sbuf_finish(&sb) == 0)
-		devctl_notify("CAM", "periph", type, sbuf_data(&sb));
-	sbuf_delete(&sb);
-	free(sbmsg, M_CAMPERIPH);
+	cam_periph_devctl_sb_fini(&sb, sbmsg, type);
 }
 
 /*