Refactor function map_update_elem() by creating a
helper function bpf_map_update_elem() which will be
used later by batched map update operation.

Also reuse function bpf_map_value_size()
in map_update_elem().

Signed-off-by: Yonghong Song <y...@fb.com>
---
 kernel/bpf/syscall.c | 113 ++++++++++++++++++++++---------------------
 1 file changed, 57 insertions(+), 56 deletions(-)

diff --git a/kernel/bpf/syscall.c b/kernel/bpf/syscall.c
index 211e0bc667bd..3caa0ab3d30d 100644
--- a/kernel/bpf/syscall.c
+++ b/kernel/bpf/syscall.c
@@ -878,6 +878,61 @@ static void maybe_wait_bpf_programs(struct bpf_map *map)
                synchronize_rcu();
 }
 
+static int bpf_map_update_elem(struct bpf_map *map, void *key, void *value,
+                              struct fd *f, __u64 flags) {
+       int err;
+
+       /* Need to create a kthread, thus must support schedule */
+       if (bpf_map_is_dev_bound(map)) {
+               return bpf_map_offload_update_elem(map, key, value, flags);
+       } else if (map->map_type == BPF_MAP_TYPE_CPUMAP ||
+                  map->map_type == BPF_MAP_TYPE_SOCKHASH ||
+                  map->map_type == BPF_MAP_TYPE_SOCKMAP) {
+               return map->ops->map_update_elem(map, key, value, flags);
+       }
+
+       /* must increment bpf_prog_active to avoid kprobe+bpf triggering from
+        * inside bpf map update or delete otherwise deadlocks are possible
+        */
+       preempt_disable();
+       __this_cpu_inc(bpf_prog_active);
+       if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
+           map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) {
+               err = bpf_percpu_hash_update(map, key, value, flags);
+       } else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) {
+               err = bpf_percpu_array_update(map, key, value, flags);
+       } else if (map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE) {
+               err = bpf_percpu_cgroup_storage_update(map, key, value,
+                                                      flags);
+       } else if (IS_FD_ARRAY(map)) {
+               rcu_read_lock();
+               err = bpf_fd_array_map_update_elem(map, f->file, key, value,
+                                                  flags);
+               rcu_read_unlock();
+       } else if (map->map_type == BPF_MAP_TYPE_HASH_OF_MAPS) {
+               rcu_read_lock();
+               err = bpf_fd_htab_map_update_elem(map, f->file, key, value,
+                                                 flags);
+               rcu_read_unlock();
+       } else if (map->map_type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY) {
+               /* rcu_read_lock() is not needed */
+               err = bpf_fd_reuseport_array_update_elem(map, key, value,
+                                                        flags);
+       } else if (map->map_type == BPF_MAP_TYPE_QUEUE ||
+                  map->map_type == BPF_MAP_TYPE_STACK) {
+               err = map->ops->map_push_elem(map, value, flags);
+       } else {
+               rcu_read_lock();
+               err = map->ops->map_update_elem(map, key, value, flags);
+               rcu_read_unlock();
+       }
+       __this_cpu_dec(bpf_prog_active);
+       preempt_enable();
+       maybe_wait_bpf_programs(map);
+
+       return err;
+}
+
 #define BPF_MAP_UPDATE_ELEM_LAST_FIELD flags
 
 static int map_update_elem(union bpf_attr *attr)
@@ -915,13 +970,7 @@ static int map_update_elem(union bpf_attr *attr)
                goto err_put;
        }
 
-       if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
-           map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
-           map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY ||
-           map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE)
-               value_size = round_up(map->value_size, 8) * num_possible_cpus();
-       else
-               value_size = map->value_size;
+       value_size = bpf_map_value_size(map);
 
        err = -ENOMEM;
        value = kmalloc(value_size, GFP_USER | __GFP_NOWARN);
@@ -932,56 +981,8 @@ static int map_update_elem(union bpf_attr *attr)
        if (copy_from_user(value, uvalue, value_size) != 0)
                goto free_value;
 
-       /* Need to create a kthread, thus must support schedule */
-       if (bpf_map_is_dev_bound(map)) {
-               err = bpf_map_offload_update_elem(map, key, value, attr->flags);
-               goto out;
-       } else if (map->map_type == BPF_MAP_TYPE_CPUMAP ||
-                  map->map_type == BPF_MAP_TYPE_SOCKHASH ||
-                  map->map_type == BPF_MAP_TYPE_SOCKMAP) {
-               err = map->ops->map_update_elem(map, key, value, attr->flags);
-               goto out;
-       }
+       err = bpf_map_update_elem(map, key, value, &f, attr->flags);
 
-       /* must increment bpf_prog_active to avoid kprobe+bpf triggering from
-        * inside bpf map update or delete otherwise deadlocks are possible
-        */
-       preempt_disable();
-       __this_cpu_inc(bpf_prog_active);
-       if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
-           map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) {
-               err = bpf_percpu_hash_update(map, key, value, attr->flags);
-       } else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) {
-               err = bpf_percpu_array_update(map, key, value, attr->flags);
-       } else if (map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE) {
-               err = bpf_percpu_cgroup_storage_update(map, key, value,
-                                                      attr->flags);
-       } else if (IS_FD_ARRAY(map)) {
-               rcu_read_lock();
-               err = bpf_fd_array_map_update_elem(map, f.file, key, value,
-                                                  attr->flags);
-               rcu_read_unlock();
-       } else if (map->map_type == BPF_MAP_TYPE_HASH_OF_MAPS) {
-               rcu_read_lock();
-               err = bpf_fd_htab_map_update_elem(map, f.file, key, value,
-                                                 attr->flags);
-               rcu_read_unlock();
-       } else if (map->map_type == BPF_MAP_TYPE_REUSEPORT_SOCKARRAY) {
-               /* rcu_read_lock() is not needed */
-               err = bpf_fd_reuseport_array_update_elem(map, key, value,
-                                                        attr->flags);
-       } else if (map->map_type == BPF_MAP_TYPE_QUEUE ||
-                  map->map_type == BPF_MAP_TYPE_STACK) {
-               err = map->ops->map_push_elem(map, value, attr->flags);
-       } else {
-               rcu_read_lock();
-               err = map->ops->map_update_elem(map, key, value, attr->flags);
-               rcu_read_unlock();
-       }
-       __this_cpu_dec(bpf_prog_active);
-       preempt_enable();
-       maybe_wait_bpf_programs(map);
-out:
 free_value:
        kfree(value);
 free_key:
-- 
2.17.1

Reply via email to