Merge git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next
[platform/kernel/linux-rpi.git] / kernel / bpf / hashtab.c
index 7bf18d9..ec46266 100644 (file)
@@ -855,6 +855,32 @@ static void pcpu_copy_value(struct bpf_htab *htab, void __percpu *pptr,
        }
 }
 
+static void pcpu_init_value(struct bpf_htab *htab, void __percpu *pptr,
+                           void *value, bool onallcpus)
+{
+       /* When using prealloc and not setting the initial value on all cpus,
+        * zero-fill element values for other cpus (just as what happens when
+        * not using prealloc). Otherwise, bpf program has no way to ensure
+        * known initial values for cpus other than current one
+        * (onallcpus=false always when coming from bpf prog).
+        */
+       if (htab_is_prealloc(htab) && !onallcpus) {
+               u32 size = round_up(htab->map.value_size, 8);
+               int current_cpu = raw_smp_processor_id();
+               int cpu;
+
+               for_each_possible_cpu(cpu) {
+                       if (cpu == current_cpu)
+                               bpf_long_memcpy(per_cpu_ptr(pptr, cpu), value,
+                                               size);
+                       else
+                               memset(per_cpu_ptr(pptr, cpu), 0, size);
+               }
+       } else {
+               pcpu_copy_value(htab, pptr, value, onallcpus);
+       }
+}
+
 static bool fd_htab_map_needs_adjust(const struct bpf_htab *htab)
 {
        return htab->map.map_type == BPF_MAP_TYPE_HASH_OF_MAPS &&
@@ -925,7 +951,7 @@ static struct htab_elem *alloc_htab_elem(struct bpf_htab *htab, void *key,
                        }
                }
 
-               pcpu_copy_value(htab, pptr, value, onallcpus);
+               pcpu_init_value(htab, pptr, value, onallcpus);
 
                if (!prealloc)
                        htab_elem_set_ptr(l_new, key_size, pptr);
@@ -1225,7 +1251,7 @@ static int __htab_lru_percpu_map_update_elem(struct bpf_map *map, void *key,
                pcpu_copy_value(htab, htab_elem_get_ptr(l_old, key_size),
                                value, onallcpus);
        } else {
-               pcpu_copy_value(htab, htab_elem_get_ptr(l_new, key_size),
+               pcpu_init_value(htab, htab_elem_get_ptr(l_new, key_size),
                                value, onallcpus);
                hlist_nulls_add_head_rcu(&l_new->hash_node, head);
                l_new = NULL;