mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Tom Zanussi <tom.zanussi@linux.intel.com>
To: rostedt@goodmis.org
Cc: masami.hiramatsu.pt@hitachi.com, namhyung@kernel.org,
	andi@firstfloor.org, ast@plumgrid.com,
	linux-kernel@vger.kernel.org,
	Tom Zanussi <tom.zanussi@linux.intel.com>
Subject: [PATCH 04/15] bpf: Export bpf map functionality as trace_map_*
Date: Mon,  2 Mar 2015 10:00:57 -0600	[thread overview]
Message-ID: <f6ba33aaee9137cee7930abea99cf7cea8104d01.1425310176.git.tom.zanussi@linux.intel.com> (raw)
In-Reply-To: <cover.1425310176.git.tom.zanussi@linux.intel.com>
In-Reply-To: <cover.1425310176.git.tom.zanussi@linux.intel.com>

Make the bpf map implementation available outside of kernel/bpf - as a
general-purpose map implementation for tracing, it should be available
to any tracing facility that can make use of it, not just the bpf
syscall.

Create a set of exported tracing_map_* functions and have the bpf
implementation use them.

Signed-off-by: Tom Zanussi <tom.zanussi@linux.intel.com>
---
 include/linux/bpf.h  |   7 +++
 kernel/bpf/syscall.c | 173 ++++++++++++++++++++++++++++++++++++++++++++++-----
 2 files changed, 163 insertions(+), 17 deletions(-)

diff --git a/include/linux/bpf.h b/include/linux/bpf.h
index bbfceb7..900405bf 100644
--- a/include/linux/bpf.h
+++ b/include/linux/bpf.h
@@ -142,4 +142,11 @@ extern struct bpf_func_proto bpf_map_lookup_elem_proto;
 extern struct bpf_func_proto bpf_map_update_elem_proto;
 extern struct bpf_func_proto bpf_map_delete_elem_proto;
 
+struct bpf_map *tracing_map_create(union bpf_attr *attr);
+void tracing_map_destroy(struct bpf_map *map);
+int tracing_map_update_elem(struct bpf_map *map, void *key, void *value,
+			    union bpf_attr *attr);
+int tracing_map_lookup_elem(struct bpf_map *map, void *key, void *uvalue);
+int tracing_map_delete_elem(struct bpf_map *map, void *key);
+int tracing_map_get_next_key(struct bpf_map *map, void *key, void *next_key);
 #endif /* _LINUX_BPF_H */
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 088ac0b..cac8df6 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -63,11 +63,24 @@ void bpf_map_put(struct bpf_map *map)
 	}
 }
 
+/**
+ * tracing_map_destroy - destroy (release) a bpf_map instance
+ * @map: The bpf_map to destroy
+ *
+ * Release a bpf_map.  This decrements the map's refcount and
+ * schedules it for deletion.  For all intents and purposes, the user
+ * can assume the map has been deleted after this call.
+ */
+void tracing_map_destroy(struct bpf_map *map)
+{
+	bpf_map_put(map);
+}
+
 static int bpf_map_release(struct inode *inode, struct file *filp)
 {
 	struct bpf_map *map = filp->private_data;
 
-	bpf_map_put(map);
+	tracing_map_destroy(map);
 	return 0;
 }
 
@@ -84,6 +97,32 @@ static const struct file_operations bpf_map_fops = {
 		   sizeof(attr->CMD##_LAST_FIELD)) != NULL
 
 #define BPF_MAP_CREATE_LAST_FIELD max_entries
+
+/**
+ * tracing_map_create - Create a bpf_map instance
+ * @attr: The bpf_attr for the operation
+ *
+ * Create a bpf_map of the type specified by attr.
+ *
+ * Note that it's assumed that unused attr fields have been zeroed and
+ * that kernel code can be trusted to have done so before calling this
+ * function.
+ *
+ * Return: the map created on success, ERR_PTR otherwise
+ */
+struct bpf_map *tracing_map_create(union bpf_attr *attr)
+{
+	struct bpf_map *map;
+
+	/* find map type and init map: hashtable vs rbtree vs bloom vs ... */
+	map = find_and_alloc_map(attr);
+	if (!IS_ERR(map))
+		atomic_set(&map->refcnt, 1);
+
+	return map;
+}
+EXPORT_SYMBOL_GPL(tracing_map_create);
+
 /* called via syscall */
 static int map_create(union bpf_attr *attr)
 {
@@ -94,13 +133,10 @@ static int map_create(union bpf_attr *attr)
 	if (err)
 		return -EINVAL;
 
-	/* find map type and init map: hashtable vs rbtree vs bloom vs ... */
-	map = find_and_alloc_map(attr);
+	map = tracing_map_create(attr);
 	if (IS_ERR(map))
 		return PTR_ERR(map);
 
-	atomic_set(&map->refcnt, 1);
-
 	err = anon_inode_getfd("bpf-map", &bpf_map_fops, map, O_RDWR | O_CLOEXEC);
 
 	if (err < 0)
@@ -140,6 +176,40 @@ static void __user *u64_to_ptr(__u64 val)
 	return (void __user *) (unsigned long) val;
 }
 
+/**
+ * tracing_map_lookup_elem - Perform a bpf_map lookup
+ * @map: The bpf_map to perform the lookup on
+ * @key: The key to look up
+ * @uvalue: The caller-owned memory to be filled in with the found value
+ *
+ * Look up the specified key in the bpf_map and if found copy the
+ * value into the uvalue specified by the caller.  The uvalue must be
+ * at least as large as the map->value_size.
+ *
+ * Return: 0 on success, -ENOENT if key not found
+ */
+int tracing_map_lookup_elem(struct bpf_map *map, void *key, void *uvalue)
+{
+	int err = -ENOENT;
+	void *value;
+
+	rcu_read_lock();
+
+	value = map->ops->map_lookup_elem(map, key);
+	if (!value)
+		goto err_unlock;
+
+	memcpy(uvalue, value, map->value_size);
+
+	err = 0;
+
+err_unlock:
+	rcu_read_unlock();
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(tracing_map_lookup_elem);
+
 /* last field in 'union bpf_attr' used by this command */
 #define BPF_MAP_LOOKUP_ELEM_LAST_FIELD value
 
@@ -190,6 +260,39 @@ err_put:
 	return err;
 }
 
+/**
+ * tracing_map_update_elem - Update or add a bpf_map element
+ * @map: The bpf_map to perform the lookup on
+ * @key: The key to update or add
+ * @value: The value to update or add
+ * @attr: The bpf_attr for the operation
+ *
+ * Update or add a value for the specified key in the bpf_map.  Both
+ * the key and value are user-owned memory, copies of which will be
+ * added to the map.
+ *
+ * Note that it's assumed that unused attr fields have been zeroed and
+ * that kernel code can be trusted to have done so before calling this
+ * function.
+ *
+ * Return: 0 on success, errno otherwise
+ */
+int tracing_map_update_elem(struct bpf_map *map, void *key, void *value,
+			    union bpf_attr *attr)
+{
+	int err;
+
+	/* eBPF program that use maps are running under rcu_read_lock(),
+	 * therefore all map accessors rely on this fact, so do the same here
+	 */
+	rcu_read_lock();
+	err = map->ops->map_update_elem(map, key, value, attr->flags);
+	rcu_read_unlock();
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(tracing_map_update_elem);
+
 #define BPF_MAP_UPDATE_ELEM_LAST_FIELD flags
 
 static int map_update_elem(union bpf_attr *attr)
@@ -227,12 +330,7 @@ static int map_update_elem(union bpf_attr *attr)
 	if (copy_from_user(value, uvalue, map->value_size) != 0)
 		goto free_value;
 
-	/* eBPF program that use maps are running under rcu_read_lock(),
-	 * therefore all map accessors rely on this fact, so do the same here
-	 */
-	rcu_read_lock();
-	err = map->ops->map_update_elem(map, key, value, attr->flags);
-	rcu_read_unlock();
+	err = tracing_map_update_elem(map, key, value, attr);
 
 free_value:
 	kfree(value);
@@ -243,6 +341,27 @@ err_put:
 	return err;
 }
 
+/**
+ * tracing_map_delete_elem - Delete an element from a bpf_map
+ * @map: The bpf_map to perform the lookup on
+ * @key: The key to delete
+ *
+ * Delete the bpf_map element with the specified key.
+ *
+ * Return: 0 on success, -ENOENT if key not found
+ */
+int tracing_map_delete_elem(struct bpf_map *map, void *key)
+{
+	int err;
+
+	rcu_read_lock();
+	err = map->ops->map_delete_elem(map, key);
+	rcu_read_unlock();
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(tracing_map_delete_elem);
+
 #define BPF_MAP_DELETE_ELEM_LAST_FIELD key
 
 static int map_delete_elem(union bpf_attr *attr)
@@ -270,9 +389,7 @@ static int map_delete_elem(union bpf_attr *attr)
 	if (copy_from_user(key, ukey, map->key_size) != 0)
 		goto free_key;
 
-	rcu_read_lock();
-	err = map->ops->map_delete_elem(map, key);
-	rcu_read_unlock();
+	err = tracing_map_delete_elem(map, key);
 
 free_key:
 	kfree(key);
@@ -281,6 +398,30 @@ err_put:
 	return err;
 }
 
+/**
+ * tracing_map_get_next_key - Get the next key in the bpf_map
+ * @map: The bpf_map to perform the lookup on
+ * @key: The key to look up
+ * @next_key: The caller-owned memory to be filled in with the next key
+ *
+ * Look up the specified key in the bpf_map and if found copy the next
+ * key into the next_key specified by the caller.  If the key isn't
+ * found, just copy in the first key found.
+ *
+ * Return: 0 on success, -ENOENT if the map is empty
+ */
+int tracing_map_get_next_key(struct bpf_map *map, void *key, void *next_key)
+{
+	int err;
+
+	rcu_read_lock();
+	err = map->ops->map_get_next_key(map, key, next_key);
+	rcu_read_unlock();
+
+	return err;
+}
+EXPORT_SYMBOL_GPL(tracing_map_get_next_key);
+
 /* last field in 'union bpf_attr' used by this command */
 #define BPF_MAP_GET_NEXT_KEY_LAST_FIELD next_key
 
@@ -315,9 +456,7 @@ static int map_get_next_key(union bpf_attr *attr)
 	if (!next_key)
 		goto free_key;
 
-	rcu_read_lock();
-	err = map->ops->map_get_next_key(map, key, next_key);
-	rcu_read_unlock();
+	err = tracing_map_get_next_key(map, key, next_key);
 	if (err)
 		goto free_next_key;
 
-- 
1.9.3


  parent reply	other threads:[~2015-03-02 16:01 UTC|newest]

Thread overview: 25+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-03-02 16:00 [PATCH v2 00/15] tracing: 'hist' triggers Tom Zanussi
2015-03-02 16:00 ` [PATCH 01/15] tracing: Make ftrace_event_field checking functions available Tom Zanussi
2015-03-02 16:00 ` [PATCH 02/15] tracing: Add event record param to trigger_ops.func() Tom Zanussi
2015-03-02 16:00 ` [PATCH 03/15] tracing: Add get_syscall_name() Tom Zanussi
2015-03-02 16:00 ` Tom Zanussi [this message]
2015-03-02 16:00 ` [PATCH 05/15] bpf: Export a map-clearing function Tom Zanussi
2015-03-02 16:00 ` [PATCH 06/15] bpf: Add tracing_map client ops Tom Zanussi
2015-03-02 16:01 ` [PATCH 07/15] mm: Add ___GFP_NOTRACE Tom Zanussi
2015-03-02 16:37   ` Steven Rostedt
2015-03-02 16:46     ` Tom Zanussi
2015-03-02 17:58       ` Alexei Starovoitov
2015-03-02 18:03         ` Tom Zanussi
2015-03-02 18:12           ` Alexei Starovoitov
2015-03-02 18:25             ` Tom Zanussi
2015-03-02 18:43             ` Steven Rostedt
2015-03-02 16:01 ` [PATCH 08/15] tracing: Make kmem memory allocation tracepoints conditional Tom Zanussi
2015-03-02 16:01 ` [PATCH 09/15] tracing: Add kmalloc/kfree macros Tom Zanussi
2015-03-02 16:01 ` [PATCH 10/15] bpf: Make tracing_map use kmalloc/kfree_notrace() Tom Zanussi
2015-03-02 16:01 ` [PATCH 11/15] tracing: Add a per-event-trigger 'paused' field Tom Zanussi
2015-03-02 16:01 ` [PATCH 12/15] tracing: Add 'hist' event trigger command Tom Zanussi
2015-03-02 16:01 ` [PATCH 13/15] tracing: Add sorting to hist triggers Tom Zanussi
2015-03-02 16:01 ` [PATCH 14/15] tracing: Add enable_hist/disable_hist triggers Tom Zanussi
2015-03-02 16:01 ` [PATCH 15/15] tracing: Add 'hist' trigger Documentation Tom Zanussi
2015-03-03  2:25 ` [PATCH v2 00/15] tracing: 'hist' triggers Masami Hiramatsu
2015-03-03 14:47   ` Tom Zanussi

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=f6ba33aaee9137cee7930abea99cf7cea8104d01.1425310176.git.tom.zanussi@linux.intel.com \
    --to=tom.zanussi@linux.intel.com \
    --cc=andi@firstfloor.org \
    --cc=ast@plumgrid.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=masami.hiramatsu.pt@hitachi.com \
    --cc=namhyung@kernel.org \
    --cc=rostedt@goodmis.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®