git: 70f2356d364f - main - cam: Make cam_debug macros atomic

From: Warner Losh <imp_at_FreeBSD.org>
Date: Fri, 03 Nov 2023 16:18:01 UTC
The branch main has been updated by imp:

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

commit 70f2356d364fdb7e2ff5487ae03125a338defd54
Author:     Warner Losh <imp@FreeBSD.org>
AuthorDate: 2023-11-02 20:41:09 +0000
Commit:     Warner Losh <imp@FreeBSD.org>
CommitDate: 2023-11-03 16:15:38 +0000

    cam: Make cam_debug macros atomic
    
    The CAM_DEBUG* macros use multiple printfs to dump the data. This is
    suboptimal when tracing things that produce even a moderate amount since
    it gets intertwingled. I can't even turn on tracing with a 24-disk HBA
    on boot without it getting messed up. Add helper routines to work around
    clang's over-use of the stack: that way we only pay the stack penalty
    when a trace hits.
    
    Sponsored by:           Netflix
    Reviewed by:            ken, mav
    Differential Revision:  https://reviews.freebsd.org/D42411
---
 sys/cam/cam_debug.h | 67 ++++++++++++++++++++---------------------------
 sys/cam/cam_xpt.c   | 75 ++++++++++++++++++++++++++++++++++++++++++++++-------
 sys/cam/cam_xpt.h   |  4 +--
 3 files changed, 95 insertions(+), 51 deletions(-)

diff --git a/sys/cam/cam_debug.h b/sys/cam/cam_debug.h
index 1526f11f4c0d..8c04b1fd7ce9 100644
--- a/sys/cam/cam_debug.h
+++ b/sys/cam/cam_debug.h
@@ -81,57 +81,46 @@ extern uint32_t cam_dflags;
 /* Printf delay value (to prevent scrolling) */
 extern uint32_t cam_debug_delay;
 
-/* Debugging macros. */
-#define	CAM_DEBUGGED(path, flag)			\
-	(((flag) & (CAM_DEBUG_COMPILE) & cam_dflags)	\
-	 && (cam_dpath != NULL)				\
-	 && (xpt_path_comp(cam_dpath, path) >= 0)	\
-	 && (xpt_path_comp(cam_dpath, path) < 2))
-
-#define	CAM_DEBUG(path, flag, printfargs)		\
-	if (((flag) & (CAM_DEBUG_COMPILE) & cam_dflags)	\
-	 && (cam_dpath != NULL)				\
-	 && (xpt_path_comp(cam_dpath, path) >= 0)	\
-	 && (xpt_path_comp(cam_dpath, path) < 2)) {	\
-		xpt_print_path(path);			\
-		printf printfargs;			\
-		if (cam_debug_delay != 0)		\
-			DELAY(cam_debug_delay);		\
-	}
+/* Helper routines -- helps conserve stack */
+struct cam_ed;
+void xpt_cam_path_debug(struct cam_path *path, const char *fmt, ...);
+void xpt_cam_dev_debug(struct cam_ed *dev, const char *fmt, ...);
+void xpt_cam_debug(const char *fmt, ...);
 
-#define	CAM_DEBUG_DEV(dev, flag, printfargs)		\
-	if (((flag) & (CAM_DEBUG_COMPILE) & cam_dflags)	\
-	 && (cam_dpath != NULL)				\
-	 && (xpt_path_comp_dev(cam_dpath, dev) >= 0)	\
-	 && (xpt_path_comp_dev(cam_dpath, dev) < 2)) {	\
-		xpt_print_device(dev);			\
-		printf printfargs;			\
-		if (cam_debug_delay != 0)		\
-			DELAY(cam_debug_delay);		\
+/* Stupid macro to remove a layer of parens */
+#define _CAM_X(...) __VA_ARGS__
+
+/* Debugging macros. */
+#define	CAM_DEBUGGED(path, flag)					\
+	(((flag) & (CAM_DEBUG_COMPILE) & cam_dflags)			\
+	 && (cam_dpath != NULL)						\
+	 && (xpt_path_comp(cam_dpath, (path)) >= 0)			\
+	 && (xpt_path_comp(cam_dpath, (path)) < 2))
+
+#define	CAM_DEBUG(path, flag, printfargs)				\
+	if (CAM_DEBUGGED(path, flag)) {					\
+		xpt_cam_path_debug(path, _CAM_X printfargs);		\
 	}
 
-#define	CAM_DEBUG_PRINT(flag, printfargs)		\
-	if (((flag) & (CAM_DEBUG_COMPILE) & cam_dflags)) {	\
-		printf("cam_debug: ");			\
-		printf printfargs;			\
-		if (cam_debug_delay != 0)		\
-			DELAY(cam_debug_delay);		\
+#define	CAM_DEBUG_DEV(dev, flag, printfargs)				\
+	if (((flag) & (CAM_DEBUG_COMPILE) & cam_dflags)			\
+	&& (cam_dpath != NULL)						\
+	&& (xpt_path_comp_dev(cam_dpath, (dev)) >= 0)			\
+	&& (xpt_path_comp_dev(cam_dpath, (dev)) < 2)) {			\
+		xpt_cam_dev_debug(dev, _CAM_X printfargs);		\
 	}
 
-#define	CAM_DEBUG_PATH_PRINT(flag, path, printfargs)	\
-	if (((flag) & (CAM_DEBUG_COMPILE) & cam_dflags)) {	\
-		xpt_print(path, "cam_debug: ");		\
-		printf printfargs;			\
-		if (cam_debug_delay != 0)		\
-			DELAY(cam_debug_delay);		\
+#define	CAM_DEBUG_PRINT(flag, printfargs)				\
+	if (((flag) & (CAM_DEBUG_COMPILE) & cam_dflags)) {		\
+		xpt_cam_debug(_CAM_X printfargs);			\
 	}
 
 #else /* !_KERNEL */
 
 #define	CAM_DEBUGGED(A, B)	0
 #define	CAM_DEBUG(A, B, C)
+#define	CAM_DEBUG_DEV(A, B, C)
 #define	CAM_DEBUG_PRINT(A, B)
-#define	CAM_DEBUG_PATH_PRINT(A, B, C)
 
 #endif /* _KERNEL */
 
diff --git a/sys/cam/cam_xpt.c b/sys/cam/cam_xpt.c
index c32cad2433b1..a1dec7a8a674 100644
--- a/sys/cam/cam_xpt.c
+++ b/sys/cam/cam_xpt.c
@@ -3712,18 +3712,18 @@ xpt_print_path(struct cam_path *path)
 	sbuf_delete(&sb);
 }
 
-void
-xpt_print_device(struct cam_ed *device)
+static void
+xpt_device_sbuf(struct cam_ed *device, struct sbuf *sb)
 {
-
 	if (device == NULL)
-		printf("(nopath): ");
+		sbuf_printf(sb, "(nopath): ");
 	else {
-		printf("(noperiph:%s%d:%d:%d:%jx): ", device->sim->sim_name,
-		       device->sim->unit_number,
-		       device->sim->bus_id,
-		       device->target->target_id,
-		       (uintmax_t)device->lun_id);
+		sbuf_printf(sb, "(noperiph:%s%d:%d:%d:%jx): ",
+		    device->sim->sim_name,
+		    device->sim->unit_number,
+		    device->sim->bus_id,
+		    device->target->target_id,
+		    (uintmax_t)device->lun_id);
 	}
 }
 
@@ -5543,3 +5543,60 @@ xpt_action_name(uint32_t action)
 	snprintf(buffer, sizeof(buffer), "%#x", action);
 	return (buffer);
 }
+
+void
+xpt_cam_path_debug(struct cam_path *path, const char *fmt, ...)
+{
+	struct sbuf sbuf;
+	char buf[XPT_PRINT_LEN]; /* balance to not eat too much stack */
+	struct sbuf *sb = sbuf_new(&sbuf, buf, sizeof(buf), SBUF_FIXEDLEN);
+	va_list ap;
+
+	sbuf_set_drain(sb, sbuf_printf_drain, NULL);
+	xpt_path_sbuf(path, sb);
+	va_start(ap, fmt);
+	sbuf_vprintf(sb, fmt, ap);
+	va_end(ap);
+	sbuf_finish(sb);
+	sbuf_delete(sb);
+	if (cam_debug_delay != 0)
+		DELAY(cam_debug_delay);
+}
+
+void
+xpt_cam_dev_debug(struct cam_ed *dev, const char *fmt, ...)
+{
+	struct sbuf sbuf;
+	char buf[XPT_PRINT_LEN]; /* balance to not eat too much stack */
+	struct sbuf *sb = sbuf_new(&sbuf, buf, sizeof(buf), SBUF_FIXEDLEN);
+	va_list ap;
+
+	sbuf_set_drain(sb, sbuf_printf_drain, NULL);
+	xpt_device_sbuf(dev, sb);
+	va_start(ap, fmt);
+	sbuf_vprintf(sb, fmt, ap);
+	va_end(ap);
+	sbuf_finish(sb);
+	sbuf_delete(sb);
+	if (cam_debug_delay != 0)
+		DELAY(cam_debug_delay);
+}
+
+void
+xpt_cam_debug(const char *fmt, ...)
+{
+	struct sbuf sbuf;
+	char buf[XPT_PRINT_LEN]; /* balance to not eat too much stack */
+	struct sbuf *sb = sbuf_new(&sbuf, buf, sizeof(buf), SBUF_FIXEDLEN);
+	va_list ap;
+
+	sbuf_set_drain(sb, sbuf_printf_drain, NULL);
+	sbuf_printf(sb, "cam_debug: ");
+	va_start(ap, fmt);
+	sbuf_vprintf(sb, fmt, ap);
+	va_end(ap);
+	sbuf_finish(sb);
+	sbuf_delete(sb);
+	if (cam_debug_delay != 0)
+		DELAY(cam_debug_delay);
+}
diff --git a/sys/cam/cam_xpt.h b/sys/cam/cam_xpt.h
index 1276dd7b9b2e..3c8d385fe33b 100644
--- a/sys/cam/cam_xpt.h
+++ b/sys/cam/cam_xpt.h
@@ -33,16 +33,15 @@
 #define _CAM_CAM_XPT_H 1
 
 #ifdef _KERNEL
-#include <sys/cdefs.h>
 #include <cam/cam_ccb.h>
 #endif
+#include <sys/sbuf.h>
 
 /* Forward Declarations */
 union ccb;
 struct cam_periph;
 struct cam_ed;
 struct cam_sim;
-struct sbuf;
 
 /*
  * Definition of a CAM path.  Paths are created from bus, target, and lun ids
@@ -113,7 +112,6 @@ struct cam_sim		*xpt_path_sim(struct cam_path *path);
 struct cam_periph	*xpt_path_periph(struct cam_path *path);
 device_t		xpt_path_sim_device(const struct cam_path *path);
 void			xpt_print_path(struct cam_path *path);
-void			xpt_print_device(struct cam_ed *device);
 void			xpt_print(struct cam_path *path, const char *fmt, ...);
 void			xpt_async(uint32_t async_code, struct cam_path *path,
 				  void *async_arg);