1. Add 3 user-flags [xyz] which work like original [pfmlt] flags, but have no effect on callsite behavior. This is literally just the added flags, behavior follows other flags. 2. Add [PFMLT],[XYZ] flags, which invert their counterparts; P===!p etc. And in ddebug_read_flags(): current code does: [pfmlt_xyz] -> flags reuse as [PFMLT_XYZ] -> mask also disallow both of a pair: ie no 'xX', no true & false. 3. Add filtering ops into ddebug_change(), right after all the callsite-property selections are complete. These test the callsite's current flagstate before applying modflags. Why ? The 3 new/user flags facilitate batching of changes. By marking individual callsites with 'xyz', user can compose an arbitrary set of changes, then activate them together by selecting on 'xyz': #> echo 'file foo.c +xyz; file bar.c +xyz' > control #> echo 'xyz+p' > control These user flags aren't strictly needed, but with them you can avoid using [fmlt] flags for marking, which would alter logging. Signed-off-by: Jim Cromie <jim.cromie@xxxxxxxxx> --- .../admin-guide/dynamic-debug-howto.rst | 28 +++++++++++++-- include/linux/dynamic_debug.h | 3 ++ lib/dynamic_debug.c | 34 ++++++++++++++----- 3 files changed, 55 insertions(+), 10 deletions(-) diff --git a/Documentation/admin-guide/dynamic-debug-howto.rst b/Documentation/admin-guide/dynamic-debug-howto.rst index cdc45dcb3e0c..5404e23eeac8 100644 --- a/Documentation/admin-guide/dynamic-debug-howto.rst +++ b/Documentation/admin-guide/dynamic-debug-howto.rst @@ -231,9 +231,33 @@ The flags are:: m Include module name in the printed message t Include thread ID in messages not generated from interrupt context _ No flags are set. (Or'd with others on input) + x user flag, to mark callsites into a group + y user flag, ... + z user flag, ... -For ``print_hex_dump_debug()`` and ``print_hex_dump_bytes()``, only ``p`` flag -have meaning, other flags ignored. +Additionally, the flags above have upper-case versions, which invert +their respective meanings. Their use follows. + +Using Filters:: + +Filter-flags specify an optional additional selector on pr_debug +callsites; with them you can compose an arbitrary set of callsites, by +iteratively marking them with ``+xyz``, then enabling them all with +``xyz+p``. + +Filters can also contain upper-case flags, like ``XY``, which select +only callsites with x&y cleared. + +Flagsets cannot contain ``xX`` etc, a flag cannot be true and false. + +modflags containing upper-case flags is reserved/undefined for now. +inverted-flags are currently ignored, usage gets trickier if given +``-pXy``, it should leave x set. + +Notes:: + +For ``print_hex_dump_debug()`` and ``print_hex_dump_bytes()``, only +``p`` flag has meaning, other flags are ignored. For display, the flags are preceded by ``=`` (mnemonic: what the flags are currently equal to). diff --git a/include/linux/dynamic_debug.h b/include/linux/dynamic_debug.h index a829c86364d4..0c099283bf1b 100644 --- a/include/linux/dynamic_debug.h +++ b/include/linux/dynamic_debug.h @@ -32,6 +32,9 @@ struct _ddebug { #define _DPRINTK_FLAGS_INCL_FUNCNAME (1<<2) #define _DPRINTK_FLAGS_INCL_LINENO (1<<3) #define _DPRINTK_FLAGS_INCL_TID (1<<4) +#define _DPRINTK_FLAGS_USR_X (1<<5) +#define _DPRINTK_FLAGS_USR_Y (1<<6) +#define _DPRINTK_FLAGS_USR_Z (1<<7) #if defined DEBUG #define _DPRINTK_FLAGS_DEFAULT _DPRINTK_FLAGS_PRINT #else diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c index 4369afeb52f0..f1ff7e30753e 100644 --- a/lib/dynamic_debug.c +++ b/lib/dynamic_debug.c @@ -72,13 +72,16 @@ static LIST_HEAD(ddebug_tables); static int verbose; module_param(verbose, int, 0644); -static struct { unsigned flag:8; char opt_char; } opt_array[] = { - { _DPRINTK_FLAGS_PRINT, 'p' }, - { _DPRINTK_FLAGS_INCL_MODNAME, 'm' }, - { _DPRINTK_FLAGS_INCL_FUNCNAME, 'f' }, - { _DPRINTK_FLAGS_INCL_LINENO, 'l' }, - { _DPRINTK_FLAGS_INCL_TID, 't' }, - { _DPRINTK_FLAGS_NONE, '_' }, +static struct { unsigned flag:8; char opt_char, not_char; } opt_array[] = { + { _DPRINTK_FLAGS_PRINT, 'p', 'P' }, + { _DPRINTK_FLAGS_INCL_MODNAME, 'm', 'M' }, + { _DPRINTK_FLAGS_INCL_FUNCNAME, 'f', 'F' }, + { _DPRINTK_FLAGS_INCL_LINENO, 'l', 'L' }, + { _DPRINTK_FLAGS_INCL_TID, 't', 'T' }, + { _DPRINTK_FLAGS_NONE, '_', '_' }, + { _DPRINTK_FLAGS_USR_X, 'x', 'X' }, + { _DPRINTK_FLAGS_USR_Y, 'y', 'Y' }, + { _DPRINTK_FLAGS_USR_Z, 'z', 'Z' }, }; /* format a string into buf[] which describes the _ddebug's flags */ @@ -180,6 +183,13 @@ static int ddebug_change(const struct ddebug_query *query, dp->lineno > query->last_lineno) continue; + /* filter for required flags */ + if ((dp->flags & filter->flags) != filter->flags) + continue; + /* filter on prohibited bits */ + if ((~dp->flags & filter->mask) != filter->mask) + continue; + nfound++; newflags = (dp->flags & mods->mask) | mods->flags; @@ -414,9 +424,17 @@ static int ddebug_read_flags(const char *str, struct flagsettings *f) f->flags |= opt_array[i].flag; break; } + else if (*str == opt_array[i].not_char) { + f->mask |= opt_array[i].flag; + break; + } } if (i < 0) { - pr_err("unknown flag '%c' in \"%s\"\n", *str, str); + pr_err("unknown flag '%c'", *str); + return -EINVAL; + } + if (f->flags & f->mask) { + pr_err("flag '%c' conflicts with earlier one\n", *str); return -EINVAL; } } -- 2.21.0