Skip to content

Commit ac9a904

Browse files
AsphalttKernel Patches Daemon
authored andcommitted
bpf: Introduce BPF_F_CPU and BPF_F_ALL_CPUS flags
Introduce BPF_F_CPU and BPF_F_ALL_CPUS flags and check them for following APIs: * 'map_lookup_elem()' * 'map_update_elem()' * 'generic_map_lookup_batch()' * 'generic_map_update_batch()' And, get the correct value size for these APIs. Acked-by: Andrii Nakryiko <[email protected]> Signed-off-by: Leon Hwang <[email protected]>
1 parent b7f25ca commit ac9a904

File tree

4 files changed

+43
-15
lines changed

4 files changed

+43
-15
lines changed

include/linux/bpf.h

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3815,14 +3815,35 @@ bpf_prog_update_insn_ptrs(struct bpf_prog *prog, u32 *offsets, void *image)
38153815
}
38163816
#endif
38173817

3818+
static inline bool bpf_map_supports_cpu_flags(enum bpf_map_type map_type)
3819+
{
3820+
return false;
3821+
}
3822+
38183823
static inline int bpf_map_check_op_flags(struct bpf_map *map, u64 flags, u64 allowed_flags)
38193824
{
3820-
if (flags & ~allowed_flags)
3825+
u32 cpu;
3826+
3827+
if ((u32)flags & ~allowed_flags)
38213828
return -EINVAL;
38223829

38233830
if ((flags & BPF_F_LOCK) && !btf_record_has_field(map->record, BPF_SPIN_LOCK))
38243831
return -EINVAL;
38253832

3833+
if (!(flags & BPF_F_CPU) && flags >> 32)
3834+
return -EINVAL;
3835+
3836+
if (flags & (BPF_F_CPU | BPF_F_ALL_CPUS)) {
3837+
if (!bpf_map_supports_cpu_flags(map->map_type))
3838+
return -EINVAL;
3839+
if ((flags & BPF_F_CPU) && (flags & BPF_F_ALL_CPUS))
3840+
return -EINVAL;
3841+
3842+
cpu = flags >> 32;
3843+
if ((flags & BPF_F_CPU) && cpu >= num_possible_cpus())
3844+
return -ERANGE;
3845+
}
3846+
38263847
return 0;
38273848
}
38283849

include/uapi/linux/bpf.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1373,6 +1373,8 @@ enum {
13731373
BPF_NOEXIST = 1, /* create new element if it didn't exist */
13741374
BPF_EXIST = 2, /* update existing element */
13751375
BPF_F_LOCK = 4, /* spin_lock-ed map_lookup/map_update */
1376+
BPF_F_CPU = 8, /* cpu flag for percpu maps, upper 32-bit of flags is a cpu number */
1377+
BPF_F_ALL_CPUS = 16, /* update value across all CPUs for percpu maps */
13761378
};
13771379

13781380
/* flags for BPF_MAP_CREATE command */

kernel/bpf/syscall.c

Lines changed: 17 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -133,12 +133,14 @@ bool bpf_map_write_active(const struct bpf_map *map)
133133
return atomic64_read(&map->writecnt) != 0;
134134
}
135135

136-
static u32 bpf_map_value_size(const struct bpf_map *map)
137-
{
138-
if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
139-
map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
140-
map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY ||
141-
map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE)
136+
static u32 bpf_map_value_size(const struct bpf_map *map, u64 flags)
137+
{
138+
if (flags & (BPF_F_CPU | BPF_F_ALL_CPUS))
139+
return map->value_size;
140+
else if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
141+
map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH ||
142+
map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY ||
143+
map->map_type == BPF_MAP_TYPE_PERCPU_CGROUP_STORAGE)
142144
return round_up(map->value_size, 8) * num_possible_cpus();
143145
else if (IS_FD_MAP(map))
144146
return sizeof(u32);
@@ -1732,15 +1734,15 @@ static int map_lookup_elem(union bpf_attr *attr)
17321734
if (!(map_get_sys_perms(map, f) & FMODE_CAN_READ))
17331735
return -EPERM;
17341736

1735-
err = bpf_map_check_op_flags(map, attr->flags, BPF_F_LOCK);
1737+
err = bpf_map_check_op_flags(map, attr->flags, BPF_F_LOCK | BPF_F_CPU);
17361738
if (err)
17371739
return err;
17381740

17391741
key = __bpf_copy_key(ukey, map->key_size);
17401742
if (IS_ERR(key))
17411743
return PTR_ERR(key);
17421744

1743-
value_size = bpf_map_value_size(map);
1745+
value_size = bpf_map_value_size(map, attr->flags);
17441746

17451747
err = -ENOMEM;
17461748
value = kvmalloc(value_size, GFP_USER | __GFP_NOWARN);
@@ -1807,7 +1809,7 @@ static int map_update_elem(union bpf_attr *attr, bpfptr_t uattr)
18071809
goto err_put;
18081810
}
18091811

1810-
value_size = bpf_map_value_size(map);
1812+
value_size = bpf_map_value_size(map, attr->flags);
18111813
value = kvmemdup_bpfptr(uvalue, value_size);
18121814
if (IS_ERR(value)) {
18131815
err = PTR_ERR(value);
@@ -2003,11 +2005,12 @@ int generic_map_update_batch(struct bpf_map *map, struct file *map_file,
20032005
void *key, *value;
20042006
int err = 0;
20052007

2006-
err = bpf_map_check_op_flags(map, attr->batch.elem_flags, BPF_F_LOCK);
2008+
err = bpf_map_check_op_flags(map, attr->batch.elem_flags,
2009+
BPF_F_LOCK | BPF_F_CPU | BPF_F_ALL_CPUS);
20072010
if (err)
20082011
return err;
20092012

2010-
value_size = bpf_map_value_size(map);
2013+
value_size = bpf_map_value_size(map, attr->batch.elem_flags);
20112014

20122015
max_count = attr->batch.count;
20132016
if (!max_count)
@@ -2062,11 +2065,11 @@ int generic_map_lookup_batch(struct bpf_map *map,
20622065
u32 value_size, cp, max_count;
20632066
int err;
20642067

2065-
err = bpf_map_check_op_flags(map, attr->batch.elem_flags, BPF_F_LOCK);
2068+
err = bpf_map_check_op_flags(map, attr->batch.elem_flags, BPF_F_LOCK | BPF_F_CPU);
20662069
if (err)
20672070
return err;
20682071

2069-
value_size = bpf_map_value_size(map);
2072+
value_size = bpf_map_value_size(map, attr->batch.elem_flags);
20702073

20712074
max_count = attr->batch.count;
20722075
if (!max_count)
@@ -2188,7 +2191,7 @@ static int map_lookup_and_delete_elem(union bpf_attr *attr)
21882191
goto err_put;
21892192
}
21902193

2191-
value_size = bpf_map_value_size(map);
2194+
value_size = bpf_map_value_size(map, 0);
21922195

21932196
err = -ENOMEM;
21942197
value = kvmalloc(value_size, GFP_USER | __GFP_NOWARN);

tools/include/uapi/linux/bpf.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1373,6 +1373,8 @@ enum {
13731373
BPF_NOEXIST = 1, /* create new element if it didn't exist */
13741374
BPF_EXIST = 2, /* update existing element */
13751375
BPF_F_LOCK = 4, /* spin_lock-ed map_lookup/map_update */
1376+
BPF_F_CPU = 8, /* cpu flag for percpu maps, upper 32-bit of flags is a cpu number */
1377+
BPF_F_ALL_CPUS = 16, /* update value across all CPUs for percpu maps */
13761378
};
13771379

13781380
/* flags for BPF_MAP_CREATE command */

0 commit comments

Comments
 (0)