[PATCH v3 2/7] dynamic_debug: Group debug messages by level bitmask

From: Stanimir Varbanov
Date: Tue Jun 09 2020 - 06:50:01 EST


This will allow dynamic debug users and driver writers to group
debug messages by level bitmask. The level bitmask should be a
hex number.

Done this functionality by extending dynamic debug metadata with
new level member and propagate it over all the users. Also
introduce new dynamic_pr_debug_level and dynamic_dev_dbg_level
macros to be used by the drivers.

Cc: Jason Baron <jbaron@xxxxxxxxxx>
Cc: Chris Mason <clm@xxxxxx>
Cc: Josef Bacik <josef@xxxxxxxxxxxxxx>
Cc: David Sterba <dsterba@xxxxxxxx>
Cc: "Rafael J. Wysocki" <rjw@xxxxxxxxxxxxx>
Cc: Len Brown <lenb@xxxxxxxxxx>
Cc: "David S. Miller" <davem@xxxxxxxxxxxxx>
Cc: Jakub Kicinski <kuba@xxxxxxxxxx>
Cc: Petr Mladek <pmladek@xxxxxxxx>
Cc: Sergey Senozhatsky <sergey.senozhatsky@xxxxxxxxx>
Cc: Steven Rostedt <rostedt@xxxxxxxxxxx>
Cc: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>

Suggested-by: Joe Perches <joe@xxxxxxxxxxx>
Signed-off-by: Stanimir Varbanov <stanimir.varbanov@xxxxxxxxxx>
---
fs/btrfs/ctree.h | 12 +++++---
include/linux/acpi.h | 3 +-
include/linux/dev_printk.h | 3 +-
include/linux/dynamic_debug.h | 55 ++++++++++++++++++++++++-----------
include/linux/net.h | 3 +-
include/linux/printk.h | 3 +-
lib/dynamic_debug.c | 30 +++++++++++++++++++
7 files changed, 84 insertions(+), 25 deletions(-)

diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 161533040978..f6a778789056 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -3081,16 +3081,20 @@ void btrfs_printk(const struct btrfs_fs_info *fs_info, const char *fmt, ...);

#if defined(CONFIG_DYNAMIC_DEBUG)
#define btrfs_debug(fs_info, fmt, args...) \
- _dynamic_func_call_no_desc(fmt, btrfs_printk, \
+ _dynamic_func_call_no_desc(fmt, _DPRINTK_LEVEL_DEFAULT, \
+ btrfs_printk, \
fs_info, KERN_DEBUG fmt, ##args)
#define btrfs_debug_in_rcu(fs_info, fmt, args...) \
- _dynamic_func_call_no_desc(fmt, btrfs_printk_in_rcu, \
+ _dynamic_func_call_no_desc(fmt, _DPRINTK_LEVEL_DEFAULT, \
+ btrfs_printk_in_rcu, \
fs_info, KERN_DEBUG fmt, ##args)
#define btrfs_debug_rl_in_rcu(fs_info, fmt, args...) \
- _dynamic_func_call_no_desc(fmt, btrfs_printk_rl_in_rcu, \
+ _dynamic_func_call_no_desc(fmt, _DPRINTK_LEVEL_DEFAULT, \
+ btrfs_printk_rl_in_rcu, \
fs_info, KERN_DEBUG fmt, ##args)
#define btrfs_debug_rl(fs_info, fmt, args...) \
- _dynamic_func_call_no_desc(fmt, btrfs_printk_ratelimited, \
+ _dynamic_func_call_no_desc(fmt, _DPRINTK_LEVEL_DEFAULT, \
+ btrfs_printk_ratelimited, \
fs_info, KERN_DEBUG fmt, ##args)
#elif defined(DEBUG)
#define btrfs_debug(fs_info, fmt, args...) \
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index d661cd0ee64d..6e51438f7635 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -1043,7 +1043,8 @@ void __acpi_handle_debug(struct _ddebug *descriptor, acpi_handle handle, const c
#else
#if defined(CONFIG_DYNAMIC_DEBUG)
#define acpi_handle_debug(handle, fmt, ...) \
- _dynamic_func_call(fmt, __acpi_handle_debug, \
+ _dynamic_func_call(fmt, _DPRINTK_LEVEL_DEFAULT, \
+ __acpi_handle_debug, \
handle, pr_fmt(fmt), ##__VA_ARGS__)
#else
#define acpi_handle_debug(handle, fmt, ...) \
diff --git a/include/linux/dev_printk.h b/include/linux/dev_printk.h
index 5aad06b4ca7b..7b50551833e1 100644
--- a/include/linux/dev_printk.h
+++ b/include/linux/dev_printk.h
@@ -188,7 +188,8 @@ do { \
static DEFINE_RATELIMIT_STATE(_rs, \
DEFAULT_RATELIMIT_INTERVAL, \
DEFAULT_RATELIMIT_BURST); \
- DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \
+ DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt, \
+ _DPRINTK_LEVEL_DEFAULT); \
if (DYNAMIC_DEBUG_BRANCH(descriptor) && \
__ratelimit(&_rs)) \
__dynamic_dev_dbg(&descriptor, dev, dev_fmt(fmt), \
diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h
index 4cf02ecd67de..95e97260c517 100644
--- a/include/linux/dynamic_debug.h
+++ b/include/linux/dynamic_debug.h
@@ -38,6 +38,8 @@ struct _ddebug {
#define _DPRINTK_FLAGS_DEFAULT 0
#endif
unsigned int flags:8;
+#define _DPRINTK_LEVEL_DEFAULT 0
+ unsigned int level:5;
#ifdef CONFIG_JUMP_LABEL
union {
struct static_key_true dd_key_true;
@@ -78,7 +80,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
const struct ib_device *ibdev,
const char *fmt, ...);

-#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt) \
+#define DEFINE_DYNAMIC_DEBUG_METADATA(name, fmt, lvl) \
static struct _ddebug __aligned(8) \
__attribute__((section("__verbose"))) name = { \
.modname = KBUILD_MODNAME, \
@@ -87,6 +89,7 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
.format = (fmt), \
.lineno = __LINE__, \
.flags = _DPRINTK_FLAGS_DEFAULT, \
+ .level = (lvl), \
_DPRINTK_KEY_INIT \
}

@@ -119,16 +122,16 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,

#endif

-#define __dynamic_func_call(id, fmt, func, ...) do { \
- DEFINE_DYNAMIC_DEBUG_METADATA(id, fmt); \
- if (DYNAMIC_DEBUG_BRANCH(id)) \
- func(&id, ##__VA_ARGS__); \
+#define __dynamic_func_call(id, fmt, level, func, ...) do { \
+ DEFINE_DYNAMIC_DEBUG_METADATA(id, fmt, level); \
+ if (DYNAMIC_DEBUG_BRANCH(id)) \
+ func(&id, ##__VA_ARGS__); \
} while (0)

-#define __dynamic_func_call_no_desc(id, fmt, func, ...) do { \
- DEFINE_DYNAMIC_DEBUG_METADATA(id, fmt); \
- if (DYNAMIC_DEBUG_BRANCH(id)) \
- func(__VA_ARGS__); \
+#define __dynamic_func_call_no_desc(id, fmt, level, func, ...) do { \
+ DEFINE_DYNAMIC_DEBUG_METADATA(id, fmt, level); \
+ if (DYNAMIC_DEBUG_BRANCH(id)) \
+ func(__VA_ARGS__); \
} while (0)

/*
@@ -139,35 +142,49 @@ void __dynamic_ibdev_dbg(struct _ddebug *descriptor,
* the varargs. Note that fmt is repeated in invocations of this
* macro.
*/
-#define _dynamic_func_call(fmt, func, ...) \
- __dynamic_func_call(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__)
+#define _dynamic_func_call(fmt, lvl, func, ...) \
+ __dynamic_func_call(__UNIQUE_ID(ddebug), fmt, lvl, func, ##__VA_ARGS__)
/*
* A variant that does the same, except that the descriptor is not
* passed as the first argument to the function; it is only called
* with precisely the macro's varargs.
*/
-#define _dynamic_func_call_no_desc(fmt, func, ...) \
- __dynamic_func_call_no_desc(__UNIQUE_ID(ddebug), fmt, func, ##__VA_ARGS__)
+#define _dynamic_func_call_no_desc(fmt, lvl, func, ...) \
+ __dynamic_func_call_no_desc(__UNIQUE_ID(ddebug), fmt, lvl, \
+ func, ##__VA_ARGS__)

#define dynamic_pr_debug(fmt, ...) \
- _dynamic_func_call(fmt, __dynamic_pr_debug, \
+ _dynamic_func_call(fmt, _DPRINTK_LEVEL_DEFAULT, \
+ __dynamic_pr_debug, \
+ pr_fmt(fmt), ##__VA_ARGS__)
+
+#define dynamic_pr_debug_level(lvl, fmt, ...) \
+ _dynamic_func_call(fmt, lvl, __dynamic_pr_debug, \
pr_fmt(fmt), ##__VA_ARGS__)

#define dynamic_dev_dbg(dev, fmt, ...) \
- _dynamic_func_call(fmt,__dynamic_dev_dbg, \
+ _dynamic_func_call(fmt, _DPRINTK_LEVEL_DEFAULT, \
+ __dynamic_dev_dbg, \
+ dev, fmt, ##__VA_ARGS__)
+
+#define dynamic_dev_dbg_level(dev, lvl, fmt, ...) \
+ _dynamic_func_call(fmt, lvl, __dynamic_dev_dbg, \
dev, fmt, ##__VA_ARGS__)

#define dynamic_netdev_dbg(dev, fmt, ...) \
- _dynamic_func_call(fmt, __dynamic_netdev_dbg, \
+ _dynamic_func_call(fmt, _DPRINTK_LEVEL_DEFAULT, \
+ __dynamic_netdev_dbg, \
dev, fmt, ##__VA_ARGS__)

#define dynamic_ibdev_dbg(dev, fmt, ...) \
- _dynamic_func_call(fmt, __dynamic_ibdev_dbg, \
+ _dynamic_func_call(fmt, _DPRINTK_LEVEL_DEFAULT, \
+ __dynamic_ibdev_dbg, \
dev, fmt, ##__VA_ARGS__)

#define dynamic_hex_dump(prefix_str, prefix_type, rowsize, \
groupsize, buf, len, ascii) \
_dynamic_func_call_no_desc(__builtin_constant_p(prefix_str) ? prefix_str : "hexdump", \
+ _DPRINTK_LEVEL_DEFAULT, \
print_hex_dump, \
KERN_DEBUG, prefix_str, prefix_type, \
rowsize, groupsize, buf, len, ascii)
@@ -202,8 +219,12 @@ static inline int ddebug_dyndbg_module_param_cb(char *param, char *val,

#define dynamic_pr_debug(fmt, ...) \
do { if (0) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); } while (0)
+#define dynamic_pr_debug_level(lvl, fmt, ...) \
+ do { if (0) printk(KERN_DEBUG pr_fmt(fmt), ##__VA_ARGS__); } while (0)
#define dynamic_dev_dbg(dev, fmt, ...) \
do { if (0) dev_printk(KERN_DEBUG, dev, fmt, ##__VA_ARGS__); } while (0)
+#define dynamic_dev_dbg_level(dev, lvl, fmt, ...) \
+ do { if (0) dev_printk(KERN_DEBUG, dev, fmt, ##__VA_ARGS__); } while (0)
#define dynamic_hex_dump(prefix_str, prefix_type, rowsize, \
groupsize, buf, len, ascii) \
do { if (0) \
diff --git a/include/linux/net.h b/include/linux/net.h
index e10f378194a5..bcf6f010bc67 100644
--- a/include/linux/net.h
+++ b/include/linux/net.h
@@ -267,7 +267,8 @@ do { \
#if defined(CONFIG_DYNAMIC_DEBUG)
#define net_dbg_ratelimited(fmt, ...) \
do { \
- DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt); \
+ DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, fmt, \
+ _DPRINTK_LEVEL_DEFAULT); \
if (DYNAMIC_DEBUG_BRANCH(descriptor) && \
net_ratelimit()) \
__dynamic_pr_debug(&descriptor, pr_fmt(fmt), \
diff --git a/include/linux/printk.h b/include/linux/printk.h
index 3cc2f178bf06..ceea84aa705b 100644
--- a/include/linux/printk.h
+++ b/include/linux/printk.h
@@ -542,7 +542,8 @@ do { \
static DEFINE_RATELIMIT_STATE(_rs, \
DEFAULT_RATELIMIT_INTERVAL, \
DEFAULT_RATELIMIT_BURST); \
- DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, pr_fmt(fmt)); \
+ DEFINE_DYNAMIC_DEBUG_METADATA(descriptor, pr_fmt(fmt), \
+ _DPRINTK_LEVEL_DEFAULT); \
if (DYNAMIC_DEBUG_BRANCH(descriptor) && \
__ratelimit(&_rs)) \
__dynamic_pr_debug(&descriptor, pr_fmt(fmt), ##__VA_ARGS__); \
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 8f199f403ab5..5d28d388f6dd 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -55,6 +55,7 @@ struct ddebug_query {
const char *function;
const char *format;
unsigned int first_lineno, last_lineno;
+ unsigned int level;
};

struct ddebug_iter {
@@ -187,6 +188,18 @@ static int ddebug_change(const struct ddebug_query *query,

nfound++;

+#ifdef CONFIG_JUMP_LABEL
+ if (query->level && query->level & dp->level) {
+ if (flags & _DPRINTK_FLAGS_PRINT)
+ static_branch_enable(&dp->key.dd_key_true);
+ else
+ static_branch_disable(&dp->key.dd_key_true);
+ } else if (query->level &&
+ flags & _DPRINTK_FLAGS_PRINT) {
+ static_branch_disable(&dp->key.dd_key_true);
+ continue;
+ }
+#endif
newflags = (dp->flags & mask) | flags;
if (newflags == dp->flags)
continue;
@@ -289,6 +302,20 @@ static inline int parse_lineno(const char *str, unsigned int *val)
return 0;
}

+static inline int parse_level(const char *str, unsigned int *val)
+{
+ WARN_ON(str == NULL);
+ if (*str == '\0') {
+ *val = 0;
+ return 0;
+ }
+ if (kstrtouint(str, 0, val) < 0) {
+ pr_err("bad level-number: %s\n", str);
+ return -EINVAL;
+ }
+ return 0;
+}
+
static int check_set(const char **dest, char *src, char *name)
{
int rc = 0;
@@ -375,6 +402,9 @@ static int ddebug_parse_query(char *words[], int nwords,
} else {
query->last_lineno = query->first_lineno;
}
+ } else if (!strcmp(words[i], "level")) {
+ if (parse_level(words[i+1], &query->level) < 0)
+ return -EINVAL;
} else {
pr_err("unknown keyword \"%s\"\n", words[i]);
return -EINVAL;
--
2.17.1