Skip to content

Commit 7090b24

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 af70342 commit 7090b24

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
@@ -3813,14 +3813,35 @@ bpf_prog_update_insn_ptrs(struct bpf_prog *prog, u32 *offsets, void *image)
38133813
}
38143814
#endif
38153815

3816+
static inline bool bpf_map_supports_cpu_flags(enum bpf_map_type map_type)
3817+
{
3818+
return false;
3819+
}
3820+
38163821
static inline int bpf_map_check_op_flags(struct bpf_map *map, u64 flags, u64 allowed_flags)
38173822
{
3818-
if (flags & ~allowed_flags)
3823+
u32 cpu;
3824+
3825+
if ((u32)flags & ~allowed_flags)
38193826
return -EINVAL;
38203827

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

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

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)