[RFC] bpf: change bpf syacall to use u64 temp variables

Subsystems: bpf [core], bpf [general] (safe dynamic programs and tools), the rest

3 messages, 3 authors, 2015-10-19 · open the first message on its own page

[RFC] bpf: change bpf syacall to use u64 temp variables

From: yalin wang <hidden>
Date: 2015-10-19 07:10:58

This patch change map_lookup_elem() and map_update_elem() function
to use u64 temp variable if the key_size or value_size is less than
u64, we don't need use kmalloc() for these small variables.

Signed-off-by: yalin wang <redacted>
---
 kernel/bpf/syscall.c | 30 ++++++++++++++++++++----------
 1 file changed, 20 insertions(+), 10 deletions(-)
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index f640e5f..c82d7bf 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -189,7 +189,8 @@ static int map_lookup_elem(union bpf_attr *attr)
 	void __user *uvalue = u64_to_ptr(attr->value);
 	int ufd = attr->map_fd;
 	struct bpf_map *map;
-	void *key, *value, *ptr;
+	u64 key_buf, value_buf;
+	void *key = &key_buf, *value = &value_buf, *ptr;
 	struct fd f;
 	int err;
 
@@ -202,7 +203,8 @@ static int map_lookup_elem(union bpf_attr *attr)
 		return PTR_ERR(map);
 
 	err = -ENOMEM;
-	key = kmalloc(map->key_size, GFP_USER);
+	if (map->key_size > sizeof(u64))
+		key = kmalloc(map->key_size, GFP_USER);
 	if (!key)
 		goto err_put;
 
@@ -211,7 +213,8 @@ static int map_lookup_elem(union bpf_attr *attr)
 		goto free_key;
 
 	err = -ENOMEM;
-	value = kmalloc(map->value_size, GFP_USER);
+	if (map->value_size > sizeof(u64))
+		value = kmalloc(map->value_size, GFP_USER);
 	if (!value)
 		goto free_key;
 
@@ -232,9 +235,11 @@ static int map_lookup_elem(union bpf_attr *attr)
 	err = 0;
 
 free_value:
-	kfree(value);
+	if (value != &value_buf)
+		kfree(value);
 free_key:
-	kfree(key);
+	if (key != &key_buf)
+		kfree(key);
 err_put:
 	fdput(f);
 	return err;
@@ -248,7 +253,8 @@ static int map_update_elem(union bpf_attr *attr)
 	void __user *uvalue = u64_to_ptr(attr->value);
 	int ufd = attr->map_fd;
 	struct bpf_map *map;
-	void *key, *value;
+	u64 key_buf, value_buf;
+	void *key = &key_buf, *value = &value_buf;
 	struct fd f;
 	int err;
 
@@ -261,7 +267,8 @@ static int map_update_elem(union bpf_attr *attr)
 		return PTR_ERR(map);
 
 	err = -ENOMEM;
-	key = kmalloc(map->key_size, GFP_USER);
+	if (map->key_size > sizeof(u64))
+		key = kmalloc(map->key_size, GFP_USER);
 	if (!key)
 		goto err_put;
 
@@ -270,7 +277,8 @@ static int map_update_elem(union bpf_attr *attr)
 		goto free_key;
 
 	err = -ENOMEM;
-	value = kmalloc(map->value_size, GFP_USER);
+	if (map->value_size > sizeof(u64))
+		value = kmalloc(map->value_size, GFP_USER);
 	if (!value)
 		goto free_key;
 
@@ -286,9 +294,11 @@ static int map_update_elem(union bpf_attr *attr)
 	rcu_read_unlock();
 
 free_value:
-	kfree(value);
+	if (value != &value_buf)
+		kfree(value);
 free_key:
-	kfree(key);
+	if (key != &key_buf)
+		kfree(key);
 err_put:
 	fdput(f);
 	return err;
-- 
1.9.1

Re: [RFC] bpf: change bpf syacall to use u64 temp variables

From: Daniel Borkmann <daniel@iogearbox.net>
Date: 2015-10-19 08:55:28

On 10/19/2015 09:10 AM, yalin wang wrote:
This patch change map_lookup_elem() and map_update_elem() function
to use u64 temp variable if the key_size or value_size is less than
u64, we don't need use kmalloc() for these small variables.

Signed-off-by: yalin wang <redacted>
 From an application PoV that has to make the bpf(2) syscall, how
much do we actually gain from this? I'm curious, did you perform
some benchmarks that show a noticeable difference?

Re: [RFC] bpf: change bpf syacall to use u64 temp variables

From: Alexei Starovoitov <hidden>
Date: 2015-10-19 19:08:39

On Mon, Oct 19, 2015 at 03:10:46PM +0800, yalin wang wrote:
quoted hunk
This patch change map_lookup_elem() and map_update_elem() function
to use u64 temp variable if the key_size or value_size is less than
u64, we don't need use kmalloc() for these small variables.

Signed-off-by: yalin wang <redacted>
---
 kernel/bpf/syscall.c | 30 ++++++++++++++++++++----------
 1 file changed, 20 insertions(+), 10 deletions(-)
diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index f640e5f..c82d7bf 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -189,7 +189,8 @@ static int map_lookup_elem(union bpf_attr *attr)
 	void __user *uvalue = u64_to_ptr(attr->value);
 	int ufd = attr->map_fd;
 	struct bpf_map *map;
-	void *key, *value, *ptr;
+	u64 key_buf, value_buf;
+	void *key = &key_buf, *value = &value_buf, *ptr;
 	struct fd f;
 	int err;
 
@@ -202,7 +203,8 @@ static int map_lookup_elem(union bpf_attr *attr)
 		return PTR_ERR(map);
 
 	err = -ENOMEM;
-	key = kmalloc(map->key_size, GFP_USER);
+	if (map->key_size > sizeof(u64))
+		key = kmalloc(map->key_size, GFP_USER);
I think it's a good optimization for common case.
Performance numbers would be good to prove the point.
Thanks
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help