Skip to content

Commit 11b844b

Browse files
anakryikoborkmann
authored andcommitted
selftests/bpf: Work-around EBUSY errors from hashmap update/delete
20b6cc3 ("bpf: Avoid hashtab deadlock with map_locked") introduced a possibility of getting EBUSY error on lock contention, which seems to happen very deterministically in test_maps when running 1024 threads on low-CPU machine. In libbpf CI case, it's a 2 CPU VM and it's hitting this 100% of the time. Work around by retrying on EBUSY (and EAGAIN, while we are at it) after a small sleep. sched_yield() is too agressive and fails even after 20 retries, so I went with usleep(1) for backoff. Also log actual error returned to make it easier to see what's going on. Fixes: 20b6cc3 ("bpf: Avoid hashtab deadlock with map_locked") Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Acked-by: Song Liu <songliubraving@fb.com> Link: https://lore.kernel.org/bpf/20201223200652.3417075-1-andrii@kernel.org
1 parent e7e5180 commit 11b844b

File tree

1 file changed

+42
-6
lines changed

1 file changed

+42
-6
lines changed

tools/testing/selftests/bpf/test_maps.c

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1312,22 +1312,58 @@ static void test_map_stress(void)
13121312
#define DO_UPDATE 1
13131313
#define DO_DELETE 0
13141314

1315+
#define MAP_RETRIES 20
1316+
1317+
static int map_update_retriable(int map_fd, const void *key, const void *value,
1318+
int flags, int attempts)
1319+
{
1320+
while (bpf_map_update_elem(map_fd, key, value, flags)) {
1321+
if (!attempts || (errno != EAGAIN && errno != EBUSY))
1322+
return -errno;
1323+
1324+
usleep(1);
1325+
attempts--;
1326+
}
1327+
1328+
return 0;
1329+
}
1330+
1331+
static int map_delete_retriable(int map_fd, const void *key, int attempts)
1332+
{
1333+
while (bpf_map_delete_elem(map_fd, key)) {
1334+
if (!attempts || (errno != EAGAIN && errno != EBUSY))
1335+
return -errno;
1336+
1337+
usleep(1);
1338+
attempts--;
1339+
}
1340+
1341+
return 0;
1342+
}
1343+
13151344
static void test_update_delete(unsigned int fn, void *data)
13161345
{
13171346
int do_update = ((int *)data)[1];
13181347
int fd = ((int *)data)[0];
1319-
int i, key, value;
1348+
int i, key, value, err;
13201349

13211350
for (i = fn; i < MAP_SIZE; i += TASKS) {
13221351
key = value = i;
13231352

13241353
if (do_update) {
1325-
assert(bpf_map_update_elem(fd, &key, &value,
1326-
BPF_NOEXIST) == 0);
1327-
assert(bpf_map_update_elem(fd, &key, &value,
1328-
BPF_EXIST) == 0);
1354+
err = map_update_retriable(fd, &key, &value, BPF_NOEXIST, MAP_RETRIES);
1355+
if (err)
1356+
printf("error %d %d\n", err, errno);
1357+
assert(err == 0);
1358+
err = map_update_retriable(fd, &key, &value, BPF_EXIST, MAP_RETRIES);
1359+
if (err)
1360+
printf("error %d %d\n", err, errno);
1361+
assert(err == 0);
13291362
} else {
1330-
assert(bpf_map_delete_elem(fd, &key) == 0);
1363+
err = map_delete_retriable(fd, &key, MAP_RETRIES);
1364+
if (err)
1365+
printf("error %d %d\n", err, errno);
1366+
assert(err == 0);
13311367
}
13321368
}
13331369
}

0 commit comments

Comments
 (0)