From: "zhangwei(Jovi)" <jovi.zhangwei@huawei.com>
To: Namhyung Kim <namhyung@kernel.org>
Cc: Steven Rostedt <rostedt@goodmis.org>,
Namhyung Kim <namhyung.kim@lge.com>,
Hyeoncheol Lee <cheol.lee@lge.com>,
Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>,
LKML <linux-kernel@vger.kernel.org>,
Srikar Dronamraju <srikar@linux.vnet.ibm.com>,
Oleg Nesterov <oleg@redhat.com>,
Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
Subject: Re: [PATCH 10/13] tracing/uprobes: Fetch args before reserving a ring buffer
Date: Tue, 3 Sep 2013 19:10:04 +0800 [thread overview]
Message-ID: <5225C38C.2090305@huawei.com> (raw)
In-Reply-To: <1378187054-27401-11-git-send-email-namhyung@kernel.org>
On 2013/9/3 13:44, Namhyung Kim wrote:
> From: Namhyung Kim <namhyung.kim@lge.com>
>
> Fetching from user space should be done in a non-atomic context. So
> use a per-cpu buffer and copy its content to the ring buffer
> atomically. Note that we can migrate during accessing user memory
> thus use a per-cpu mutex to protect concurrent accesses.
>
> This is needed since we'll be able to fetch args from an user memory
> which can be swapped out. Before that uprobes could fetch args from
> registers only which saved in a kernel space.
>
> While at it, use __get_data_size() and store_trace_args() to reduce
> code duplication.
>
> Cc: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
> Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com>
> Cc: Oleg Nesterov <oleg@redhat.com>
> Cc: zhangwei(Jovi) <jovi.zhangwei@huawei.com>
> Cc: Arnaldo Carvalho de Melo <acme@ghostprotocols.net>
> Signed-off-by: Namhyung Kim <namhyung@kernel.org>
> ---
> kernel/trace/trace_uprobe.c | 97 +++++++++++++++++++++++++++++++++++++--------
> 1 file changed, 81 insertions(+), 16 deletions(-)
>
> diff --git a/kernel/trace/trace_uprobe.c b/kernel/trace/trace_uprobe.c
> index 9f2d12d2311d..9ede401759ab 100644
> --- a/kernel/trace/trace_uprobe.c
> +++ b/kernel/trace/trace_uprobe.c
> @@ -530,21 +530,46 @@ static const struct file_operations uprobe_profile_ops = {
> .release = seq_release,
> };
>
> +static atomic_t uprobe_buffer_ref = ATOMIC_INIT(0);
> +static void __percpu *uprobe_cpu_buffer;
> +static DEFINE_PER_CPU(struct mutex, uprobe_cpu_mutex);
> +
> static void uprobe_trace_print(struct trace_uprobe *tu,
> unsigned long func, struct pt_regs *regs)
> {
> struct uprobe_trace_entry_head *entry;
> struct ring_buffer_event *event;
> struct ring_buffer *buffer;
> - void *data;
> - int size, i;
> + struct mutex *mutex;
> + void *data, *arg_buf;
> + int size, dsize, esize;
> + int cpu;
> struct ftrace_event_call *call = &tu->p.call;
>
> - size = SIZEOF_TRACE_ENTRY(is_ret_probe(tu));
> + dsize = __get_data_size(&tu->p, regs);
> + esize = SIZEOF_TRACE_ENTRY(is_ret_probe(tu));
> +
> + if (WARN_ON_ONCE(!uprobe_cpu_buffer || tu->p.size + dsize > PAGE_SIZE))
> + return;
> +
> + cpu = raw_smp_processor_id();
> + mutex = &per_cpu(uprobe_cpu_mutex, cpu);
> + arg_buf = per_cpu_ptr(uprobe_cpu_buffer, cpu);
> +
> + /*
> + * Use per-cpu buffers for fastest access, but we might migrate
> + * so the mutex makes sure we have sole access to it.
> + */
> + mutex_lock(mutex);
> + store_trace_args(esize, &tu->p, regs, arg_buf, dsize);
> +
> + size = esize + tu->p.size + dsize;
> event = trace_current_buffer_lock_reserve(&buffer, call->event.type,
> - size + tu->p.size, 0, 0);
> - if (!event)
> + size, 0, 0);
> + if (!event) {
> + mutex_unlock(mutex);
> return;
> + }
>
> entry = ring_buffer_event_data(event);
> if (is_ret_probe(tu)) {
> @@ -556,13 +581,12 @@ static void uprobe_trace_print(struct trace_uprobe *tu,
> data = DATAOF_TRACE_ENTRY(entry, false);
> }
>
> - for (i = 0; i < tu->p.nr_args; i++) {
> - call_fetch(&tu->p.args[i].fetch, regs,
> - data + tu->p.args[i].offset);
> - }
> + memcpy(data, arg_buf, tu->p.size + dsize);
>
> if (!filter_current_check_discard(buffer, call, entry, event))
> trace_buffer_unlock_commit(buffer, event, 0, 0);
> +
> + mutex_unlock(mutex);
> }
>
> /* uprobe handler */
> @@ -630,6 +654,17 @@ probe_event_enable(struct trace_uprobe *tu, int flag, filter_func_t filter)
> if (trace_probe_is_enabled(&tu->p))
> return -EINTR;
>
> + if (atomic_inc_return(&uprobe_buffer_ref) == 1) {
> + int cpu;
> +
> + uprobe_cpu_buffer = __alloc_percpu(PAGE_SIZE, PAGE_SIZE);
> + if (uprobe_cpu_buffer == NULL)
> + return -ENOMEM;
> +
Do we need add atomic_dec if allocate percpu buffer failed?
> + for_each_possible_cpu(cpu)
> + mutex_init(&per_cpu(uprobe_cpu_mutex, cpu));
> + }
> +
> WARN_ON(!uprobe_filter_is_empty(&tu->filter));
>
> tu->p.flags |= flag;
> @@ -646,6 +681,11 @@ static void probe_event_disable(struct trace_uprobe *tu, int flag)
> if (!trace_probe_is_enabled(&tu->p))
> return;
>
> + if (atomic_dec_and_test(&uprobe_buffer_ref)) {
> + free_percpu(uprobe_cpu_buffer);
> + uprobe_cpu_buffer = NULL;
> + }
> +
> WARN_ON(!uprobe_filter_is_empty(&tu->filter));
>
> uprobe_unregister(tu->inode, tu->offset, &tu->consumer);
> @@ -776,11 +816,33 @@ static void uprobe_perf_print(struct trace_uprobe *tu,
> struct ftrace_event_call *call = &tu->p.call;
> struct uprobe_trace_entry_head *entry;
> struct hlist_head *head;
> - void *data;
> - int size, rctx, i;
> + struct mutex *mutex;
> + void *data, *arg_buf;
> + int size, dsize, esize;
> + int cpu;
> + int rctx;
>
> - size = SIZEOF_TRACE_ENTRY(is_ret_probe(tu));
> - size = ALIGN(size + tu->p.size + sizeof(u32), sizeof(u64)) - sizeof(u32);
> + dsize = __get_data_size(&tu->p, regs);
> + esize = SIZEOF_TRACE_ENTRY(is_ret_probe(tu));
> +
> + if (WARN_ON_ONCE(!uprobe_cpu_buffer))
> + return;
> +
> + size = esize + tu->p.size + dsize;
> + size = ALIGN(size + sizeof(u32), sizeof(u64)) - sizeof(u32);
> + if (WARN_ONCE(size > PERF_MAX_TRACE_SIZE, "profile buffer not large enough"))
> + return;
> +
> + cpu = raw_smp_processor_id();
> + mutex = &per_cpu(uprobe_cpu_mutex, cpu);
> + arg_buf = per_cpu_ptr(uprobe_cpu_buffer, cpu);
> +
> + /*
> + * Use per-cpu buffers for fastest access, but we might migrate
> + * so the mutex makes sure we have sole access to it.
> + */
> + mutex_lock(mutex);
> + store_trace_args(esize, &tu->p, regs, arg_buf, dsize);
>
> preempt_disable();
> head = this_cpu_ptr(call->perf_events);
> @@ -800,15 +862,18 @@ static void uprobe_perf_print(struct trace_uprobe *tu,
> data = DATAOF_TRACE_ENTRY(entry, false);
> }
>
> - for (i = 0; i < tu->p.nr_args; i++) {
> - struct probe_arg *parg = &tu->p.args[i];
> + memcpy(data, arg_buf, tu->p.size + dsize);
> +
> + if (size - esize > tu->p.size + dsize) {
> + int len = tu->p.size + dsize;
>
> - call_fetch(&parg->fetch, regs, data + parg->offset);
> + memset(data + len, 0, size - esize - len);
> }
>
> perf_trace_buf_submit(entry, size, rctx, 0, 1, regs, head, NULL);
> out:
> preempt_enable();
> + mutex_unlock(mutex);
> }
>
> /* uprobe profile handler */
>
next prev parent reply other threads:[~2013-09-03 11:12 UTC|newest]
Thread overview: 45+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-09-03 5:44 [PATCHSET 00/13] tracing/uprobes: Add support for more fetch methods (v5) Namhyung Kim
2013-09-03 5:44 ` [PATCH 01/13] tracing/uprobes: Fix documentation of uprobe registration syntax Namhyung Kim
2013-09-03 5:44 ` [PATCH 02/13] tracing/probes: Fix basic print type functions Namhyung Kim
2013-09-03 5:44 ` [PATCH 03/13] tracing/kprobes: Move fetch functions to trace_kprobe.c Namhyung Kim
2013-09-03 5:44 ` [PATCH 04/13] tracing/kprobes: Add fetch{,_size} member into deref fetch method Namhyung Kim
2013-09-03 5:44 ` [PATCH 05/13] tracing/kprobes: Staticize stack and memory fetch functions Namhyung Kim
2013-09-03 5:44 ` [PATCH 06/13] tracing/kprobes: Factor out struct trace_probe Namhyung Kim
2013-09-03 5:44 ` [PATCH 07/13] tracing/uprobes: Convert to " Namhyung Kim
2013-09-03 5:44 ` [PATCH 08/13] tracing/kprobes: Move common functions to trace_probe.h Namhyung Kim
2013-09-03 5:44 ` [PATCH 09/13] tracing/kprobes: Integrate duplicate set_print_fmt() Namhyung Kim
2013-09-03 5:44 ` [PATCH 10/13] tracing/uprobes: Fetch args before reserving a ring buffer Namhyung Kim
2013-09-03 10:50 ` Masami Hiramatsu
2013-09-04 7:08 ` Namhyung Kim
2013-09-04 8:13 ` [PATCH v5.1 " Namhyung Kim
2013-09-03 11:10 ` zhangwei(Jovi) [this message]
2013-09-04 7:10 ` [PATCH " Namhyung Kim
2013-09-03 5:44 ` [PATCH 11/13] tracing/kprobes: Add priv argument to fetch functions Namhyung Kim
2013-09-03 5:44 ` [PATCH 12/13] tracing/uprobes: Add more " Namhyung Kim
2013-09-03 5:44 ` [PATCH 13/13] tracing/uprobes: Add support for full argument access methods Namhyung Kim
2013-09-03 9:48 ` Masami Hiramatsu
-- strict thread matches above, loose matches on Subject: below --
2013-10-29 6:53 [PATCHSET 00/13] tracing/uprobes: Add support for more fetch methods (v6) Namhyung Kim
2013-10-29 6:53 ` [PATCH 10/13] tracing/uprobes: Fetch args before reserving a ring buffer Namhyung Kim
2013-10-31 18:16 ` Oleg Nesterov
2013-11-01 9:00 ` Namhyung Kim
2013-11-04 8:06 ` Namhyung Kim
2013-11-04 14:35 ` Oleg Nesterov
2013-11-05 1:12 ` Namhyung Kim
2013-11-01 15:09 ` Oleg Nesterov
2013-11-01 15:22 ` Oleg Nesterov
2013-11-03 20:20 ` Oleg Nesterov
2013-11-04 8:11 ` Namhyung Kim
2013-11-04 14:38 ` Oleg Nesterov
2013-11-05 1:17 ` Namhyung Kim
2013-08-27 8:48 [PATCHSET 00/13] tracing/uprobes: Add support for more fetch methods (v4) Namhyung Kim
2013-08-27 8:48 ` [PATCH 10/13] tracing/uprobes: Fetch args before reserving a ring buffer Namhyung Kim
2013-08-09 8:44 [PATCHSET 00/13] tracing/uprobes: Add support for more fetch methods (v3) Namhyung Kim
2013-08-09 8:45 ` [PATCH 10/13] tracing/uprobes: Fetch args before reserving a ring buffer Namhyung Kim
2013-08-09 9:56 ` Masami Hiramatsu
2013-08-09 16:20 ` Oleg Nesterov
2013-08-09 16:21 ` Oleg Nesterov
2013-08-10 1:26 ` zhangwei(Jovi)
2013-08-10 1:41 ` zhangwei(Jovi)
2013-08-10 14:06 ` zhangwei(Jovi)
2013-08-22 16:42 ` Steven Rostedt
2013-08-22 23:57 ` zhangwei(Jovi)
2013-08-23 1:08 ` Steven Rostedt
2013-08-27 8:07 ` Namhyung Kim
2013-08-23 4:22 ` Masami Hiramatsu
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=5225C38C.2090305@huawei.com \
--to=jovi.zhangwei@huawei.com \
--cc=acme@ghostprotocols.net \
--cc=cheol.lee@lge.com \
--cc=linux-kernel@vger.kernel.org \
--cc=masami.hiramatsu.pt@hitachi.com \
--cc=namhyung.kim@lge.com \
--cc=namhyung@kernel.org \
--cc=oleg@redhat.com \
--cc=rostedt@goodmis.org \
--cc=srikar@linux.vnet.ibm.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.