[<prev] [next>] [day] [month] [year] [list]
Message-ID: <20250829102050.232291-1-seokwoo.chung130@gmail.com>
Date: Fri, 29 Aug 2025 19:20:50 +0900
From: Ryan Chung <seokwoo.chung130@...il.com>
To: Steven Rostedt <rostedt@...dmis.org>,
Masami Hiramatsu <mhiramat@...nel.org>
Cc: Mathieu Desnoyers <mathieu.desnoyers@...icios.com>,
linux-trace-kernel@...r.kernel.org,
linux-kernel@...r.kernel.org,
Ryan Chung <seokwoo.chung130@...il.com>
Subject: [PATCH v2] trace_fprobe.c: TODO: handle filter, nofilter or symbol list
This v2 addresses the TODO in trace_fprobe to handle comma-separated
symbol lists and the '!' prefix. Tokens starting with '!' are collected
as "nofilter", and the others as "filter", then passed to
register_fprobe() accordingly. Empty tokens are rejected and errors are
reported with trace_probe_log_err().
Questions for maintainers (to confirm my understanding):
* Parsing location: Masami suggested doing the parsing in the parse
stage (e.g., via parse_symbol_and_return()). v2 keeps the logic in
__register_trace_fprobe(), but I can move the call into the parsing
path in v3 if that is the preferred place. Is that correct?
* Documentation: I plan to update the user-facing docs for fprobe
syntax. Is Documentation/trace/ the right place (e.g.,
Documentation/trace/fprobetrace.rst)?
Link: https://lore.kernel.org/linux-trace-kernel/20250812162101.5981-1-seokwoo.chung130@gmail.com/
Signed-off-by: Ryan Chung <seokwoo.chung130@...il.com>
---
Changes in v2:
* Classify '!' tokens as nofilter, others as filter; pass both to
register_fprobe().
* Reject empty tokens; log errors with trace_probe_log_*().
* Use __free(kfree) for temporary buffers.
* Keep subject and style per "Submitting patches" (tabs, wrapping).
* No manual dedup (leave to ftrace).
kernel/trace/trace_fprobe.c | 48 +++++++++++++++++++++++++++++++++++--
1 file changed, 46 insertions(+), 2 deletions(-)
diff --git a/kernel/trace/trace_fprobe.c b/kernel/trace/trace_fprobe.c
index b36ade43d4b3..d731d9754a39 100644
--- a/kernel/trace/trace_fprobe.c
+++ b/kernel/trace/trace_fprobe.c
@@ -815,6 +815,11 @@ static int trace_fprobe_verify_target(struct trace_fprobe *tf)
static int __register_trace_fprobe(struct trace_fprobe *tf)
{
int i, ret;
+ const char *p, *q;
+ size_t spec_len, flen = 0, nflen = 0, tlen;
+ bool have_f = false, have_nf = false;
+ char *filter __free(kfree) = NULL;
+ char *nofilter __free(kfree) = NULL;
/* Should we need new LOCKDOWN flag for fprobe? */
ret = security_locked_down(LOCKDOWN_KPROBES);
@@ -835,8 +840,47 @@ static int __register_trace_fprobe(struct trace_fprobe *tf)
if (trace_fprobe_is_tracepoint(tf))
return __regsiter_tracepoint_fprobe(tf);
- /* TODO: handle filter, nofilter or symbol list */
- return register_fprobe(&tf->fp, tf->symbol, NULL);
+ spec_len = strlen(tf->symbol);
+ filter = kzalloc(spec_len + 1, GFP_KERNEL);
+ nofilter = kzalloc(spec_len + 1, GFP_KERNEL);
+ if (!filter || !nofilter)
+ return -ENOMEM;
+
+ p = tf->symbol;
+ for (p = tf->symbol; p; p = q ? q + 1 : NULL) {
+ q = strchr(p, ',');
+ tlen = q ? (size_t)(q-p) : strlen(p);
+
+ /* reject empty token */
+ if (!tlen) {
+ trace_probe_log_set_index(1);
+ trace_probe_log_err(0, BAD_TP_NAME);
+ return -EINVAL;
+ }
+
+ if (*p == '!') {
+ if (tlen == 1) {
+ trace_probe_log_set_index(1);
+ trace_probe_log_err(0, BAD_TP_NAME);
+ return -EINVAL;
+ }
+ if (have_nf)
+ nofilter[nflen++] = ',';
+ memcpy(nofilter + nflen, p + 1, tlen - 1);
+ nflen += tlen - 1;
+ have_nf = true;
+ } else {
+ if (have_f)
+ filter[flen++] = ',';
+ memcpy(filter + flen, p, tlen);
+ flen += tlen;
+ have_f = true;
+ }
+ }
+
+ return register_fprobe(&tf->fp,
+ have_f ? filter : NULL,
+ have_nf ? nofilter : NULL);
}
/* Internal unregister function - just handle fprobe and flags */
--
2.43.0
Powered by blists - more mailing lists