[PATCH] trace-cmd: filter out specific pids

From: Josef Bacik
Date: Fri Dec 04 2015 - 12:03:52 EST


Sometimes it is a good idea to filter out events from the recording processes
and even other pids, for example an external app that links against libtracecmd
that watches syscalls probably doesn't want its own syscalls showing up in the
events. So add the ability to filter _out_ certain pids for the events that are
enabled. The recorder threads will add their pids to this list, but they are
only filtered if the library consumer filters out a pid or if the trace-cmd
record user tries to filter anything out. Thanks,

Signed-off-by: Josef Bacik <jbacik@xxxxxx>
---
trace-cmd.h | 1 +
trace-record.c | 44 +++++++++++++++++++++++++++++++++++---------
2 files changed, 36 insertions(+), 9 deletions(-)

diff --git a/trace-cmd.h b/trace-cmd.h
index 6bbc97a..3a230b4 100644
--- a/trace-cmd.h
+++ b/trace-cmd.h
@@ -295,6 +295,7 @@ void tracecmd_start_threads(enum tracecmd_trace_type type,
tracecmd_handle_init_func handle_init, int global);
void tracecmd_stop_threads(enum tracecmd_trace_type type);
int tracecmd_stream_loop(struct timeval *tv);
+void tracecmd_filter_pid(int pid, int exclude);

/* --- Plugin handling --- */
extern struct pevent_plugin_option trace_ftrace_options[];
diff --git a/trace-record.c b/trace-record.c
index 7d3ea37..49a8280 100644
--- a/trace-record.c
+++ b/trace-record.c
@@ -114,6 +114,7 @@ static int save_stdout = -1;
struct filter_pids {
struct filter_pids *next;
int pid;
+ int exclude;
};

static struct filter_pids *filter_pids;
@@ -747,13 +748,14 @@ static void reset_max_latency(void)
fclose(fp);
}

-static void add_filter_pid(int pid)
+static void add_filter_pid(int pid, int exclude)
{
struct filter_pids *p;
char buf[100];

p = malloc_or_die(sizeof(*p));
p->next = filter_pids;
+ p->exclude = exclude;
p->pid = pid;
filter_pids = p;
nr_filter_pids++;
@@ -823,6 +825,8 @@ static void update_ftrace_pids(int reset)
struct filter_pids *pid;

for (pid = filter_pids; pid; pid = pid->next) {
+ if (pid->exclude)
+ continue;
snprintf(buf, 100, "%d ", pid->pid);
update_ftrace_pid(buf, reset);
/* Only reset the first entry */
@@ -849,6 +853,7 @@ static char *make_pid_filter(char *curr_filter, const char *field)
struct filter_pids *p;
char *filter;
char *orit;
+ char *match;
char *str;
int curr_len = 0;
int len;
@@ -875,7 +880,11 @@ static char *make_pid_filter(char *curr_filter, const char *field)
orit = "";
else
orit = "||";
- len = sprintf(str, "%s(%s==%d)", orit, field, p->pid);
+ if (p->exclude)
+ match = "!=";
+ else
+ match = "==";
+ len = sprintf(str, "%s(%s%s%d)", orit, field, match, p->pid);
str += len;
}

@@ -891,7 +900,7 @@ static void update_task_filter(void)
int pid = getpid();

if (filter_task)
- add_filter_pid(pid);
+ add_filter_pid(pid, 0);

if (!filter_pids)
return;
@@ -903,6 +912,21 @@ static void update_task_filter(void)
update_pid_event_filters(instance);
}

+void tracecmd_filter_pid(int pid, int exclude)
+{
+ struct buffer_instance *instance;
+
+ add_filter_pid(pid, exclude);
+ common_pid_filter = make_pid_filter(NULL, "common_pid");
+
+ if (!filter_pids)
+ return;
+
+ update_ftrace_pids(1);
+ for_all_instances(instance)
+ update_pid_event_filters(instance);
+}
+
static pid_t trace_waitpid(enum tracecmd_trace_type type, pid_t pid, int *status, int options)
{
struct timeval tv = { 1, 0 };
@@ -977,7 +1001,7 @@ static void add_new_filter_pid(int pid)
struct buffer_instance *instance;
char buf[100];

- add_filter_pid(pid);
+ add_filter_pid(pid, 0);
sprintf(buf, "%d", pid);
update_ftrace_pid(buf, 0);

@@ -999,7 +1023,7 @@ static void ptrace_attach(int pid)
do_ptrace = 0;
return;
}
- add_filter_pid(pid);
+ add_filter_pid(pid, 0);
}

static void enable_ptrace(void)
@@ -1113,7 +1137,7 @@ static void run_cmd(enum tracecmd_trace_type type, int argc, char **argv)
}
}
if (do_ptrace) {
- add_filter_pid(pid);
+ add_filter_pid(pid, 0);
ptrace_wait(type, pid);
} else
trace_waitpid(type, pid, &status, 0);
@@ -2587,7 +2611,7 @@ void tracecmd_start_threads(enum tracecmd_trace_type type,
memset(pids, 0, sizeof(*pids) * cpu_count * (buffers + 1));

for_all_instances(instance) {
- int x;
+ int x, pid;
for (x = 0; x < cpu_count; x++) {
if (type & TRACE_TYPE_STREAM) {
brass = pids[i].brass;
@@ -2606,9 +2630,11 @@ void tracecmd_start_threads(enum tracecmd_trace_type type,
pids[i].instance = instance;
/* Make sure all output is flushed before forking */
fflush(stdout);
- pids[i++].pid = create_recorder(instance, x, type, brass);
+ pid = pids[i++].pid = create_recorder(instance, x, type, brass);
if (brass)
close(brass[1]);
+ if (pid > 0)
+ add_filter_pid(pid, 1);
}
}
recorder_threads = i;
@@ -4088,7 +4114,7 @@ void trace_record (int argc, char **argv)
die("strdup");
pid = strtok_r(pids, ",", &sav);
while (pid) {
- add_filter_pid(atoi(pid));
+ add_filter_pid(atoi(pid), 0);
pid = strtok_r(NULL, ",", &sav);
}
free(pids);
--
2.5.0

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/