@@ -937,7 +937,7 @@ static void free_htab_elem(struct bpf_htab *htab, struct htab_elem *l)
937937}
938938
939939static void pcpu_copy_value (struct bpf_htab * htab , void __percpu * pptr ,
940- void * value , bool onallcpus )
940+ void * value , bool onallcpus , u64 map_flags )
941941{
942942 if (!onallcpus ) {
943943 /* copy true value_size bytes */
@@ -946,15 +946,26 @@ static void pcpu_copy_value(struct bpf_htab *htab, void __percpu *pptr,
946946 u32 size = round_up (htab -> map .value_size , 8 );
947947 int off = 0 , cpu ;
948948
949+ if (map_flags & BPF_F_CPU ) {
950+ cpu = map_flags >> 32 ;
951+ copy_map_value_long (& htab -> map , per_cpu_ptr (pptr , cpu ), value );
952+ return ;
953+ }
954+
949955 for_each_possible_cpu (cpu ) {
950956 copy_map_value_long (& htab -> map , per_cpu_ptr (pptr , cpu ), value + off );
951- off += size ;
957+ /* same user-provided value is used if BPF_F_ALL_CPUS
958+ * is specified, otherwise value is an array of per-CPU
959+ * values.
960+ */
961+ if (!(map_flags & BPF_F_ALL_CPUS ))
962+ off += size ;
952963 }
953964 }
954965}
955966
956967static void pcpu_init_value (struct bpf_htab * htab , void __percpu * pptr ,
957- void * value , bool onallcpus )
968+ void * value , bool onallcpus , u64 map_flags )
958969{
959970 /* When not setting the initial value on all cpus, zero-fill element
960971 * values for other cpus. Otherwise, bpf program has no way to ensure
@@ -972,7 +983,7 @@ static void pcpu_init_value(struct bpf_htab *htab, void __percpu *pptr,
972983 zero_map_value (& htab -> map , per_cpu_ptr (pptr , cpu ));
973984 }
974985 } else {
975- pcpu_copy_value (htab , pptr , value , onallcpus );
986+ pcpu_copy_value (htab , pptr , value , onallcpus , map_flags );
976987 }
977988}
978989
@@ -984,7 +995,7 @@ static bool fd_htab_map_needs_adjust(const struct bpf_htab *htab)
984995static struct htab_elem * alloc_htab_elem (struct bpf_htab * htab , void * key ,
985996 void * value , u32 key_size , u32 hash ,
986997 bool percpu , bool onallcpus ,
987- struct htab_elem * old_elem )
998+ struct htab_elem * old_elem , u64 map_flags )
988999{
9891000 u32 size = htab -> map .value_size ;
9901001 bool prealloc = htab_is_prealloc (htab );
@@ -1042,7 +1053,7 @@ static struct htab_elem *alloc_htab_elem(struct bpf_htab *htab, void *key,
10421053 pptr = * (void __percpu * * )ptr ;
10431054 }
10441055
1045- pcpu_init_value (htab , pptr , value , onallcpus );
1056+ pcpu_init_value (htab , pptr , value , onallcpus , map_flags );
10461057
10471058 if (!prealloc )
10481059 htab_elem_set_ptr (l_new , key_size , pptr );
@@ -1147,7 +1158,7 @@ static long htab_map_update_elem(struct bpf_map *map, void *key, void *value,
11471158 }
11481159
11491160 l_new = alloc_htab_elem (htab , key , value , key_size , hash , false, false,
1150- l_old );
1161+ l_old , map_flags );
11511162 if (IS_ERR (l_new )) {
11521163 /* all pre-allocated elements are in use or memory exhausted */
11531164 ret = PTR_ERR (l_new );
@@ -1263,7 +1274,7 @@ static long htab_map_update_elem_in_place(struct bpf_map *map, void *key,
12631274 u32 key_size , hash ;
12641275 int ret ;
12651276
1266- if (unlikely (map_flags > BPF_EXIST ))
1277+ if (unlikely (! onallcpus && map_flags > BPF_EXIST ))
12671278 /* unknown flags */
12681279 return - EINVAL ;
12691280
@@ -1291,7 +1302,7 @@ static long htab_map_update_elem_in_place(struct bpf_map *map, void *key,
12911302 /* Update value in-place */
12921303 if (percpu ) {
12931304 pcpu_copy_value (htab , htab_elem_get_ptr (l_old , key_size ),
1294- value , onallcpus );
1305+ value , onallcpus , map_flags );
12951306 } else {
12961307 void * * inner_map_pptr = htab_elem_value (l_old , key_size );
12971308
@@ -1300,7 +1311,7 @@ static long htab_map_update_elem_in_place(struct bpf_map *map, void *key,
13001311 }
13011312 } else {
13021313 l_new = alloc_htab_elem (htab , key , value , key_size ,
1303- hash , percpu , onallcpus , NULL );
1314+ hash , percpu , onallcpus , NULL , map_flags );
13041315 if (IS_ERR (l_new )) {
13051316 ret = PTR_ERR (l_new );
13061317 goto err ;
@@ -1326,7 +1337,7 @@ static long __htab_lru_percpu_map_update_elem(struct bpf_map *map, void *key,
13261337 u32 key_size , hash ;
13271338 int ret ;
13281339
1329- if (unlikely (map_flags > BPF_EXIST ))
1340+ if (unlikely (! onallcpus && map_flags > BPF_EXIST ))
13301341 /* unknown flags */
13311342 return - EINVAL ;
13321343
@@ -1366,10 +1377,10 @@ static long __htab_lru_percpu_map_update_elem(struct bpf_map *map, void *key,
13661377
13671378 /* per-cpu hash map can update value in-place */
13681379 pcpu_copy_value (htab , htab_elem_get_ptr (l_old , key_size ),
1369- value , onallcpus );
1380+ value , onallcpus , map_flags );
13701381 } else {
13711382 pcpu_init_value (htab , htab_elem_get_ptr (l_new , key_size ),
1372- value , onallcpus );
1383+ value , onallcpus , map_flags );
13731384 hlist_nulls_add_head_rcu (& l_new -> hash_node , head );
13741385 l_new = NULL ;
13751386 }
@@ -1698,9 +1709,16 @@ __htab_map_lookup_and_delete_batch(struct bpf_map *map,
16981709 int ret = 0 ;
16991710
17001711 elem_map_flags = attr -> batch .elem_flags ;
1701- if ((elem_map_flags & ~BPF_F_LOCK ) ||
1702- ((elem_map_flags & BPF_F_LOCK ) && !btf_record_has_field (map -> record , BPF_SPIN_LOCK )))
1703- return - EINVAL ;
1712+ if (!do_delete && is_percpu ) {
1713+ ret = bpf_map_check_op_flags (map , elem_map_flags , BPF_F_LOCK | BPF_F_CPU );
1714+ if (ret )
1715+ return ret ;
1716+ } else {
1717+ if ((elem_map_flags & ~BPF_F_LOCK ) ||
1718+ ((elem_map_flags & BPF_F_LOCK ) &&
1719+ !btf_record_has_field (map -> record , BPF_SPIN_LOCK )))
1720+ return - EINVAL ;
1721+ }
17041722
17051723 map_flags = attr -> batch .flags ;
17061724 if (map_flags )
@@ -1724,7 +1742,7 @@ __htab_map_lookup_and_delete_batch(struct bpf_map *map,
17241742 value_size = htab -> map .value_size ;
17251743 size = round_up (value_size , 8 );
17261744 if (is_percpu )
1727- value_size = size * num_possible_cpus ();
1745+ value_size = ( elem_map_flags & BPF_F_CPU ) ? size : size * num_possible_cpus ();
17281746 total = 0 ;
17291747 /* while experimenting with hash tables with sizes ranging from 10 to
17301748 * 1000, it was observed that a bucket can have up to 5 entries.
@@ -1806,10 +1824,17 @@ __htab_map_lookup_and_delete_batch(struct bpf_map *map,
18061824 void __percpu * pptr ;
18071825
18081826 pptr = htab_elem_get_ptr (l , map -> key_size );
1809- for_each_possible_cpu (cpu ) {
1810- copy_map_value_long (& htab -> map , dst_val + off , per_cpu_ptr (pptr , cpu ));
1811- check_and_init_map_value (& htab -> map , dst_val + off );
1812- off += size ;
1827+ if (elem_map_flags & BPF_F_CPU ) {
1828+ cpu = elem_map_flags >> 32 ;
1829+ copy_map_value_long (& htab -> map , dst_val , per_cpu_ptr (pptr , cpu ));
1830+ check_and_init_map_value (& htab -> map , dst_val );
1831+ } else {
1832+ for_each_possible_cpu (cpu ) {
1833+ copy_map_value_long (& htab -> map , dst_val + off ,
1834+ per_cpu_ptr (pptr , cpu ));
1835+ check_and_init_map_value (& htab -> map , dst_val + off );
1836+ off += size ;
1837+ }
18131838 }
18141839 } else {
18151840 value = htab_elem_value (l , key_size );
@@ -2365,7 +2390,7 @@ static void *htab_lru_percpu_map_lookup_percpu_elem(struct bpf_map *map, void *k
23652390 return NULL ;
23662391}
23672392
2368- int bpf_percpu_hash_copy (struct bpf_map * map , void * key , void * value )
2393+ int bpf_percpu_hash_copy (struct bpf_map * map , void * key , void * value , u64 map_flags )
23692394{
23702395 struct htab_elem * l ;
23712396 void __percpu * pptr ;
@@ -2382,16 +2407,22 @@ int bpf_percpu_hash_copy(struct bpf_map *map, void *key, void *value)
23822407 l = __htab_map_lookup_elem (map , key );
23832408 if (!l )
23842409 goto out ;
2410+ ret = 0 ;
23852411 /* We do not mark LRU map element here in order to not mess up
23862412 * eviction heuristics when user space does a map walk.
23872413 */
23882414 pptr = htab_elem_get_ptr (l , map -> key_size );
2415+ if (map_flags & BPF_F_CPU ) {
2416+ cpu = map_flags >> 32 ;
2417+ copy_map_value_long (map , value , per_cpu_ptr (pptr , cpu ));
2418+ check_and_init_map_value (map , value );
2419+ goto out ;
2420+ }
23892421 for_each_possible_cpu (cpu ) {
23902422 copy_map_value_long (map , value + off , per_cpu_ptr (pptr , cpu ));
23912423 check_and_init_map_value (map , value + off );
23922424 off += size ;
23932425 }
2394- ret = 0 ;
23952426out :
23962427 rcu_read_unlock ();
23972428 return ret ;
0 commit comments