Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753426AbZJQKCK (ORCPT ); Sat, 17 Oct 2009 06:02:10 -0400 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1752909AbZJQKCJ (ORCPT ); Sat, 17 Oct 2009 06:02:09 -0400 Received: from hera.kernel.org ([140.211.167.34]:36465 "EHLO hera.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753016AbZJQKCF (ORCPT ); Sat, 17 Oct 2009 06:02:05 -0400 Date: Sat, 17 Oct 2009 10:01:27 GMT From: tip-bot for Masami Hiramatsu Cc: mingo@redhat.com, peterz@infradead.org, fweisbec@gmail.com, rostedt@goodmis.org, ak@linux.intel.com, jbaron@redhat.com, tglx@linutronix.de, laijs@cn.fujitsu.com, mhiramat@redhat.com, linux-kernel@vger.kernel.org, hpa@zytor.com, fche@redhat.com, jkenisto@us.ibm.com, tzanussi@gmail.com, lizf@cn.fujitsu.com, hch@infradead.org, ananth@in.ibm.com, srikar@linux.vnet.ibm.com, mingo@elte.hu, prasad@linux.vnet.ibm.com Reply-To: mingo@redhat.com, peterz@infradead.org, fweisbec@gmail.com, rostedt@goodmis.org, ak@linux.intel.com, jbaron@redhat.com, tglx@linutronix.de, laijs@cn.fujitsu.com, mhiramat@redhat.com, linux-kernel@vger.kernel.org, hpa@zytor.com, fche@redhat.com, jkenisto@us.ibm.com, tzanussi@gmail.com, lizf@cn.fujitsu.com, hch@infradead.org, ananth@in.ibm.com, srikar@linux.vnet.ibm.com, mingo@elte.hu, prasad@linux.vnet.ibm.com In-Reply-To: <20090914204920.18779.57555.stgit@dhcp-100-2-132.bos.redhat.com> References: <20090914204920.18779.57555.stgit@dhcp-100-2-132.bos.redhat.com> To: linux-tip-commits@vger.kernel.org Subject: [tip:perf/probes] tracing/kprobes: Add probe handler dispatcher to support perf and ftrace concurrent use Message-ID: Git-Commit-ID: 50d780560785b068c358675c5f0bf6c83b5c373e X-Mailer: tip-git-log-daemon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.0 (hera.kernel.org [127.0.0.1]); Sat, 17 Oct 2009 10:01:28 +0000 (UTC) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 6475 Lines: 203 Commit-ID: 50d780560785b068c358675c5f0bf6c83b5c373e Gitweb: http://git.kernel.org/tip/50d780560785b068c358675c5f0bf6c83b5c373e Author: Masami Hiramatsu AuthorDate: Mon, 14 Sep 2009 16:49:20 -0400 Committer: Frederic Weisbecker CommitDate: Thu, 17 Sep 2009 04:03:54 +0200 tracing/kprobes: Add probe handler dispatcher to support perf and ftrace concurrent use Add kprobe_dispatcher and kretprobe_dispatcher to dispatch event in both profile and tracing handlers. This allows simultaneous kprobe uses by ftrace and perf. Signed-off-by: Masami Hiramatsu Acked-by: Steven Rostedt Cc: Jim Keniston Cc: Ananth N Mavinakayanahalli Cc: Andi Kleen Cc: Christoph Hellwig Cc: Frank Ch. Eigler Cc: H. Peter Anvin Cc: Ingo Molnar Cc: Jason Baron Cc: K.Prasad Cc: Lai Jiangshan Cc: Li Zefan Cc: Peter Zijlstra Cc: Srikar Dronamraju Cc: Tom Zanussi LKML-Reference: <20090914204920.18779.57555.stgit@dhcp-100-2-132.bos.redhat.com> Signed-off-by: Frederic Weisbecker --- kernel/trace/trace_kprobe.c | 85 ++++++++++++++++++++++++++++++++----------- 1 files changed, 63 insertions(+), 22 deletions(-) diff --git a/kernel/trace/trace_kprobe.c b/kernel/trace/trace_kprobe.c index ea0db8e..70b632c 100644 --- a/kernel/trace/trace_kprobe.c +++ b/kernel/trace/trace_kprobe.c @@ -185,10 +185,15 @@ struct probe_arg { const char *name; }; +/* Flags for trace_probe */ +#define TP_FLAG_TRACE 1 +#define TP_FLAG_PROFILE 2 + struct trace_probe { struct list_head list; struct kretprobe rp; /* Use rp.kp for kprobe use */ unsigned long nhit; + unsigned int flags; /* For TP_FLAG_* */ const char *symbol; /* symbol name */ struct ftrace_event_call call; struct trace_event event; @@ -200,10 +205,6 @@ struct trace_probe { (offsetof(struct trace_probe, args) + \ (sizeof(struct probe_arg) * (n))) -static int kprobe_trace_func(struct kprobe *kp, struct pt_regs *regs); -static int kretprobe_trace_func(struct kretprobe_instance *ri, - struct pt_regs *regs); - static __kprobes int probe_is_return(struct trace_probe *tp) { return tp->rp.handler != NULL; @@ -263,6 +264,10 @@ static void unregister_probe_event(struct trace_probe *tp); static DEFINE_MUTEX(probe_lock); static LIST_HEAD(probe_list); +static int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs); +static int kretprobe_dispatcher(struct kretprobe_instance *ri, + struct pt_regs *regs); + /* * Allocate new trace_probe and initialize it (including kprobes). */ @@ -288,11 +293,10 @@ static struct trace_probe *alloc_trace_probe(const char *group, } else tp->rp.kp.addr = addr; - /* Set handler here for checking whether this probe is return or not. */ if (is_return) - tp->rp.handler = kretprobe_trace_func; + tp->rp.handler = kretprobe_dispatcher; else - tp->rp.kp.pre_handler = kprobe_trace_func; + tp->rp.kp.pre_handler = kprobe_dispatcher; if (!event) goto error; @@ -379,6 +383,7 @@ static int register_trace_probe(struct trace_probe *tp) goto end; } + tp->flags = TP_FLAG_TRACE; if (probe_is_return(tp)) ret = register_kretprobe(&tp->rp); else @@ -987,23 +992,24 @@ static int probe_event_enable(struct ftrace_event_call *call) { struct trace_probe *tp = (struct trace_probe *)call->data; - if (probe_is_return(tp)) { - tp->rp.handler = kretprobe_trace_func; + tp->flags |= TP_FLAG_TRACE; + if (probe_is_return(tp)) return enable_kretprobe(&tp->rp); - } else { - tp->rp.kp.pre_handler = kprobe_trace_func; + else return enable_kprobe(&tp->rp.kp); - } } static void probe_event_disable(struct ftrace_event_call *call) { struct trace_probe *tp = (struct trace_probe *)call->data; - if (probe_is_return(tp)) - disable_kretprobe(&tp->rp); - else - disable_kprobe(&tp->rp.kp); + tp->flags &= ~TP_FLAG_TRACE; + if (!(tp->flags & (TP_FLAG_TRACE | TP_FLAG_PROFILE))) { + if (probe_is_return(tp)) + disable_kretprobe(&tp->rp); + else + disable_kprobe(&tp->rp.kp); + } } static int probe_event_raw_init(struct ftrace_event_call *event_call) @@ -1212,22 +1218,57 @@ static int probe_profile_enable(struct ftrace_event_call *call) if (atomic_inc_return(&call->profile_count)) return 0; - if (probe_is_return(tp)) { - tp->rp.handler = kretprobe_profile_func; + tp->flags |= TP_FLAG_PROFILE; + if (probe_is_return(tp)) return enable_kretprobe(&tp->rp); - } else { - tp->rp.kp.pre_handler = kprobe_profile_func; + else return enable_kprobe(&tp->rp.kp); - } } static void probe_profile_disable(struct ftrace_event_call *call) { + struct trace_probe *tp = (struct trace_probe *)call->data; + if (atomic_add_negative(-1, &call->profile_count)) - probe_event_disable(call); + tp->flags &= ~TP_FLAG_PROFILE; + + if (!(tp->flags & (TP_FLAG_TRACE | TP_FLAG_PROFILE))) { + if (probe_is_return(tp)) + disable_kretprobe(&tp->rp); + else + disable_kprobe(&tp->rp.kp); + } } +#endif /* CONFIG_EVENT_PROFILE */ + + +static __kprobes +int kprobe_dispatcher(struct kprobe *kp, struct pt_regs *regs) +{ + struct trace_probe *tp = container_of(kp, struct trace_probe, rp.kp); + if (tp->flags & TP_FLAG_TRACE) + kprobe_trace_func(kp, regs); +#ifdef CONFIG_EVENT_PROFILE + if (tp->flags & TP_FLAG_PROFILE) + kprobe_profile_func(kp, regs); #endif /* CONFIG_EVENT_PROFILE */ + return 0; /* We don't tweek kernel, so just return 0 */ +} + +static __kprobes +int kretprobe_dispatcher(struct kretprobe_instance *ri, struct pt_regs *regs) +{ + struct trace_probe *tp = container_of(ri->rp, struct trace_probe, rp); + + if (tp->flags & TP_FLAG_TRACE) + kretprobe_trace_func(ri, regs); +#ifdef CONFIG_EVENT_PROFILE + if (tp->flags & TP_FLAG_PROFILE) + kretprobe_profile_func(ri, regs); +#endif /* CONFIG_EVENT_PROFILE */ + return 0; /* We don't tweek kernel, so just return 0 */ +} static int register_probe_event(struct trace_probe *tp) { -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/