From: "Łukasz Bartosik" <lb@semihalf.com>
To: Jason Baron <jbaron@akamai.com>,
Jim Cromie <jim.cromie@gmail.com>,
Andrew Morton <akpm@linux-foundation.org>,
Kees Cook <keescook@chromium.org>,
Douglas Anderson <dianders@chromium.org>
Cc: Guenter Roeck <groeck@google.com>,
Yaniv Tzoreff <yanivt@google.com>,
Benson Leung <bleung@google.com>,
Steven Rostedt <rostedt@goodmis.org>,
Vincent Whitchurch <vincent.whitchurch@axis.com>,
Pekka Paalanen <ppaalanen@gmail.com>,
Sean Paul <seanpaul@chromium.org>,
Daniel Vetter <daniel@ffwll.ch>,
linux-kernel@vger.kernel.org, upstream@semihalf.com
Subject: [PATCH v2 12/15] dyndbg: add processing of T(race) flag argument
Date: Fri, 1 Dec 2023 00:40:45 +0100 [thread overview]
Message-ID: <20231130234048.157509-13-lb@semihalf.com> (raw)
In-Reply-To: <20231130234048.157509-1-lb@semihalf.com>
Add processing of argument provided to T(race) flag.
The string argument determines destination of debug logs:
"0" - debug logs will be written to prdbg and devdbg trace events
name - debug logs will be written to trace instance pointed by name,
trace instance name has to be previously opened with open
command
A user can provide trace destination name by following T flag with
":" and trace destination name, for example:
echo "module thunderbolt =pT:tbt" > <debugfs>/dynamic_debug/control
echo "module thunderbolt =lT:tbt,p" > <debugfs>/dynamic_debug/control
When T flag with argument is followed by other flag then the next
flag has to be preceded with ",".
Signed-off-by: Łukasz Bartosik <lb@semihalf.com>
---
lib/dynamic_debug.c | 169 ++++++++++++++++++++++++++++++++++----------
1 file changed, 132 insertions(+), 37 deletions(-)
diff --git a/lib/dynamic_debug.c b/lib/dynamic_debug.c
index 73b6818e5fab..dbedb1139d4b 100644
--- a/lib/dynamic_debug.c
+++ b/lib/dynamic_debug.c
@@ -72,6 +72,7 @@ struct ddebug_iter {
struct flag_settings {
unsigned int flags;
unsigned int mask;
+ unsigned int trace_dst;
};
#define DD_OPEN_CMD "open"
@@ -85,8 +86,16 @@ struct ddebug_trace_inst {
};
/*
- * TRACE_DST_MAX value is reserved for writing
- * debug logs to trace events (prdbg, devdbg)
+ * When trace is enabled (T flag is set) and trace destination field
+ * value is not a TRACE_DST_MAX (it is reserved for trace events)
+ * then debug logs will be written to trace instance whose name is
+ * stored in inst[trace destination].name, e.g. when trace destination
+ * value is 2 and inst[2].name is set to tbt then debug logs will be
+ * written to <debugfs>/tracing/instances/tbt
+ *
+ * Size of inst and bmap is TRACE_DST_MAX-1 because TRACE_DST_MAX value
+ * is reserved as a special value of trace destination which when set
+ * writes debug logs to trace events (prdbg, devdbg)
*/
struct ddebug_trace {
struct ddebug_trace_inst inst[TRACE_DST_MAX-1];
@@ -123,6 +132,72 @@ static inline unsigned int get_trace_dst(const struct _ddebug *desc)
return desc->ctrl.trace_dst;
}
+static int find_tr_instance(const char *name)
+{
+ int idx;
+
+ for_each_set_bit(idx, tr.bmap, tr.bmap_size)
+ if (!strcmp(tr.inst[idx].name, name))
+ return idx;
+
+ return -ENOENT;
+}
+
+static const
+char *read_T_args(const char *str, struct flag_settings *modifiers)
+{
+ int len, idx = TRACE_DST_MAX;
+ char *end;
+
+ if (*(str+1) != ':')
+ return str;
+
+ str += 2;
+ end = strchr(str, ',');
+ if (end && *(end + 1) == '\0')
+ return NULL;
+
+ if (end) {
+ len = end - str;
+ *end = '\0';
+ } else
+ len = strlen(str);
+
+ /* destination trace events */
+ if (!strcmp(str, DD_TR_EVENT))
+ goto end;
+
+ idx = find_tr_instance(str);
+ if (idx < 0)
+ return NULL;
+end:
+ modifiers->trace_dst = idx;
+ return end ? end : str + len;
+}
+
+/*
+ * Maximum number of characters which are being displayed when
+ * printing trace instance name, longer names are truncated
+ */
+#define FLAG_T_ARG_LEN 24
+
+char *show_T_args(struct dd_ctrl *ctrl, char *p)
+{
+ const char *str;
+ int n;
+
+ str = ctrl->trace_dst == TRACE_DST_MAX ?
+ DD_TR_EVENT : tr.inst[ctrl->trace_dst].name;
+
+ n = snprintf(p, FLAG_T_ARG_LEN, ":%s", str);
+ if (n >= FLAG_T_ARG_LEN) {
+ strscpy(&p[FLAG_T_ARG_LEN-4], "...", 4);
+ n = FLAG_T_ARG_LEN - 1;
+ }
+
+ return n < 0 ? p : p + n;
+}
+
/* Return the path relative to source root */
static inline const char *trim_prefix(const char *path)
{
@@ -134,9 +209,18 @@ static inline const char *trim_prefix(const char *path)
return path + skip;
}
-static const struct { unsigned flag:8; char opt_char; } opt_array[] = {
+typedef const char* (*read_flag_args_f)(const char *, struct flag_settings *);
+typedef char* (*show_flag_args_f)(struct dd_ctrl *, char *);
+
+static const struct
+{
+ unsigned flag:8;
+ char opt_char;
+ read_flag_args_f read_args;
+ show_flag_args_f show_args;
+} opt_array[] = {
{ _DPRINTK_FLAGS_PRINTK, 'p' },
- { _DPRINTK_FLAGS_TRACE, 'T' },
+ { _DPRINTK_FLAGS_TRACE, 'T', read_T_args, show_T_args},
{ _DPRINTK_FLAGS_INCL_MODNAME, 'm' },
{ _DPRINTK_FLAGS_INCL_FUNCNAME, 'f' },
{ _DPRINTK_FLAGS_INCL_SOURCENAME, 's' },
@@ -145,22 +229,30 @@ static const struct { unsigned flag:8; char opt_char; } opt_array[] = {
{ _DPRINTK_FLAGS_NONE, '_' },
};
-struct flagsbuf { char buf[ARRAY_SIZE(opt_array)+1]; };
+struct ctrlbuf { char buf[ARRAY_SIZE(opt_array)+FLAG_T_ARG_LEN+1]; };
/* format a string into buf[] which describes the _ddebug's flags */
-static char *ddebug_describe_flags(unsigned int flags, struct flagsbuf *fb)
+static char *ddebug_describe_ctrl(struct dd_ctrl *ctrl, struct ctrlbuf *cb)
{
- char *p = fb->buf;
+ show_flag_args_f show_args = NULL;
+ char *p = cb->buf;
int i;
for (i = 0; i < ARRAY_SIZE(opt_array); ++i)
- if (flags & opt_array[i].flag)
+ if (ctrl->flags & opt_array[i].flag) {
+ if (show_args)
+ *p++ = ',';
*p++ = opt_array[i].opt_char;
- if (p == fb->buf)
+ show_args = opt_array[i].show_args;
+ if (show_args)
+ p = show_args(ctrl, p);
+ }
+
+ if (p == cb->buf)
*p++ = '_';
*p = '\0';
- return fb->buf;
+ return cb->buf;
}
#define vnpr_info(lvl, fmt, ...) \
@@ -219,17 +311,6 @@ static bool validate_tr_name(const char *str)
return true;
}
-static int find_tr_instance(const char *name)
-{
- int idx;
-
- for_each_set_bit(idx, tr.bmap, tr.bmap_size)
- if (!strcmp(tr.inst[idx].name, name))
- return idx;
-
- return -ENOENT;
-}
-
static int handle_tr_opend_cmd(const char *arg)
{
struct ddebug_trace_inst *inst;
@@ -387,7 +468,7 @@ static struct ddebug_class_map *ddebug_find_valid_class(struct ddebug_table cons
* Search the tables for _ddebug's which match the given `query' and
* apply the `flags' and `mask' to them. Returns number of matching
* callsites, normally the same as number of changes. If verbose,
- * logs the changes. Takes ddebug_lock.
+ * logs the changes.
*/
static int ddebug_change(const struct ddebug_query *query,
struct flag_settings *modifiers)
@@ -395,13 +476,12 @@ static int ddebug_change(const struct ddebug_query *query,
int i;
struct ddebug_table *dt;
unsigned int nfound = 0;
+ struct ctrlbuf cbuf, nbuf;
struct dd_ctrl nctrl = {0};
- struct flagsbuf fbuf, nbuf;
struct ddebug_class_map *map = NULL;
int __outvar valid_class;
/* search for matching ddebugs */
- mutex_lock(&ddebug_lock);
list_for_each_entry(dt, &ddebug_tables, link) {
/* match against the module name */
@@ -462,7 +542,8 @@ static int ddebug_change(const struct ddebug_query *query,
nfound++;
nctrl.flags = (get_flags(dp) & modifiers->mask) | modifiers->flags;
- if (!memcmp(&nctrl, get_ctrl(dp), sizeof(struct dd_ctrl)))
+ nctrl.trace_dst = modifiers->trace_dst;
+ if (!memcmp(&nctrl, get_ctrl(dp), sizeof(nctrl)))
continue;
#ifdef CONFIG_JUMP_LABEL
if (get_flags(dp) & _DPRINTK_FLAGS_ENABLED) {
@@ -475,13 +556,12 @@ static int ddebug_change(const struct ddebug_query *query,
v4pr_info("changed %s:%d [%s]%s %s => %s\n",
trim_prefix(dp->filename), dp->lineno,
dt->mod_name, dp->function,
- ddebug_describe_flags(get_flags(dp), &fbuf),
- ddebug_describe_flags(nctrl.flags, &nbuf));
+ ddebug_describe_ctrl(&dp->ctrl, &cbuf),
+ ddebug_describe_ctrl(&nctrl, &nbuf));
update_tr_dst(dp, &nctrl);
set_ctrl(dp, &nctrl);
}
}
- mutex_unlock(&ddebug_lock);
if (!nfound && verbose)
pr_info("no matches for query\n");
@@ -702,6 +782,7 @@ static int ddebug_parse_query(char *words[], int nwords,
*/
static int ddebug_parse_flags(const char *str, struct flag_settings *modifiers)
{
+ read_flag_args_f read_args;
int op, i;
switch (*str) {
@@ -720,6 +801,12 @@ static int ddebug_parse_flags(const char *str, struct flag_settings *modifiers)
for (i = ARRAY_SIZE(opt_array) - 1; i >= 0; i--) {
if (*str == opt_array[i].opt_char) {
modifiers->flags |= opt_array[i].flag;
+ read_args = opt_array[i].read_args;
+ if (read_args) {
+ str = read_args(str, modifiers);
+ if (!str)
+ return -EINVAL;
+ }
break;
}
}
@@ -728,7 +815,7 @@ static int ddebug_parse_flags(const char *str, struct flag_settings *modifiers)
return -EINVAL;
}
}
- v3pr_info("flags=0x%x\n", modifiers->flags);
+ v3pr_info("flags=0x%x, trace dest=0x%x\n", modifiers->flags, modifiers->trace_dst);
/* calculate final flags, mask based upon op */
switch (op) {
@@ -767,20 +854,28 @@ static int ddebug_exec_query(char *query_string, const char *modname)
if (is_ddebug_cmd(words[0]))
return ddebug_parse_cmd(words, nwords-1);
- /* check flags 1st (last arg) so query is pairs of spec,val */
- if (ddebug_parse_flags(words[nwords-1], &modifiers)) {
- pr_err("flags parse failed\n");
- return -EINVAL;
- }
if (ddebug_parse_query(words, nwords-1, &query, modname)) {
pr_err("query parse failed\n");
return -EINVAL;
}
+
+ mutex_lock(&ddebug_lock);
+
+ /* check flags 1st (last arg) so query is pairs of spec,val */
+ if (ddebug_parse_flags(words[nwords-1], &modifiers)) {
+ pr_err("flags parse failed\n");
+ goto err;
+ }
+
/* actually go and implement the change */
nfound = ddebug_change(&query, &modifiers);
- vpr_info_dq(&query, nfound ? "applied" : "no-match");
+ mutex_unlock(&ddebug_lock);
+ vpr_info_dq(&query, nfound ? "applied" : "no-match");
return nfound;
+err:
+ mutex_unlock(&ddebug_lock);
+ return -EINVAL;
}
/* handle multiple queries in query string, continue on error, return
@@ -1470,7 +1565,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
{
struct ddebug_iter *iter = m->private;
struct _ddebug *dp = p;
- struct flagsbuf flags;
+ struct ctrlbuf cbuf;
char const *class;
if (p == SEQ_START_TOKEN) {
@@ -1482,7 +1577,7 @@ static int ddebug_proc_show(struct seq_file *m, void *p)
seq_printf(m, "%s:%u [%s]%s =%s \"",
trim_prefix(dp->filename), dp->lineno,
iter->table->mod_name, dp->function,
- ddebug_describe_flags(get_flags(dp), &flags));
+ ddebug_describe_ctrl(&dp->ctrl, &cbuf));
seq_escape_str(m, dp->format, ESCAPE_SPACE, "\t\r\n\"");
seq_puts(m, "\"");
--
2.43.0.rc2.451.g8631bc7472-goog
next prev parent reply other threads:[~2023-11-30 23:43 UTC|newest]
Thread overview: 55+ messages / expand[flat|nested] mbox.gz Atom feed top
2023-11-30 23:40 [PATCH v2 00/15] dyndbg: add support for writing debug logs to trace Łukasz Bartosik
2023-11-30 23:40 ` [PATCH v2 01/15] dyndbg: add _DPRINTK_FLAGS_ENABLED Łukasz Bartosik
2023-11-30 23:40 ` [PATCH v2 02/15] dyndbg: add _DPRINTK_FLAGS_TRACE Łukasz Bartosik
2023-11-30 23:40 ` [PATCH v2 03/15] dyndbg: add write events to tracefs code Łukasz Bartosik
2023-11-30 23:40 ` [PATCH v2 04/15] dyndbg: add 2 trace-events: prdbg, devdbg Łukasz Bartosik
2023-11-30 23:40 ` [PATCH v2 05/15] tracefs: add __get_str_strip_nl - RFC Łukasz Bartosik
2023-12-01 0:25 ` Steven Rostedt
2023-12-01 9:00 ` Łukasz Bartosik
2023-12-08 0:15 ` [re: PATCH v2 00/15 - 00/11] dyndbg: add support for writing debug logs to trace Jim Cromie
2023-12-08 0:15 ` [re: PATCH v2 00/15 - 01/11] dyndbg: export _print_hex_dump Jim Cromie
2023-12-08 0:15 ` [re: PATCH v2 00/15 - 02/11] dyndbg: tweak pr_info format s/trace dest/trace_dest/ Jim Cromie
2023-12-08 0:15 ` [re: PATCH v2 00/15 - 03/11] dyndbg: disambiguate quoting in a debug msg Jim Cromie
2023-12-18 16:34 ` Petr Mladek
2023-12-19 23:38 ` jim.cromie
2024-01-04 7:54 ` Petr Mladek
2024-01-05 0:06 ` jim.cromie
2023-12-08 0:15 ` [re: PATCH v2 00/15 - 04/11] dyndbg: fix old BUG_ON in >control parser Jim Cromie
2023-12-08 0:15 ` [re: PATCH v2 00/15 - 05/11] dyndbg: change +T:name_terminator to dot Jim Cromie
2023-12-18 17:29 ` Petr Mladek
2023-12-21 15:21 ` Łukasz Bartosik
2024-01-04 7:54 ` Petr Mladek
2024-01-08 12:21 ` Łukasz Bartosik
2023-12-08 0:15 ` [re: PATCH v2 00/15 - 06/11] dyndbg: treat comma as a token separator Jim Cromie
2023-12-08 0:15 ` [re: PATCH v2 00/15 - 07/11] dyndbg: __skip_spaces Jim Cromie
2023-12-18 17:17 ` Petr Mladek
2023-12-21 15:25 ` Łukasz Bartosik
2023-12-08 0:15 ` [re: PATCH v2 00/15 - 08/11] dyndbg: split multi-query strings with % Jim Cromie
2023-12-09 0:32 ` Łukasz Bartosik
2023-12-11 1:07 ` jim.cromie
2023-12-08 0:15 ` [re: PATCH v2 00/15 - 09/11] dyndbg: reduce verbose/debug clutter Jim Cromie
2023-12-08 0:15 ` [re: PATCH v2 00/15 - 10/11] dyndbg: move lock,unlock into ddebug_change, drop goto Jim Cromie
2023-12-09 0:32 ` Łukasz Bartosik
2023-12-08 0:15 ` [re: PATCH v2 00/15 - 11/11] dyndbg: id the bad word in parse-flags err msg Jim Cromie
2023-12-09 0:31 ` [re: PATCH v2 00/15 - 00/11] dyndbg: add support for writing debug logs to trace Łukasz Bartosik
2023-12-14 15:20 ` Łukasz Bartosik
2023-12-16 3:09 ` jim.cromie
2023-12-18 1:01 ` Łukasz Bartosik
2023-12-18 14:12 ` Łukasz Bartosik
2023-11-30 23:40 ` [PATCH v2 06/15] dyndbg: use __get_str_strip_nl in prdbg and devdbg Łukasz Bartosik
2023-11-30 23:40 ` [PATCH v2 07/15] dyndbg: repack _ddebug structure Łukasz Bartosik
2023-11-30 23:40 ` [PATCH v2 08/15] dyndbg: move flags field to a new structure Łukasz Bartosik
2023-11-30 23:40 ` [PATCH v2 09/15] dyndbg: add trace destination field to _ddebug Łukasz Bartosik
2023-12-14 7:09 ` jim.cromie
2023-12-14 15:46 ` Łukasz Bartosik
2023-11-30 23:40 ` [PATCH v2 10/15] dyndbg: add open and close commands for trace Łukasz Bartosik
2023-12-16 6:17 ` jim.cromie
2023-12-18 1:07 ` Łukasz Bartosik
2024-01-05 22:46 ` Jason Baron
2024-01-09 15:19 ` jim.cromie
2024-01-10 12:40 ` Łukasz Bartosik
2023-11-30 23:40 ` [PATCH v2 11/15] dyndbg: don't close trace instance when in use Łukasz Bartosik
2023-11-30 23:40 ` Łukasz Bartosik [this message]
2023-11-30 23:40 ` [PATCH v2 13/15] dyndbg: add support for default trace destination Łukasz Bartosik
2023-11-30 23:40 ` [PATCH v2 14/15] dyndbg: write debug logs to trace instance Łukasz Bartosik
2023-11-30 23:40 ` [PATCH v2 15/15] dyndbg: add support for hex_dump output to trace Łukasz Bartosik
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20231130234048.157509-13-lb@semihalf.com \
--to=lb@semihalf.com \
--cc=akpm@linux-foundation.org \
--cc=bleung@google.com \
--cc=daniel@ffwll.ch \
--cc=dianders@chromium.org \
--cc=groeck@google.com \
--cc=jbaron@akamai.com \
--cc=jim.cromie@gmail.com \
--cc=keescook@chromium.org \
--cc=linux-kernel@vger.kernel.org \
--cc=ppaalanen@gmail.com \
--cc=rostedt@goodmis.org \
--cc=seanpaul@chromium.org \
--cc=upstream@semihalf.com \
--cc=vincent.whitchurch@axis.com \
--cc=yanivt@google.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).