| @@ -307,7 +307,7 @@ static void *percpu_array_map_lookup_percpu_elem(struct bpf_map *map, void *key, · 306 unmodified lines |
| 307 | return per_cpu_ptr(array->pptrs[index & array->index_mask], cpu); | 307 | return per_cpu_ptr(array->pptrs[index & array->index_mask], cpu); |
| 308 | } | 308 | } |
| 309 | | 309 | |
| 310 | int bpf_percpu_array_copy(struct bpf_map *map, void *key, void *value) | 310 | int bpf_percpu_array_copy(struct bpf_map *map, void *key, void *value, u64 map_flags) |
| 311 | { | 311 | { |
| 312 | struct bpf_array *array = container_of(map, struct bpf_array, map); | 312 | struct bpf_array *array = container_of(map, struct bpf_array, map); |
| 313 | u32 index = *(u32 *)key; | 313 | u32 index = *(u32 *)key; |
| @@ -325,11 +325,18 @@ int bpf_percpu_array_copy(struct bpf_map *map, void *key, void *value) · 11 unmodified lines |
| 325 | size = array->elem_size; | 325 | size = array->elem_size; |
| 326 | rcu_read_lock(); | 326 | rcu_read_lock(); |
| 327 | pptr = array->pptrs[index & array->index_mask]; | 327 | pptr = array->pptrs[index & array->index_mask]; |
| | 328 | if (map_flags & BPF_F_CPU) { |
| | 329 | cpu = map_flags >> 32; |
| | 330 | copy_map_value(map, value, per_cpu_ptr(pptr, cpu)); |
| | 331 | check_and_init_map_value(map, value); |
| | 332 | goto unlock; |
| | 333 | } |
| 328 | for_each_possible_cpu(cpu) { | 334 | for_each_possible_cpu(cpu) { |
| 329 | copy_map_value_long(map, value + off, per_cpu_ptr(pptr, cpu)); | 335 | copy_map_value_long(map, value + off, per_cpu_ptr(pptr, cpu)); |
| 330 | check_and_init_map_value(map, value + off); | 336 | check_and_init_map_value(map, value + off); |
| 331 | off += size; | 337 | off += size; |
| 332 | } | 338 | } |
| | 339 | unlock: |
| 333 | rcu_read_unlock(); | 340 | rcu_read_unlock(); |
| 334 | return 0; | 341 | return 0; |
| 335 | } | 342 | } |
| @@ -398,10 +405,11 @@ int bpf_percpu_array_update(struct bpf_map *map, void *key, void *value, · 62 unmodified lines |
| 398 | struct bpf_array *array = container_of(map, struct bpf_array, map); | 405 | struct bpf_array *array = container_of(map, struct bpf_array, map); |
| 399 | u32 index = *(u32 *)key; | 406 | u32 index = *(u32 *)key; |
| 400 | void __percpu *pptr; | 407 | void __percpu *pptr; |
| 401 | int cpu, off = 0; | 408 | void *ptr, *val; |
| 402 | u32 size; | 409 | u32 size; |
| | 410 | int cpu; |
| 403 | | 411 | |
| 404 | if (unlikely(map_flags > BPF_EXIST)) | 412 | if (unlikely((map_flags & BPF_F_LOCK) || (u32)map_flags > BPF_F_ALL_CPUS)) |
| 405 | /* unknown flags */ | 413 | /* unknown flags */ |
| 406 | return -EINVAL; | 414 | return -EINVAL; |
| 407 | | 415 | |
| @@ -422,11 +430,20 @@ int bpf_percpu_array_update(struct bpf_map *map, void *key, void *value, · 14 unmodified lines |
| 422 | size = array->elem_size; | 430 | size = array->elem_size; |
| 423 | rcu_read_lock(); | 431 | rcu_read_lock(); |
| 424 | pptr = array->pptrs[index & array->index_mask]; | 432 | pptr = array->pptrs[index & array->index_mask]; |
| | 433 | if (map_flags & BPF_F_CPU) { |
| | 434 | cpu = map_flags >> 32; |
| | 435 | ptr = per_cpu_ptr(pptr, cpu); |
| | 436 | copy_map_value(map, ptr, value); |
| | 437 | bpf_obj_free_fields(array->map.record, ptr); |
| | 438 | goto unlock; |
| | 439 | } |
| 425 | for_each_possible_cpu(cpu) { | 440 | for_each_possible_cpu(cpu) { |
| 426 | copy_map_value_long(map, per_cpu_ptr(pptr, cpu), value + off); | 441 | ptr = per_cpu_ptr(pptr, cpu); |
| 427 | bpf_obj_free_fields(array->map.record, per_cpu_ptr(pptr, cpu)); | 442 | val = (map_flags & BPF_F_ALL_CPUS) ? value : value + size * cpu; |
| 428 | off += size; | 443 | copy_map_value(map, ptr, val); |
| | 444 | bpf_obj_free_fields(array->map.record, ptr); |
| 429 | } | 445 | } |
| | 446 | unlock: |
| 430 | rcu_read_unlock(); | 447 | rcu_read_unlock(); |
| 431 | return 0; | 448 | return 0; |
| 432 | } | 449 | } |