2010-02-22 14:20:21

by Dave Young

[permalink] [raw]
Subject: [PATCH 05/06] kernel.h tracing stuff cleanup

trace stuff in kernel.h should stay in their own head file

cleanup trace declarations in kernel.h, put them into ring_buffer.h
include ring_buffer.h in every file which need it

Signed-off-by: Dave Young <[email protected]>
---
drivers/char/sysrq.c | 1
include/linux/ring_buffer.h | 137 ++++++++++++++++++++++++++++++++++++++++++
kernel/panic.c | 1
kernel/trace/trace_selftest.c | 1
4 files changed, 140 insertions(+)

--- linux-2.6.orig/include/linux/ring_buffer.h 2010-02-16 17:11:37.000000000 +0800
+++ linux-2.6/include/linux/ring_buffer.h 2010-02-16 17:41:33.000000000 +0800
@@ -1,6 +1,7 @@
#ifndef _LINUX_RING_BUFFER_H
#define _LINUX_RING_BUFFER_H

+#include <stdarg.h>
#include <linux/kmemcheck.h>
#include <linux/mm.h>
#include <linux/seq_file.h>
@@ -189,4 +190,140 @@ enum ring_buffer_flags {
RB_FL_OVERWRITE = 1 << 0,
};

+/*
+ * General tracing related utility functions - trace_printk(),
+ * tracing_on/tracing_off and tracing_start()/tracing_stop
+ *
+ * Use tracing_on/tracing_off when you want to quickly turn on or off
+ * tracing. It simply enables or disables the recording of the trace events.
+ * This also corresponds to the user space /sys/kernel/debug/tracing/tracing_on
+ * file, which gives a means for the kernel and userspace to interact.
+ * Place a tracing_off() in the kernel where you want tracing to end.
+ * From user space, examine the trace, and then echo 1 > tracing_on
+ * to continue tracing.
+ *
+ * tracing_stop/tracing_start has slightly more overhead. It is used
+ * by things like suspend to ram where disabling the recording of the
+ * trace is not enough, but tracing must actually stop because things
+ * like calling smp_processor_id() may crash the system.
+ *
+ * Most likely, you want to use tracing_on/tracing_off.
+ */
+#ifdef CONFIG_RING_BUFFER
+void tracing_on(void);
+void tracing_off(void);
+/* trace_off_permanent stops recording with no way to bring it back */
+void tracing_off_permanent(void);
+int tracing_is_on(void);
+#else
+static inline void tracing_on(void) { }
+static inline void tracing_off(void) { }
+static inline void tracing_off_permanent(void) { }
+static inline int tracing_is_on(void) { return 0; }
+#endif
+#ifdef CONFIG_TRACING
+extern void tracing_start(void);
+extern void tracing_stop(void);
+extern void ftrace_off_permanent(void);
+
+extern void
+ftrace_special(unsigned long arg1, unsigned long arg2, unsigned long arg3);
+
+static inline void __attribute__ ((format (printf, 1, 2)))
+____trace_printk_check_format(const char *fmt, ...)
+{
+}
+#define __trace_printk_check_format(fmt, args...) \
+do { \
+ if (0) \
+ ____trace_printk_check_format(fmt, ##args); \
+} while (0)
+
+/**
+ * trace_printk - printf formatting in the ftrace buffer
+ * @fmt: the printf format for printing
+ *
+ * Note: __trace_printk is an internal function for trace_printk and
+ * the @ip is passed in via the trace_printk macro.
+ *
+ * This function allows a kernel developer to debug fast path sections
+ * that printk is not appropriate for. By scattering in various
+ * printk like tracing in the code, a developer can quickly see
+ * where problems are occurring.
+ *
+ * This is intended as a debugging tool for the developer only.
+ * Please refrain from leaving trace_printks scattered around in
+ * your code.
+ */
+
+#define trace_printk(fmt, args...) \
+do { \
+ __trace_printk_check_format(fmt, ##args); \
+ if (__builtin_constant_p(fmt)) { \
+ static const char *trace_printk_fmt \
+ __attribute__((section("__trace_printk_fmt"))) = \
+ __builtin_constant_p(fmt) ? fmt : NULL; \
+ \
+ __trace_bprintk(_THIS_IP_, trace_printk_fmt, ##args); \
+ } else \
+ __trace_printk(_THIS_IP_, fmt, ##args); \
+} while (0)
+
+extern int
+__trace_bprintk(unsigned long ip, const char *fmt, ...)
+ __attribute__ ((format (printf, 2, 3)));
+
+extern int
+__trace_printk(unsigned long ip, const char *fmt, ...)
+ __attribute__ ((format (printf, 2, 3)));
+
+extern void trace_dump_stack(void);
+
+/*
+ * The double __builtin_constant_p is because gcc will give us an error
+ * if we try to allocate the static variable to fmt if it is not a
+ * constant. Even with the outer if statement.
+ */
+#define ftrace_vprintk(fmt, vargs) \
+do { \
+ if (__builtin_constant_p(fmt)) { \
+ static const char *trace_printk_fmt \
+ __attribute__((section("__trace_printk_fmt"))) = \
+ __builtin_constant_p(fmt) ? fmt : NULL; \
+ \
+ __ftrace_vbprintk(_THIS_IP_, trace_printk_fmt, vargs); \
+ } else \
+ __ftrace_vprintk(_THIS_IP_, fmt, vargs); \
+} while (0)
+
+extern int
+__ftrace_vbprintk(unsigned long ip, const char *fmt, va_list ap);
+
+extern int
+__ftrace_vprintk(unsigned long ip, const char *fmt, va_list ap);
+
+extern void ftrace_dump(void);
+#else
+static inline void
+ftrace_special(unsigned long arg1, unsigned long arg2, unsigned long arg3) { }
+static inline int
+trace_printk(const char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
+
+static inline void tracing_start(void) { }
+static inline void tracing_stop(void) { }
+static inline void ftrace_off_permanent(void) { }
+static inline void trace_dump_stack(void) { }
+static inline int
+trace_printk(const char *fmt, ...)
+{
+ return 0;
+}
+static inline int
+ftrace_vprintk(const char *fmt, va_list ap)
+{
+ return 0;
+}
+static inline void ftrace_dump(void) { }
+#endif /* CONFIG_TRACING */
+
#endif /* _LINUX_RING_BUFFER_H */
--- linux-2.6.orig/kernel/panic.c 2010-02-16 17:11:37.000000000 +0800
+++ linux-2.6/kernel/panic.c 2010-02-16 17:41:33.000000000 +0800
@@ -23,6 +23,7 @@
#include <linux/init.h>
#include <linux/nmi.h>
#include <linux/dmi.h>
+#include <linux/ring_buffer.h>

int panic_on_oops;
static unsigned long tainted_mask;
--- linux-2.6.orig/kernel/trace/trace_selftest.c 2010-02-16 17:11:37.000000000 +0800
+++ linux-2.6/kernel/trace/trace_selftest.c 2010-02-16 17:41:33.000000000 +0800
@@ -1,5 +1,6 @@
/* Include in trace.c */

+#include <linux/ring_buffer.h>
#include <linux/stringify.h>
#include <linux/kthread.h>
#include <linux/delay.h>
--- linux-2.6.orig/drivers/char/sysrq.c 2010-02-16 17:11:37.000000000 +0800
+++ linux-2.6/drivers/char/sysrq.c 2010-02-16 17:41:33.000000000 +0800
@@ -38,6 +38,7 @@
#include <linux/workqueue.h>
#include <linux/hrtimer.h>
#include <linux/oom.h>
+#include <linux/ring_buffer.h>

#include <asm/ptrace.h>
#include <asm/irq_regs.h>


2010-02-22 14:36:13

by Steven Rostedt

[permalink] [raw]
Subject: Re: [PATCH 05/06] kernel.h tracing stuff cleanup

On Mon, 2010-02-22 at 22:20 +0800, Dave Young wrote:
> trace stuff in kernel.h should stay in their own head file
>
> cleanup trace declarations in kernel.h, put them into ring_buffer.h
> include ring_buffer.h in every file which need it

NAK, sorry.

1) it does not belong in ring_buffer.h. The ring buffer.h is for the
ring buffer only, and is agnostic to other tracing code.

2) trace_prink() and friends needs to be with printk. It is not used
much in the delivered kernel but it is used often in development. That
is, we purposely made it so it is not needed to add a header file to
everyplace you use trace_prink(). When debugging a problem,
trace_printk() needs to be as convenient as adding printk(), and by
needing to find "what header includes trace_printk()" will become an
overwhelming inconvenience.

-- Steve


>
> Signed-off-by: Dave Young <[email protected]>