Skip to content
Permalink
Browse files
dyndbg: issue trace-events from pr_debug, dev_dbg
ddebug_trace() currently issues a single printk:console event.
Upgrade it to issue either of 2 new events:

- dyndbg:prdbg  - from trace_prdbg()  - if !dev
- dyndbg:devdbg - from trace_devdbg() - if !!dev

This links the legacy pr_debug API to tracefs, via dyndbg, allowing
pr_debug()s etc to add just a little more user-context to the
trace-logs, and then at users option, less syslog.

The 2 new trace_*() calls accept their caller's args respectively,
keeping the available info w/o alteration; ISTM this is the best basis
to support filtering.  The args:

 1- struct _ddebug *descriptor, giving tracefs all of dyndbg's info.
 2- struct device *dev, used by trace_devdbg(), if !!dev

To pass the descriptor into the trace_*() calls, the callchains from
__dynamic_{pr_debug,{dev,netdev,ibdev}_dbg} are altered to provide it.
The existing category param in this callchain is partially redundant,
as it is also in the descriptor; it may be possible to remove later.

dev_dbg(desc, dev...), if dev is true, issues a trace_devdbg(),
otherwise trace_prdbg().  This way we dont consume buffer space
storing nulls.

Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
  • Loading branch information
jimc committed Feb 12, 2022
1 parent 55bd43f commit 8931711b03d17ea34bc44b6fa6c8b6296266b951
Show file tree
Hide file tree
Showing 2 changed files with 110 additions and 32 deletions.
@@ -0,0 +1,74 @@
/* SPDX-License-Identifier: GPL-2.0 */
#undef TRACE_SYSTEM
#define TRACE_SYSTEM dyndbg

#if !defined(_TRACE_DYNDBG_H) || defined(TRACE_HEADER_MULTI_READ)
#define _TRACE_DYNDBG_H

#include <linux/tracepoint.h>

/* capture pr_debug() callsite descriptor and message */
TRACE_EVENT(prdbg,
TP_PROTO(const struct _ddebug *desc, const char *text, size_t len),

TP_ARGS(desc, text, len),

TP_STRUCT__entry(
__field(const struct _ddebug *, desc)
__dynamic_array(char, msg, len + 1)
),

TP_fast_assign(
__entry->desc = desc;
/*
* Each trace entry is printed in a new line.
* If the msg finishes with '\n', cut it off
* to avoid blank lines in the trace.
*/
if (len > 0 && (text[len - 1] == '\n'))
len -= 1;

memcpy(__get_str(msg), text, len);
__get_str(msg)[len] = 0;
),

TP_printk("%s.%s %s", __entry->desc->modname,
__entry->desc->function, __get_str(msg))
);

/* capture dev_dbg() callsite descriptor, device, and message */
TRACE_EVENT(devdbg,
TP_PROTO(const struct _ddebug *desc, const struct device *dev,
const char *text, size_t len),

TP_ARGS(desc, dev, text, len),

TP_STRUCT__entry(
__field(const struct _ddebug *, desc)
__field(const struct device *, dev)
__dynamic_array(char, msg, len + 1)
),

TP_fast_assign(
__entry->desc = desc;
__entry->dev = (struct device *) dev;
/*
* Each trace entry is printed in a new line.
* If the msg finishes with '\n', cut it off
* to avoid blank lines in the trace.
*/
if (len > 0 && (text[len - 1] == '\n'))
len -= 1;

memcpy(__get_str(msg), text, len);
__get_str(msg)[len] = 0;
),

TP_printk("%s.%s %s", __entry->desc->modname,
__entry->desc->function, __get_str(msg))
);

#endif /* _TRACE_DYNDBG_H */

/* This part must be outside protection */
#include <trace/define_trace.h>
@@ -36,7 +36,9 @@
#include <linux/sched.h>
#include <linux/device.h>
#include <linux/netdevice.h>
#include <trace/events/printk.h>

#define CREATE_TRACE_POINTS
#include <trace/events/dyndbg.h>

#include <rdma/ib_verbs.h>

@@ -733,7 +735,8 @@ struct ddebug_trace_bufs {
static DEFINE_PER_CPU(struct ddebug_trace_bufs, ddebug_trace_bufs);
static DEFINE_PER_CPU(int, ddebug_trace_reserve);

static void ddebug_trace(const char *fmt, va_list args)
static void ddebug_trace(struct _ddebug *desc, const struct device *dev,
const char *fmt, va_list args)
{
struct ddebug_trace_buf *buf;
int bufidx;
@@ -752,7 +755,11 @@ static void ddebug_trace(const char *fmt, va_list args)
buf = this_cpu_ptr(ddebug_trace_bufs.bufs) + bufidx;

len = vscnprintf(buf->buf, sizeof(buf->buf), fmt, args);
trace_console(buf->buf, len);

if (dev == NULL)
trace_prdbg(desc, buf->buf, len);
else
trace_devdbg(desc, dev, buf->buf, len);

out:
/* As above. */
@@ -762,21 +769,21 @@ static void ddebug_trace(const char *fmt, va_list args)
}

__printf(2, 3)
static void ddebug_printk(unsigned int flags, const char *fmt, ...)
static void ddebug_printk(struct _ddebug *desc, const char *fmt, ...)
{
if (flags & _DPRINTK_FLAGS_TRACE) {
if (desc->flags & _DPRINTK_FLAGS_TRACE) {
va_list args;

va_start(args, fmt);
/*
* All callers include the KERN_DEBUG prefix to keep the
* vprintk case simple; strip it out for tracing.
*/
ddebug_trace(fmt + strlen(KERN_DEBUG), args);
ddebug_trace(desc, NULL, fmt + strlen(KERN_DEBUG), args);
va_end(args);
}

if (flags & _DPRINTK_FLAGS_PRINTK) {
if (desc->flags & _DPRINTK_FLAGS_PRINTK) {
va_list args;

va_start(args, fmt);
@@ -786,19 +793,19 @@ static void ddebug_printk(unsigned int flags, const char *fmt, ...)
}

__printf(3, 4)
static void ddebug_dev_printk(unsigned int flags, const struct device *dev,
static void ddebug_dev_printk(struct _ddebug *desc, const struct device *dev,
const char *fmt, ...)
{

if (flags & _DPRINTK_FLAGS_TRACE) {
if (desc->flags & _DPRINTK_FLAGS_TRACE) {
va_list args;

va_start(args, fmt);
ddebug_trace(fmt, args);
ddebug_trace(desc, dev, fmt, args);
va_end(args);
}

if (flags & _DPRINTK_FLAGS_PRINTK) {
if (desc->flags & _DPRINTK_FLAGS_PRINTK) {
va_list args;

va_start(args, fmt);
@@ -821,7 +828,7 @@ void __dynamic_pr_debug(struct _ddebug *descriptor, const char *fmt, ...)
vaf.fmt = fmt;
vaf.va = &args;

ddebug_printk(descriptor->flags, KERN_DEBUG "%s%pV",
ddebug_printk(descriptor, KERN_DEBUG "%s%pV",
dynamic_emit_prefix(descriptor, buf), &vaf);

va_end(args);
@@ -832,7 +839,6 @@ void __dynamic_dev_dbg(struct _ddebug *descriptor,
const struct device *dev, const char *fmt, ...)
{
struct va_format vaf;
unsigned int flags;
va_list args;

BUG_ON(!descriptor);
@@ -842,15 +848,14 @@ void __dynamic_dev_dbg(struct _ddebug *descriptor,

vaf.fmt = fmt;
vaf.va = &args;
flags = descriptor->flags;

if (!dev) {
ddebug_printk(flags, KERN_DEBUG "(NULL device *): %pV",
&vaf);
ddebug_printk(descriptor, KERN_DEBUG "(NULL device *): %pV",
&vaf);
} else {
char buf[PREFIX_SIZE] = "";

ddebug_dev_printk(flags, dev, "%s%s %s: %pV",
ddebug_dev_printk(descriptor, dev, "%s%s %s: %pV",
dynamic_emit_prefix(descriptor, buf),
dev_driver_string(dev), dev_name(dev),
&vaf);
@@ -881,19 +886,18 @@ void __dynamic_netdev_dbg(struct _ddebug *descriptor,
if (dev && dev->dev.parent) {
char buf[PREFIX_SIZE] = "";

ddebug_dev_printk(flags, dev->dev.parent,
"%s%s %s %s%s: %pV",
dynamic_emit_prefix(descriptor, buf),
dev_driver_string(dev->dev.parent),
dev_name(dev->dev.parent),
netdev_name(dev), netdev_reg_state(dev),
&vaf);
ddebug_dev_printk(descriptor, dev->dev.parent,
"%s%s %s %s%s: %pV",
dynamic_emit_prefix(descriptor, buf),
dev_driver_string(dev->dev.parent),
dev_name(dev->dev.parent),
netdev_name(dev), netdev_reg_state(dev),
&vaf);
} else if (dev) {
ddebug_printk(flags, KERN_DEBUG "%s%s: %pV",
netdev_name(dev), netdev_reg_state(dev), &vaf);
ddebug_dev_printk(descriptor, &dev->dev, KERN_DEBUG "%s%s: %pV",
netdev_name(dev), netdev_reg_state(dev), &vaf);
} else {
ddebug_printk(flags, KERN_DEBUG "(NULL net_device): %pV",
&vaf);
ddebug_printk(descriptor, KERN_DEBUG "(NULL net_device): %pV", &vaf);
}

va_end(args);
@@ -920,18 +924,18 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
if (ibdev && ibdev->dev.parent) {
char buf[PREFIX_SIZE] = "";

ddebug_dev_printk(flags, ibdev->dev.parent,
ddebug_dev_printk(descriptor, ibdev->dev.parent,
"%s%s %s %s: %pV",
dynamic_emit_prefix(descriptor, buf),
dev_driver_string(ibdev->dev.parent),
dev_name(ibdev->dev.parent),
dev_name(&ibdev->dev),
&vaf);
} else if (ibdev) {
ddebug_printk(flags, KERN_DEBUG "%s: %pV",
dev_name(&ibdev->dev), &vaf);
ddebug_dev_printk(descriptor, &ibdev->dev, KERN_DEBUG "%s: %pV",
dev_name(&ibdev->dev), &vaf);
} else {
ddebug_printk(flags, KERN_DEBUG "(NULL ip_device): %pV", &vaf);
ddebug_printk(descriptor, KERN_DEBUG "(NULL ip_device): %pV", &vaf);
}

va_end(args);

0 comments on commit 8931711

Please sign in to comment.