-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
selftests/bpf: Add test case for element reuse in htab map
The reinitialization of spin-lock in map value after immediate reuse may corrupt lookup with BPF_F_LOCK flag and result in hard lock-up, so add one test case to demonstrate the problem. Signed-off-by: Hou Tao <houtao1@huawei.com> Link: https://lore.kernel.org/r/20230215082132.3856544-3-houtao@huaweicloud.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>
- Loading branch information
Hou Tao
authored and
Alexei Starovoitov
committed
Feb 15, 2023
1 parent
997849c
commit f88da2d
Showing
2 changed files
with
120 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,101 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* Copyright (C) 2023. Huawei Technologies Co., Ltd */ | ||
#define _GNU_SOURCE | ||
#include <sched.h> | ||
#include <stdbool.h> | ||
#include <test_progs.h> | ||
#include "htab_reuse.skel.h" | ||
|
||
struct htab_op_ctx { | ||
int fd; | ||
int loop; | ||
bool stop; | ||
}; | ||
|
||
struct htab_val { | ||
unsigned int lock; | ||
unsigned int data; | ||
}; | ||
|
||
static void *htab_lookup_fn(void *arg) | ||
{ | ||
struct htab_op_ctx *ctx = arg; | ||
int i = 0; | ||
|
||
while (i++ < ctx->loop && !ctx->stop) { | ||
struct htab_val value; | ||
unsigned int key; | ||
|
||
/* Use BPF_F_LOCK to use spin-lock in map value. */ | ||
key = 7; | ||
bpf_map_lookup_elem_flags(ctx->fd, &key, &value, BPF_F_LOCK); | ||
} | ||
|
||
return NULL; | ||
} | ||
|
||
static void *htab_update_fn(void *arg) | ||
{ | ||
struct htab_op_ctx *ctx = arg; | ||
int i = 0; | ||
|
||
while (i++ < ctx->loop && !ctx->stop) { | ||
struct htab_val value; | ||
unsigned int key; | ||
|
||
key = 7; | ||
value.lock = 0; | ||
value.data = key; | ||
bpf_map_update_elem(ctx->fd, &key, &value, BPF_F_LOCK); | ||
bpf_map_delete_elem(ctx->fd, &key); | ||
|
||
key = 24; | ||
value.lock = 0; | ||
value.data = key; | ||
bpf_map_update_elem(ctx->fd, &key, &value, BPF_F_LOCK); | ||
bpf_map_delete_elem(ctx->fd, &key); | ||
} | ||
|
||
return NULL; | ||
} | ||
|
||
void test_htab_reuse(void) | ||
{ | ||
unsigned int i, wr_nr = 1, rd_nr = 4; | ||
pthread_t tids[wr_nr + rd_nr]; | ||
struct htab_reuse *skel; | ||
struct htab_op_ctx ctx; | ||
int err; | ||
|
||
skel = htab_reuse__open_and_load(); | ||
if (!ASSERT_OK_PTR(skel, "htab_reuse__open_and_load")) | ||
return; | ||
|
||
ctx.fd = bpf_map__fd(skel->maps.htab); | ||
ctx.loop = 500; | ||
ctx.stop = false; | ||
|
||
memset(tids, 0, sizeof(tids)); | ||
for (i = 0; i < wr_nr; i++) { | ||
err = pthread_create(&tids[i], NULL, htab_update_fn, &ctx); | ||
if (!ASSERT_OK(err, "pthread_create")) { | ||
ctx.stop = true; | ||
goto reap; | ||
} | ||
} | ||
for (i = 0; i < rd_nr; i++) { | ||
err = pthread_create(&tids[i + wr_nr], NULL, htab_lookup_fn, &ctx); | ||
if (!ASSERT_OK(err, "pthread_create")) { | ||
ctx.stop = true; | ||
goto reap; | ||
} | ||
} | ||
|
||
reap: | ||
for (i = 0; i < wr_nr + rd_nr; i++) { | ||
if (!tids[i]) | ||
continue; | ||
pthread_join(tids[i], NULL); | ||
} | ||
htab_reuse__destroy(skel); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
// SPDX-License-Identifier: GPL-2.0 | ||
/* Copyright (C) 2023. Huawei Technologies Co., Ltd */ | ||
#include <linux/bpf.h> | ||
#include <bpf/bpf_helpers.h> | ||
|
||
char _license[] SEC("license") = "GPL"; | ||
|
||
struct htab_val { | ||
struct bpf_spin_lock lock; | ||
unsigned int data; | ||
}; | ||
|
||
struct { | ||
__uint(type, BPF_MAP_TYPE_HASH); | ||
__uint(max_entries, 64); | ||
__type(key, unsigned int); | ||
__type(value, struct htab_val); | ||
__uint(map_flags, BPF_F_NO_PREALLOC); | ||
} htab SEC(".maps"); |