All of lore.kernel.org
 help / color / mirror / Atom feed
From: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
To: linux-kernel@vger.kernel.org, Steven Rostedt <rostedt@goodmis.org>
Cc: Srikar Dronamraju <srikar@linux.vnet.ibm.com>,
	Frederic Weisbecker <fweisbec@gmail.com>,
	yrl.pp-manager.tt@hitachi.com, Oleg Nesterov <oleg@redhat.com>,
	Ingo Molnar <mingo@redhat.com>,
	Tom Zanussi <tom.zanussi@intel.com>
Subject: [PATCH 5/5] tracing: Support enable/disable multiple events trigger by wild cards
Date: Thu, 16 May 2013 20:49:00 +0900	[thread overview]
Message-ID: <20130516114900.13508.29247.stgit@mhiramat-M0-7522> (raw)
In-Reply-To: <20130516114839.13508.92844.stgit@mhiramat-M0-7522>

Support enable/disable multiple events trigger on ftrace
by using wild cards. This makes enabling multiple events
at once easy.

e.g.)
 # echo vfs_symlink:enable_event:\*:\*rq\* > set_ftrace_filter

 # cat set_ftrace_filter
#### all functions enabled ####
vfs_symlink:enable_event:*:*rq*:unlimited

 # grep 0\\* -r events/*/*/enable
events/block/block_getrq/enable:0*
events/block/block_rq_abort/enable:0*
events/block/block_rq_complete/enable:0*
events/block/block_rq_insert/enable:0*
events/block/block_rq_issue/enable:0*
events/block/block_rq_remap/enable:0*
events/block/block_rq_requeue/enable:0*
events/block/block_sleeprq/enable:0*
events/irq/irq_handler_entry/enable:0*
events/irq/irq_handler_exit/enable:0*
events/irq/softirq_entry/enable:0*
events/irq/softirq_exit/enable:0*
events/irq/softirq_raise/enable:0*

Signed-off-by: Masami Hiramatsu <masami.hiramatsu.pt@hitachi.com>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Ingo Molnar <mingo@redhat.com>
---
 Documentation/trace/ftrace.txt |   12 ++--
 kernel/trace/trace_events.c    |  123 +++++++++++++++++++++++++++++-----------
 2 files changed, 95 insertions(+), 40 deletions(-)

diff --git a/Documentation/trace/ftrace.txt b/Documentation/trace/ftrace.txt
index bfe8c29..92ca5236 100644
--- a/Documentation/trace/ftrace.txt
+++ b/Documentation/trace/ftrace.txt
@@ -2407,11 +2407,11 @@ The following commands are supported:
    echo '!native_flush_tlb_others:snapshot:0' > set_ftrace_filter
 
 - enable_event/disable_event
-  These commands can enable or disable a trace event. Note, because
+  These commands can enable or disable trace events. Note, because
   function tracing callbacks are very sensitive, when these commands
-  are registered, the trace point is activated, but disabled in
-  a "soft" mode. That is, the tracepoint will be called, but
-  just will not be traced. The event tracepoint stays in this mode
+  are registered, the tracepoints are activated, but disabled in
+  a "soft" mode. That is, the tracepoints will be called, but
+  just will not be traced. The event tracepoints stay in this mode
   as long as there's a command that triggers it.
 
    echo 'try_to_wake_up:enable_event:sched:sched_switch:2' > \
@@ -2422,8 +2422,10 @@ The following commands are supported:
     <function>:enable_event:<system>:<event>[:count]
     <function>:disable_event:<system>:<event>[:count]
 
-  To remove the events commands:
+  Note that the system and event accept wildcards for operating
+  multiple events at once.
 
+  To remove the events commands:
 
    echo '!try_to_wake_up:enable_event:sched:sched_switch:0' > \
    	 set_ftrace_filter
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 27963e2..1376bb4 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -1850,17 +1850,21 @@ __trace_add_event_dirs(struct trace_array *tr)
 #define DISABLE_EVENT_STR	"disable_event"
 
 struct event_probe_data {
-	struct ftrace_event_file	*file;
+	struct ftrace_event_file	**files;
+	char				*event;
+	char				*system;
 	unsigned long			count;
 	int				ref;
 	bool				enable;
 };
 
-static struct ftrace_event_file *
-find_event_file(struct trace_array *tr, const char *system,  const char *event)
+static int
+find_event_files(struct trace_array *tr, const char *system, const char *event,
+		 struct ftrace_event_file **files, int size)
 {
 	struct ftrace_event_file *file;
 	struct ftrace_event_call *call;
+	int nr = 0;
 
 	list_for_each_entry(file, &tr->events, list) {
 
@@ -1872,11 +1876,14 @@ find_event_file(struct trace_array *tr, const char *system,  const char *event)
 		if (call->flags & TRACE_EVENT_FL_IGNORE_ENABLE)
 			continue;
 
-		if (strcmp(event, call->name) == 0 &&
-		    strcmp(system, call->class->system) == 0)
-			return file;
+		if (strglobmatch(event, call->name) &&
+		    strglobmatch(system, call->class->system)) {
+			if (files && nr < size)
+				files[nr] = file;
+			nr++;
+		}
 	}
-	return NULL;
+	return nr;
 }
 
 static void
@@ -1884,14 +1891,24 @@ event_enable_probe(unsigned long ip, unsigned long parent_ip, void **_data)
 {
 	struct event_probe_data **pdata = (struct event_probe_data **)_data;
 	struct event_probe_data *data = *pdata;
+	struct ftrace_event_file **file;
 
 	if (!data)
 		return;
 
-	if (data->enable)
-		clear_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &data->file->flags);
-	else
-		set_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT, &data->file->flags);
+	file = data->files;
+	if (unlikely(!file))
+		return;
+
+	while (*file) {
+		if (data->enable)
+			clear_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT,
+				  &(*file)->flags);
+		else
+			set_bit(FTRACE_EVENT_FL_SOFT_DISABLED_BIT,
+				  &(*file)->flags);
+		file++;
+	}
 }
 
 static void
@@ -1906,10 +1923,6 @@ event_enable_count_probe(unsigned long ip, unsigned long parent_ip, void **_data
 	if (!data->count)
 		return;
 
-	/* Skip if the event is in a state we want to switch to */
-	if (data->enable == !(data->file->flags & FTRACE_EVENT_FL_SOFT_DISABLED))
-		return;
-
 	if (data->count != -1)
 		(data->count)--;
 
@@ -1926,8 +1939,7 @@ event_enable_print(struct seq_file *m, unsigned long ip,
 
 	seq_printf(m, "%s:%s:%s",
 		   data->enable ? ENABLE_EVENT_STR : DISABLE_EVENT_STR,
-		   data->file->event_call->class->system,
-		   data->file->event_call->name);
+		   data->system, data->event);
 
 	if (data->count == -1)
 		seq_printf(m, ":unlimited\n");
@@ -1948,6 +1960,40 @@ event_enable_init(struct ftrace_probe_ops *ops, unsigned long ip,
 	return 0;
 }
 
+static int event_files_soft_mode(struct ftrace_event_file **files, int enable)
+{
+	struct ftrace_event_file **file = files;
+
+	if (!file)
+		return -EINVAL;
+
+	while (*file) {
+		/* Don't let event modules unload while probe registered */
+		if (enable) {
+			if (!try_module_get((*file)->event_call->mod))
+				goto rollback;
+		}
+
+		__ftrace_event_enable_disable(*file, enable, 1);
+
+		if (!enable)
+			module_put((*file)->event_call->mod);
+
+		file++;
+	}
+
+	return 0;
+
+ rollback:
+	while (file != files) {
+		file--;
+		__ftrace_event_enable_disable(*file, 0, 1);
+		module_put((*file)->event_call->mod);
+	}
+
+	return -EBUSY;
+}
+
 static void
 event_enable_free(struct ftrace_probe_ops *ops, unsigned long ip,
 		  void **_data)
@@ -1960,9 +2006,11 @@ event_enable_free(struct ftrace_probe_ops *ops, unsigned long ip,
 
 	data->ref--;
 	if (!data->ref) {
-		/* Remove the SOFT_MODE flag */
-		__ftrace_event_enable_disable(data->file, 0, 1);
-		module_put(data->file->event_call->mod);
+		/* We don't need wait rcu because no one refers data here */
+		event_files_soft_mode(data->files, 0);
+		kfree(data->files);
+		kfree(data->event);
+		kfree(data->system);
 		kfree(data);
 	}
 	*pdata = NULL;
@@ -2001,13 +2049,13 @@ event_enable_func(struct ftrace_hash *hash,
 		  char *glob, char *cmd, char *param, int enabled)
 {
 	struct trace_array *tr = top_trace_array();
-	struct ftrace_event_file *file;
 	struct ftrace_probe_ops *ops;
 	struct event_probe_data *data;
 	const char *system;
 	const char *event;
 	char *number;
 	bool enable;
+	int nr_files;
 	int ret;
 
 	/* hash funcs only work with set_ftrace_filter */
@@ -2026,8 +2074,8 @@ event_enable_func(struct ftrace_hash *hash,
 	mutex_lock(&event_mutex);
 
 	ret = -EINVAL;
-	file = find_event_file(tr, system, event);
-	if (!file)
+	nr_files = find_event_files(tr, system, event, NULL, 0);
+	if (nr_files == 0)
 		goto out;
 
 	enable = strcmp(cmd, ENABLE_EVENT_STR) == 0;
@@ -2050,7 +2098,17 @@ event_enable_func(struct ftrace_hash *hash,
 
 	data->enable = enable;
 	data->count = -1;
-	data->file = file;
+	data->files = kzalloc((nr_files + 1) * sizeof(*data->files),
+			      GFP_KERNEL);
+	if (!data->files)
+		goto out_free;
+
+	find_event_files(tr, system, event, data->files, nr_files);
+
+	data->event = kstrdup(event, GFP_KERNEL);
+	data->system = kstrdup(system, GFP_KERNEL);
+	if (!data->event || !data->system)
+		goto out_free;
 
 	if (!param)
 		goto out_reg;
@@ -2070,16 +2128,10 @@ event_enable_func(struct ftrace_hash *hash,
 		goto out_free;
 
  out_reg:
-	/* Don't let event modules unload while probe registered */
-	ret = try_module_get(file->event_call->mod);
-	if (!ret) {
-		ret = -EBUSY;
+	ret = event_files_soft_mode(data->files, 1);
+	if (ret < 0)
 		goto out_free;
-	}
 
-	ret = __ftrace_event_enable_disable(file, 1, 1);
-	if (ret < 0)
-		goto out_put;
 	ret = register_ftrace_function_probe(glob, ops, data);
 	/*
 	 * The above returns on success the # of functions enabled,
@@ -2098,10 +2150,11 @@ event_enable_func(struct ftrace_hash *hash,
 	return ret;
 
  out_disable:
-	__ftrace_event_enable_disable(file, 0, 1);
- out_put:
-	module_put(file->event_call->mod);
+	event_files_soft_mode(data->files, 0);
  out_free:
+	kfree(data->files);
+	kfree(data->event);
+	kfree(data->system);
 	kfree(data);
 	goto out;
 }


      parent reply	other threads:[~2013-05-16 11:51 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-05-16 11:48 [PATCH 0/5] Add glob pattern matching support on trigger and kprobe-event Masami Hiramatsu
2013-05-16 11:48 ` [PATCH 1/5] [BUGFIX] tracing: Returns -EBUSY when event_enable_func fails to get module Masami Hiramatsu
2013-05-16 14:58   ` Steven Rostedt
2013-05-16 11:48 ` [PATCH 2/5] perf: Reorder parameters of strglobmatch Masami Hiramatsu
2013-05-16 14:55   ` Steven Rostedt
2013-05-17  2:21     ` Masami Hiramatsu
2013-05-21  9:19       ` Arnaldo Carvalho de Melo
2013-05-21  9:49         ` Masami Hiramatsu
2013-05-16 11:48 ` [PATCH 3/5] lib/string: Add a generic wildcard string matching function Masami Hiramatsu
2013-05-16 11:48 ` [PATCH 4/5] tracing/kprobes: Allow user to delete kprobe events by wild cards Masami Hiramatsu
2013-05-16 11:49 ` Masami Hiramatsu [this message]

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=20130516114900.13508.29247.stgit@mhiramat-M0-7522 \
    --to=masami.hiramatsu.pt@hitachi.com \
    --cc=fweisbec@gmail.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=oleg@redhat.com \
    --cc=rostedt@goodmis.org \
    --cc=srikar@linux.vnet.ibm.com \
    --cc=tom.zanussi@intel.com \
    --cc=yrl.pp-manager.tt@hitachi.com \
    --subject='Re: [PATCH 5/5] tracing: Support enable/disable multiple events trigger by wild cards' \
    /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

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.