uprobes/perf: Teach trace_uprobe/perf code to pre-filter
authorOleg Nesterov <oleg@redhat.com>
Mon, 4 Feb 2013 16:11:58 +0000 (17:11 +0100)
committerOleg Nesterov <oleg@redhat.com>
Fri, 8 Feb 2013 17:28:07 +0000 (18:28 +0100)
commit31ba334836c0ac0039084859f14a5b96858493dc
treea6f8d72d58f165717481aae43fcabe25b326dce3
parent736288ba5016e255869c26296014eeff649971c2
uprobes/perf: Teach trace_uprobe/perf code to pre-filter

Finally implement uprobe_perf_filter() which checks ->nr_systemwide or
->perf_events to figure out whether we need to insert the breakpoint.

uprobe_perf_open/close are changed to do uprobe_apply(true/false) when
the new perf event comes or goes away.

Note that currently this is very suboptimal:

- uprobe_register() called by TRACE_REG_PERF_REGISTER becomes a
  heavy nop, consumer->filter() always returns F at this stage.

  As it was already discussed we need uprobe_register_only() to
  avoid the costly register_for_each_vma() when possible.

- uprobe_apply() is oftenly overkill. Unless "nr_systemwide != 0"
  changes we need uprobe_apply_mm(), unapply_uprobe() is almost
  what we need.

- uprobe_apply() can be simply avoided sometimes, see the next
  changes.

Testing:

# perf probe -x /lib/libc.so.6 syscall

# perl -e 'syscall -1 while 1' &
[1] 530

# perf record -e probe_libc:syscall perl -e 'syscall -1 for 1..10; sleep 1'

# perf report --show-total-period
100.00%            10     perl  libc-2.8.so    [.] syscall

Before this patch:

# cat /sys/kernel/debug/tracing/uprobe_profile
/lib/libc.so.6 syscall 79291

A huge ->nrhit == 79291 reflects the fact that the background process
530 constantly hits this breakpoint too, even if doesn't contribute to
the output.

After the patch:

# cat /sys/kernel/debug/tracing/uprobe_profile
/lib/libc.so.6 syscall 10

This shows that only the target process was punished by int3.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
kernel/trace/trace_uprobe.c