All of lore.kernel.org
 help / color / mirror / Atom feed
From: Steven Rostedt <rostedt@goodmis.org>
To: linux-kernel@vger.kernel.org
Cc: Ingo Molnar <mingo@kernel.org>,
	Andrew Morton <akpm@linux-foundation.org>
Subject: [for-next][PATCH 14/33] ftrace: Added ftrace_func_mapper for function probe triggers
Date: Fri, 21 Apr 2017 17:30:34 -0400	[thread overview]
Message-ID: <20170421213330.078739079@goodmis.org> (raw)
In-Reply-To: 20170421213020.875637678@goodmis.org

[-- Attachment #1: 0014-ftrace-Added-ftrace_func_mapper-for-function-probe-t.patch --]
[-- Type: text/plain, Size: 10004 bytes --]

From: "Steven Rostedt (VMware)" <rostedt@goodmis.org>

In order to move the ops to the function probes directly, they need a way to
map function ips to their own data without depending on the infrastructure
of the function probes, as the data field will be going away.

New helper functions are added that are based on the ftrace_hash code.
ftrace_func_mapper functions are there to let the probes map ips to their
data. These can be allocated by the probe ops, and referenced in the
function callbacks.

Signed-off-by: Steven Rostedt (VMware) <rostedt@goodmis.org>
---
 kernel/trace/ftrace.c       | 141 ++++++++++++++++++++++++++++++++++++++++++++
 kernel/trace/trace.h        |  14 +++++
 kernel/trace/trace_events.c |  70 +++++++++++++++++-----
 3 files changed, 210 insertions(+), 15 deletions(-)

diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index d8873079bed4..ac47d1845fdb 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -3808,6 +3808,147 @@ static void ftrace_free_entry(struct ftrace_func_probe *entry)
 	kfree(entry);
 }
 
+struct ftrace_func_map {
+	struct ftrace_func_entry	entry;
+	void				*data;
+};
+
+struct ftrace_func_mapper {
+	struct ftrace_hash		hash;
+};
+
+/**
+ * allocate_ftrace_func_mapper - allocate a new ftrace_func_mapper
+ *
+ * Returns a ftrace_func_mapper descriptor that can be used to map ips to data.
+ */
+struct ftrace_func_mapper *allocate_ftrace_func_mapper(void)
+{
+	struct ftrace_hash *hash;
+
+	/*
+	 * The mapper is simply a ftrace_hash, but since the entries
+	 * in the hash are not ftrace_func_entry type, we define it
+	 * as a separate structure.
+	 */
+	hash = alloc_ftrace_hash(FTRACE_HASH_DEFAULT_BITS);
+	return (struct ftrace_func_mapper *)hash;
+}
+
+/**
+ * ftrace_func_mapper_find_ip - Find some data mapped to an ip
+ * @mapper: The mapper that has the ip maps
+ * @ip: the instruction pointer to find the data for
+ *
+ * Returns the data mapped to @ip if found otherwise NULL. The return
+ * is actually the address of the mapper data pointer. The address is
+ * returned for use cases where the data is no bigger than a long, and
+ * the user can use the data pointer as its data instead of having to
+ * allocate more memory for the reference.
+ */
+void **ftrace_func_mapper_find_ip(struct ftrace_func_mapper *mapper,
+				  unsigned long ip)
+{
+	struct ftrace_func_entry *entry;
+	struct ftrace_func_map *map;
+
+	entry = ftrace_lookup_ip(&mapper->hash, ip);
+	if (!entry)
+		return NULL;
+
+	map = (struct ftrace_func_map *)entry;
+	return &map->data;
+}
+
+/**
+ * ftrace_func_mapper_add_ip - Map some data to an ip
+ * @mapper: The mapper that has the ip maps
+ * @ip: The instruction pointer address to map @data to
+ * @data: The data to map to @ip
+ *
+ * Returns 0 on succes otherwise an error.
+ */
+int ftrace_func_mapper_add_ip(struct ftrace_func_mapper *mapper,
+			      unsigned long ip, void *data)
+{
+	struct ftrace_func_entry *entry;
+	struct ftrace_func_map *map;
+
+	entry = ftrace_lookup_ip(&mapper->hash, ip);
+	if (entry)
+		return -EBUSY;
+
+	map = kmalloc(sizeof(*map), GFP_KERNEL);
+	if (!map)
+		return -ENOMEM;
+
+	map->entry.ip = ip;
+	map->data = data;
+
+	__add_hash_entry(&mapper->hash, &map->entry);
+
+	return 0;
+}
+
+/**
+ * ftrace_func_mapper_remove_ip - Remove an ip from the mapping
+ * @mapper: The mapper that has the ip maps
+ * @ip: The instruction pointer address to remove the data from
+ *
+ * Returns the data if it is found, otherwise NULL.
+ * Note, if the data pointer is used as the data itself, (see 
+ * ftrace_func_mapper_find_ip(), then the return value may be meaningless,
+ * if the data pointer was set to zero.
+ */
+void *ftrace_func_mapper_remove_ip(struct ftrace_func_mapper *mapper,
+				   unsigned long ip)
+{
+	struct ftrace_func_entry *entry;
+	struct ftrace_func_map *map;
+	void *data;
+
+	entry = ftrace_lookup_ip(&mapper->hash, ip);
+	if (!entry)
+		return NULL;
+
+	map = (struct ftrace_func_map *)entry;
+	data = map->data;
+
+	remove_hash_entry(&mapper->hash, entry);
+	kfree(entry);
+
+	return data;
+}
+
+/**
+ * free_ftrace_func_mapper - free a mapping of ips and data
+ * @mapper: The mapper that has the ip maps
+ * @free_func: A function to be called on each data item.
+ *
+ * This is used to free the function mapper. The @free_func is optional
+ * and can be used if the data needs to be freed as well.
+ */
+void free_ftrace_func_mapper(struct ftrace_func_mapper *mapper,
+			     ftrace_mapper_func free_func)
+{
+	struct ftrace_func_entry *entry;
+	struct ftrace_func_map *map;
+	struct hlist_head *hhd;
+	int size = 1 << mapper->hash.size_bits;
+	int i;
+
+	if (free_func && mapper->hash.count) {
+		for (i = 0; i < size; i++) {
+			hhd = &mapper->hash.buckets[i];
+			hlist_for_each_entry(entry, hhd, hlist) {
+				map = (struct ftrace_func_map *)entry;
+				free_func(map);
+			}
+		}
+	}
+	free_ftrace_hash(&mapper->hash);
+}
+
 int
 register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
 			      void *data)
diff --git a/kernel/trace/trace.h b/kernel/trace/trace.h
index 0f915c264c19..dbbdee21bcc4 100644
--- a/kernel/trace/trace.h
+++ b/kernel/trace/trace.h
@@ -944,8 +944,22 @@ struct ftrace_probe_ops {
 					 unsigned long ip,
 					 struct ftrace_probe_ops *ops,
 					 void *data);
+	void			*private_data;
 };
 
+struct ftrace_func_mapper;
+typedef int (*ftrace_mapper_func)(void *data);
+
+struct ftrace_func_mapper *allocate_ftrace_func_mapper(void);
+void **ftrace_func_mapper_find_ip(struct ftrace_func_mapper *mapper,
+					   unsigned long ip);
+int ftrace_func_mapper_add_ip(struct ftrace_func_mapper *mapper,
+			       unsigned long ip, void *data);
+void *ftrace_func_mapper_remove_ip(struct ftrace_func_mapper *mapper,
+				   unsigned long ip);
+void free_ftrace_func_mapper(struct ftrace_func_mapper *mapper,
+			     ftrace_mapper_func free_func);
+
 extern int
 register_ftrace_function_probe(char *glob, struct ftrace_probe_ops *ops,
 			      void *data);
diff --git a/kernel/trace/trace_events.c b/kernel/trace/trace_events.c
index 9dbac1881b03..ee308312fe87 100644
--- a/kernel/trace/trace_events.c
+++ b/kernel/trace/trace_events.c
@@ -2460,32 +2460,44 @@ struct event_probe_data {
 	bool				enable;
 };
 
+static void update_event_probe(struct event_probe_data *data)
+{
+	if (data->enable)
+		clear_bit(EVENT_FILE_FL_SOFT_DISABLED_BIT, &data->file->flags);
+	else
+		set_bit(EVENT_FILE_FL_SOFT_DISABLED_BIT, &data->file->flags);
+}
+
 static void
 event_enable_probe(unsigned long ip, unsigned long parent_ip,
 		   struct ftrace_probe_ops *ops, void **_data)
 {
-	struct event_probe_data **pdata = (struct event_probe_data **)_data;
-	struct event_probe_data *data = *pdata;
+	struct ftrace_func_mapper *mapper = ops->private_data;
+	struct event_probe_data *data;
+	void **pdata;
 
-	if (!data)
+	pdata = ftrace_func_mapper_find_ip(mapper, ip);
+	if (!pdata || !*pdata)
 		return;
 
-	if (data->enable)
-		clear_bit(EVENT_FILE_FL_SOFT_DISABLED_BIT, &data->file->flags);
-	else
-		set_bit(EVENT_FILE_FL_SOFT_DISABLED_BIT, &data->file->flags);
+	data = *pdata;
+	update_event_probe(data);
 }
 
 static void
 event_enable_count_probe(unsigned long ip, unsigned long parent_ip,
 			 struct ftrace_probe_ops *ops, void **_data)
 {
-	struct event_probe_data **pdata = (struct event_probe_data **)_data;
-	struct event_probe_data *data = *pdata;
+	struct ftrace_func_mapper *mapper = ops->private_data;
+	struct event_probe_data *data;
+	void **pdata;
 
-	if (!data)
+	pdata = ftrace_func_mapper_find_ip(mapper, ip);
+	if (!pdata || !*pdata)
 		return;
 
+	data = *pdata;
+
 	if (!data->count)
 		return;
 
@@ -2496,14 +2508,23 @@ event_enable_count_probe(unsigned long ip, unsigned long parent_ip,
 	if (data->count != -1)
 		(data->count)--;
 
-	event_enable_probe(ip, parent_ip, ops, _data);
+	update_event_probe(data);
 }
 
 static int
 event_enable_print(struct seq_file *m, unsigned long ip,
 		      struct ftrace_probe_ops *ops, void *_data)
 {
-	struct event_probe_data *data = _data;
+	struct ftrace_func_mapper *mapper = ops->private_data;
+	struct event_probe_data *data;
+	void **pdata;
+
+	pdata = ftrace_func_mapper_find_ip(mapper, ip);
+
+	if (WARN_ON_ONCE(!pdata || !*pdata))
+		return 0;
+
+	data = *pdata;
 
 	seq_printf(m, "%ps:", (void *)ip);
 
@@ -2524,10 +2545,17 @@ static int
 event_enable_init(struct ftrace_probe_ops *ops, unsigned long ip,
 		  void **_data)
 {
+	struct ftrace_func_mapper *mapper = ops->private_data;
 	struct event_probe_data **pdata = (struct event_probe_data **)_data;
 	struct event_probe_data *data = *pdata;
+	int ret;
+
+	ret = ftrace_func_mapper_add_ip(mapper, ip, data);
+	if (ret < 0)
+		return ret;
 
 	data->ref++;
+
 	return 0;
 }
 
@@ -2535,8 +2563,13 @@ static void
 event_enable_free(struct ftrace_probe_ops *ops, unsigned long ip,
 		  void **_data)
 {
-	struct event_probe_data **pdata = (struct event_probe_data **)_data;
-	struct event_probe_data *data = *pdata;
+	struct ftrace_func_mapper *mapper = ops->private_data;
+	struct event_probe_data *data;
+
+	data = ftrace_func_mapper_remove_ip(mapper, ip);
+
+	if (WARN_ON_ONCE(!data))
+		return;
 
 	if (WARN_ON_ONCE(data->ref <= 0))
 		return;
@@ -2548,7 +2581,6 @@ event_enable_free(struct ftrace_probe_ops *ops, unsigned long ip,
 		module_put(data->file->event_call->mod);
 		kfree(data);
 	}
-	*pdata = NULL;
 }
 
 static struct ftrace_probe_ops event_enable_probe_ops = {
@@ -2627,6 +2659,13 @@ event_enable_func(struct ftrace_hash *hash,
 	}
 
 	ret = -ENOMEM;
+
+	if (!ops->private_data) {
+		ops->private_data = allocate_ftrace_func_mapper();
+		if (!ops->private_data)
+			goto out;
+	}
+
 	data = kzalloc(sizeof(*data), GFP_KERNEL);
 	if (!data)
 		goto out;
@@ -2663,6 +2702,7 @@ event_enable_func(struct ftrace_hash *hash,
 	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,
-- 
2.10.2

  parent reply	other threads:[~2017-04-21 21:37 UTC|newest]

Thread overview: 36+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-04-21 21:30 [for-next][PATCH 00/33] tracing: More updates for 4.12 Steven Rostedt
2017-04-21 21:30 ` [for-next][PATCH 01/33] ftrace: Fix removing of second function probe Steven Rostedt
2017-04-21 21:30 ` [for-next][PATCH 02/33] ftrace: Fix indexing of t_hash_start() from t_next() Steven Rostedt
2017-04-21 21:30 ` [for-next][PATCH 03/33] tracing: Have the trace_event benchmark thread call cond_resched_rcu_qs() Steven Rostedt
2017-04-21 21:30 ` [for-next][PATCH 04/33] ftrace: Add function-fork trace option Steven Rostedt
2017-04-21 21:30 ` [for-next][PATCH 05/33] selftests: ftrace: Add -l/--logdir option Steven Rostedt
2017-04-21 21:30 ` [for-next][PATCH 06/33] selftests: ftrace: Add a way to reset triggers in the set_ftrace_filter file Steven Rostedt
2017-04-21 21:30 ` [for-next][PATCH 07/33] selftests: ftrace: Add a selftest to test event enable/disable func trigger Steven Rostedt
2017-04-21 21:30 ` [for-next][PATCH 08/33] selftests: ftrace: Add a test to test function triggers to start and stop tracing Steven Rostedt
2017-04-21 21:30 ` [for-next][PATCH 09/33] selftests: ftrace: Add test to test reading of set_ftrace_file Steven Rostedt
2017-05-22  3:23   ` Masami Hiramatsu
2017-05-26 15:02     ` Steven Rostedt
2017-04-21 21:30 ` [for-next][PATCH 10/33] ftrace: Move the probe function into the tracing directory Steven Rostedt
2017-04-21 21:30 ` [for-next][PATCH 11/33] ftrace: Move the function commands " Steven Rostedt
2017-04-21 21:30 ` [for-next][PATCH 12/33] ftrace: Remove unused "flags" field from struct ftrace_func_probe Steven Rostedt
2017-04-21 21:30 ` [for-next][PATCH 13/33] ftrace: Pass probe ops to probe function Steven Rostedt
2017-04-21 21:30 ` Steven Rostedt [this message]
2017-04-21 21:30 ` [for-next][PATCH 15/33] tracing: Have the snapshot trigger use the mapping helper functions Steven Rostedt
2017-04-21 21:30 ` [for-next][PATCH 16/33] ftrace: Convert the rest of the function trigger over to the mapping functions Steven Rostedt
2017-04-21 21:30 ` [for-next][PATCH 17/33] ftrace: Remove unused unregister_ftrace_function_probe() function Steven Rostedt
2017-04-21 21:30 ` [for-next][PATCH 18/33] ftrace: Remove unused unregister_ftrace_function_probe_all() function Steven Rostedt
2017-04-21 21:30 ` [for-next][PATCH 19/33] ftrace: Remove printing of data in showing of a function probe Steven Rostedt
2017-04-21 21:30 ` [for-next][PATCH 20/33] ftrace: Remove data field from ftrace_func_probe structure Steven Rostedt
2017-04-21 21:30 ` [for-next][PATCH 21/33] ftrace: Add helper function ftrace_hash_move_and_update_ops() Steven Rostedt
2017-04-21 21:30 ` [for-next][PATCH 22/33] ftrace: Have unregister_ftrace_function_probe_func() return a value Steven Rostedt
2017-04-21 21:30 ` [for-next][PATCH 23/33] ftrace: Have each function probe use its own ftrace_ops Steven Rostedt
2017-04-21 21:30 ` [for-next][PATCH 24/33] ftrace: Have the function probes call their own function Steven Rostedt
2017-04-21 21:30 ` [for-next][PATCH 25/33] ftrace: If the hash for a probe fails to update then free what was initialized Steven Rostedt
2017-04-21 21:30 ` [for-next][PATCH 26/33] tracing: Have the trace_array hold the list of registered func probes Steven Rostedt
2017-04-21 21:30 ` [for-next][PATCH 27/33] tracing: Pass the trace_array into ftrace_probe_ops functions Steven Rostedt
2017-04-21 21:30 ` [for-next][PATCH 28/33] ftrace: Dynamically create the probe ftrace_ops for the trace_array Steven Rostedt
2017-04-21 21:30 ` [for-next][PATCH 29/33] tracing/ftrace: Add a better way to pass data via the probe functions Steven Rostedt
2017-04-21 21:30 ` [for-next][PATCH 30/33] tracing/ftrace: Allow instances to have their own function probes Steven Rostedt
2017-04-21 21:30 ` [for-next][PATCH 31/33] tracing/ftrace: Enable snapshot function trigger to work with instances Steven Rostedt
2017-04-21 21:30 ` [for-next][PATCH 32/33] tracing/ftrace: Allow for the traceonoff probe be unique to instances Steven Rostedt
2017-04-21 21:30 ` [for-next][PATCH 33/33] tracing/ftrace: Allow for instances to trigger their own stacktrace probes Steven Rostedt

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=20170421213330.078739079@goodmis.org \
    --to=rostedt@goodmis.org \
    --cc=akpm@linux-foundation.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@kernel.org \
    /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.