Skip to content

Commit 2a36f0b

Browse files
WangNan0davem330
authored andcommitted
bpf: Make the bpf_prog_array_map more generic
All the map backends are of generic nature. In order to avoid adding much special code into the eBPF core, rewrite part of the bpf_prog_array map code and make it more generic. So the new perf_event_array map type can reuse most of code with bpf_prog_array map and add fewer lines of special code. Signed-off-by: Wang Nan <wangnan0@huawei.com> Signed-off-by: Kaixu Xia <xiakaixu@huawei.com> Signed-off-by: David S. Miller <davem@davemloft.net>
1 parent ffe8690 commit 2a36f0b

5 files changed

Lines changed: 60 additions & 38 deletions

File tree

arch/x86/net/bpf_jit_comp.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -246,7 +246,7 @@ static void emit_prologue(u8 **pprog)
246246
* goto out;
247247
* if (++tail_call_cnt > MAX_TAIL_CALL_CNT)
248248
* goto out;
249-
* prog = array->prog[index];
249+
* prog = array->ptrs[index];
250250
* if (prog == NULL)
251251
* goto out;
252252
* goto *(prog->bpf_func + prologue_size);
@@ -284,9 +284,9 @@ static void emit_bpf_tail_call(u8 **pprog)
284284
EMIT3(0x83, 0xC0, 0x01); /* add eax, 1 */
285285
EMIT2_off32(0x89, 0x85, -STACKSIZE + 36); /* mov dword ptr [rbp - 516], eax */
286286

287-
/* prog = array->prog[index]; */
287+
/* prog = array->ptrs[index]; */
288288
EMIT4_off32(0x48, 0x8D, 0x84, 0xD6, /* lea rax, [rsi + rdx * 8 + offsetof(...)] */
289-
offsetof(struct bpf_array, prog));
289+
offsetof(struct bpf_array, ptrs));
290290
EMIT3(0x48, 0x8B, 0x00); /* mov rax, qword ptr [rax] */
291291

292292
/* if (prog == NULL)

include/linux/bpf.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ struct bpf_map_ops {
2424
void *(*map_lookup_elem)(struct bpf_map *map, void *key);
2525
int (*map_update_elem)(struct bpf_map *map, void *key, void *value, u64 flags);
2626
int (*map_delete_elem)(struct bpf_map *map, void *key);
27+
28+
/* funcs called by prog_array and perf_event_array map */
29+
void *(*map_fd_get_ptr) (struct bpf_map *map, int fd);
30+
void (*map_fd_put_ptr) (void *ptr);
2731
};
2832

2933
struct bpf_map {
@@ -142,13 +146,13 @@ struct bpf_array {
142146
bool owner_jited;
143147
union {
144148
char value[0] __aligned(8);
145-
struct bpf_prog *prog[0] __aligned(8);
149+
void *ptrs[0] __aligned(8);
146150
};
147151
};
148152
#define MAX_TAIL_CALL_CNT 32
149153

150154
u64 bpf_tail_call(u64 ctx, u64 r2, u64 index, u64 r4, u64 r5);
151-
void bpf_prog_array_map_clear(struct bpf_map *map);
155+
void bpf_fd_array_map_clear(struct bpf_map *map);
152156
bool bpf_prog_array_compatible(struct bpf_array *array, const struct bpf_prog *fp);
153157
const struct bpf_func_proto *bpf_get_trace_printk_proto(void);
154158

kernel/bpf/arraymap.c

Lines changed: 49 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -150,15 +150,15 @@ static int __init register_array_map(void)
150150
}
151151
late_initcall(register_array_map);
152152

153-
static struct bpf_map *prog_array_map_alloc(union bpf_attr *attr)
153+
static struct bpf_map *fd_array_map_alloc(union bpf_attr *attr)
154154
{
155-
/* only bpf_prog file descriptors can be stored in prog_array map */
155+
/* only file descriptors can be stored in this type of map */
156156
if (attr->value_size != sizeof(u32))
157157
return ERR_PTR(-EINVAL);
158158
return array_map_alloc(attr);
159159
}
160160

161-
static void prog_array_map_free(struct bpf_map *map)
161+
static void fd_array_map_free(struct bpf_map *map)
162162
{
163163
struct bpf_array *array = container_of(map, struct bpf_array, map);
164164
int i;
@@ -167,21 +167,21 @@ static void prog_array_map_free(struct bpf_map *map)
167167

168168
/* make sure it's empty */
169169
for (i = 0; i < array->map.max_entries; i++)
170-
BUG_ON(array->prog[i] != NULL);
170+
BUG_ON(array->ptrs[i] != NULL);
171171
kvfree(array);
172172
}
173173

174-
static void *prog_array_map_lookup_elem(struct bpf_map *map, void *key)
174+
static void *fd_array_map_lookup_elem(struct bpf_map *map, void *key)
175175
{
176176
return NULL;
177177
}
178178

179179
/* only called from syscall */
180-
static int prog_array_map_update_elem(struct bpf_map *map, void *key,
181-
void *value, u64 map_flags)
180+
static int fd_array_map_update_elem(struct bpf_map *map, void *key,
181+
void *value, u64 map_flags)
182182
{
183183
struct bpf_array *array = container_of(map, struct bpf_array, map);
184-
struct bpf_prog *prog, *old_prog;
184+
void *new_ptr, *old_ptr;
185185
u32 index = *(u32 *)key, ufd;
186186

187187
if (map_flags != BPF_ANY)
@@ -191,57 +191,75 @@ static int prog_array_map_update_elem(struct bpf_map *map, void *key,
191191
return -E2BIG;
192192

193193
ufd = *(u32 *)value;
194-
prog = bpf_prog_get(ufd);
195-
if (IS_ERR(prog))
196-
return PTR_ERR(prog);
197-
198-
if (!bpf_prog_array_compatible(array, prog)) {
199-
bpf_prog_put(prog);
200-
return -EINVAL;
201-
}
194+
new_ptr = map->ops->map_fd_get_ptr(map, ufd);
195+
if (IS_ERR(new_ptr))
196+
return PTR_ERR(new_ptr);
202197

203-
old_prog = xchg(array->prog + index, prog);
204-
if (old_prog)
205-
bpf_prog_put_rcu(old_prog);
198+
old_ptr = xchg(array->ptrs + index, new_ptr);
199+
if (old_ptr)
200+
map->ops->map_fd_put_ptr(old_ptr);
206201

207202
return 0;
208203
}
209204

210-
static int prog_array_map_delete_elem(struct bpf_map *map, void *key)
205+
static int fd_array_map_delete_elem(struct bpf_map *map, void *key)
211206
{
212207
struct bpf_array *array = container_of(map, struct bpf_array, map);
213-
struct bpf_prog *old_prog;
208+
void *old_ptr;
214209
u32 index = *(u32 *)key;
215210

216211
if (index >= array->map.max_entries)
217212
return -E2BIG;
218213

219-
old_prog = xchg(array->prog + index, NULL);
220-
if (old_prog) {
221-
bpf_prog_put_rcu(old_prog);
214+
old_ptr = xchg(array->ptrs + index, NULL);
215+
if (old_ptr) {
216+
map->ops->map_fd_put_ptr(old_ptr);
222217
return 0;
223218
} else {
224219
return -ENOENT;
225220
}
226221
}
227222

223+
static void *prog_fd_array_get_ptr(struct bpf_map *map, int fd)
224+
{
225+
struct bpf_array *array = container_of(map, struct bpf_array, map);
226+
struct bpf_prog *prog = bpf_prog_get(fd);
227+
if (IS_ERR(prog))
228+
return prog;
229+
230+
if (!bpf_prog_array_compatible(array, prog)) {
231+
bpf_prog_put(prog);
232+
return ERR_PTR(-EINVAL);
233+
}
234+
return prog;
235+
}
236+
237+
static void prog_fd_array_put_ptr(void *ptr)
238+
{
239+
struct bpf_prog *prog = ptr;
240+
241+
bpf_prog_put_rcu(prog);
242+
}
243+
228244
/* decrement refcnt of all bpf_progs that are stored in this map */
229-
void bpf_prog_array_map_clear(struct bpf_map *map)
245+
void bpf_fd_array_map_clear(struct bpf_map *map)
230246
{
231247
struct bpf_array *array = container_of(map, struct bpf_array, map);
232248
int i;
233249

234250
for (i = 0; i < array->map.max_entries; i++)
235-
prog_array_map_delete_elem(map, &i);
251+
fd_array_map_delete_elem(map, &i);
236252
}
237253

238254
static const struct bpf_map_ops prog_array_ops = {
239-
.map_alloc = prog_array_map_alloc,
240-
.map_free = prog_array_map_free,
255+
.map_alloc = fd_array_map_alloc,
256+
.map_free = fd_array_map_free,
241257
.map_get_next_key = array_map_get_next_key,
242-
.map_lookup_elem = prog_array_map_lookup_elem,
243-
.map_update_elem = prog_array_map_update_elem,
244-
.map_delete_elem = prog_array_map_delete_elem,
258+
.map_lookup_elem = fd_array_map_lookup_elem,
259+
.map_update_elem = fd_array_map_update_elem,
260+
.map_delete_elem = fd_array_map_delete_elem,
261+
.map_fd_get_ptr = prog_fd_array_get_ptr,
262+
.map_fd_put_ptr = prog_fd_array_put_ptr,
245263
};
246264

247265
static struct bpf_map_type_list prog_array_type __read_mostly = {

kernel/bpf/core.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -450,7 +450,7 @@ static unsigned int __bpf_prog_run(void *ctx, const struct bpf_insn *insn)
450450

451451
tail_call_cnt++;
452452

453-
prog = READ_ONCE(array->prog[index]);
453+
prog = READ_ONCE(array->ptrs[index]);
454454
if (unlikely(!prog))
455455
goto out;
456456

kernel/bpf/syscall.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ static int bpf_map_release(struct inode *inode, struct file *filp)
7272
/* prog_array stores refcnt-ed bpf_prog pointers
7373
* release them all when user space closes prog_array_fd
7474
*/
75-
bpf_prog_array_map_clear(map);
75+
bpf_fd_array_map_clear(map);
7676

7777
bpf_map_put(map);
7878
return 0;

0 commit comments

Comments
 (0)