lkml.org 
[lkml]   [2013]   [Jan]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
Subject[PATCH 3/4] uprobes: Teach tracing/uprobe_events to accept pid=TGID argument
A separate change to simplify the review.

With this patch create_trace_uprobe() parses the new pid=TGID argument
and stores the found "struct pid *" in "struct trace_uprobe" along with
inode/offset.

However, to simplify the potential extensions, we add the new structure
to hold this pid, and the set of its methods. This way we can, say, change
this code to accept the list of pid's without touching the non-filtering
code again.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
kernel/trace/trace_uprobe.c | 66 +++++++++++++++++++++++++++++++++++++++++-
1 files changed, 64 insertions(+), 2 deletions(-)

diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
index 94d4ea2..f7a2dcb 100644
--- a/kernel/trace/trace_uprobe.c
+++ b/kernel/trace/trace_uprobe.c
@@ -23,6 +23,7 @@
#include <linux/uprobes.h>
#include <linux/namei.h>
#include <linux/string.h>
+#include <linux/pid.h>

#include "trace_probe.h"

@@ -37,11 +38,16 @@ struct uprobe_trace_consumer {
struct trace_uprobe *tu;
};

+struct trace_uprobe_filter {
+ struct pid *tgid;
+};
+
struct trace_uprobe {
struct list_head list;
struct ftrace_event_class class;
struct ftrace_event_call call;
struct uprobe_trace_consumer *consumer;
+ struct trace_uprobe_filter filter;
struct inode *inode;
char *filename;
unsigned long offset;
@@ -64,6 +70,48 @@ static LIST_HEAD(uprobe_list);

static int uprobe_dispatcher(struct uprobe_consumer *con, struct pt_regs *regs);

+static int init_trace_uprobe_filter(struct trace_uprobe_filter *filter,
+ const char *arg)
+{
+ struct task_struct *p;
+ pid_t tgid;
+
+ if (!arg)
+ return 0;
+
+ if (kstrtouint(arg, 0, &tgid))
+ goto err;
+
+ filter->tgid = find_get_pid(tgid);
+ if (!filter->tgid)
+ goto err;
+
+ rcu_read_lock();
+ p = pid_task(filter->tgid, PIDTYPE_PID);
+ if (!p || !has_group_leader_pid(p) || (p->flags & PF_KTHREAD))
+ p = NULL;
+ rcu_read_unlock();
+
+ if (p)
+ return 0;
+err:
+ pr_info("Failed to find the process by pid=%s\n", arg);
+ /* free_trace_uprobe() will take care of ->tgid != NULL */
+ return -ESRCH;
+}
+
+static void free_trace_uprobe_filter(struct trace_uprobe_filter *filter)
+{
+ put_pid(filter->tgid);
+}
+
+static void probes_seq_show_filter(struct trace_uprobe_filter *filter,
+ struct seq_file *m)
+{
+ if (filter->tgid)
+ seq_printf(m, " pid=%d", pid_vnr(filter->tgid));
+}
+
/*
* Allocate new trace_uprobe and initialize it (including uprobes).
*/
@@ -111,6 +159,7 @@ static void free_trace_uprobe(struct trace_uprobe *tu)
traceprobe_free_probe_arg(&tu->args[i]);

iput(tu->inode);
+ free_trace_uprobe_filter(&tu->filter);
kfree(tu->call.class->system);
kfree(tu->call.name);
kfree(tu->filename);
@@ -167,7 +216,7 @@ end:

/*
* Argument syntax:
- * - Add uprobe: p[:[GRP/]EVENT] PATH:SYMBOL[+offs] [FETCHARGS]
+ * - Add uprobe: p[:[GRP/]EVENT] PATH:OFFSET [pid=TGID] [FETCHARGS]
*
* - Remove uprobe: -:[GRP/]EVENT
*/
@@ -176,6 +225,7 @@ static int create_trace_uprobe(int argc, char **argv)
struct trace_uprobe *tu;
struct inode *inode;
char *arg, *event, *group, *filename;
+ char *filter_arg;
char buf[MAX_EVENT_NAME_LEN];
struct path path;
unsigned long offset;
@@ -265,6 +315,13 @@ static int create_trace_uprobe(int argc, char **argv)
argc -= 2;
argv += 2;

+ filter_arg = NULL;
+ if (argc && strncmp(argv[0], "pid=", 4) == 0) {
+ filter_arg = argv[0] + 4;
+ argc--;
+ argv++;
+ }
+
/* setup a probe */
if (!event) {
char *tail;
@@ -301,8 +358,11 @@ static int create_trace_uprobe(int argc, char **argv)
goto error;
}

+ ret = init_trace_uprobe_filter(&tu->filter, filter_arg);
+ if (ret)
+ goto error;
+
/* parse arguments */
- ret = 0;
for (i = 0; i < argc && i < MAX_TRACE_ARGS; i++) {
/* Increment count for freeing args in error case */
tu->nr_args++;
@@ -402,6 +462,8 @@ static int probes_seq_show(struct seq_file *m, void *v)
seq_printf(m, "p:%s/%s", tu->call.class->system, tu->call.name);
seq_printf(m, " %s:0x%p", tu->filename, (void *)tu->offset);

+ probes_seq_show_filter(&tu->filter, m);
+
for (i = 0; i < tu->nr_args; i++)
seq_printf(m, " %s=%s", tu->args[i].name, tu->args[i].comm);

--
1.5.5.1


\
 
 \ /
  Last update: 2013-01-27 21:21    [W:1.239 / U:0.068 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site