selftsets/bpf: Retry map update for non-preallocated per-cpu map
BPF CI failed due to map_percpu_stats_percpu_hash from time to time [1]. It seems that the failure reason is per-cpu bpf memory allocator may not be able to allocate per-cpu pointer successfully and it can not refill free llist timely, and bpf_map_update_elem() will return -ENOMEM. So mitigate the problem by retrying the update operation for non-preallocated per-cpu map. [1]: https://github.com/kernel-patches/bpf/actions/runs/6713177520/job/18244865326?pr=5909 Signed-off-by: Hou Tao <houtao1@huawei.com> Signed-off-by: Andrii Nakryiko <andrii@kernel.org> Link: https://lore.kernel.org/bpf/20231101032455.3808547-4-houtao@huaweicloud.com Signed-off-by: Alexei Starovoitov <ast@kernel.org>pull/477/merge
parent
b9b7955316
commit
2f553b032c
|
|
@ -141,6 +141,7 @@ struct upsert_opts {
|
||||||
__u32 map_type;
|
__u32 map_type;
|
||||||
int map_fd;
|
int map_fd;
|
||||||
__u32 n;
|
__u32 n;
|
||||||
|
bool retry_for_nomem;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int create_small_hash(void)
|
static int create_small_hash(void)
|
||||||
|
|
@ -154,6 +155,11 @@ static int create_small_hash(void)
|
||||||
return map_fd;
|
return map_fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool retry_for_nomem_fn(int err)
|
||||||
|
{
|
||||||
|
return err == ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
static void *patch_map_thread(void *arg)
|
static void *patch_map_thread(void *arg)
|
||||||
{
|
{
|
||||||
/* 8KB is enough for 1024 CPUs. And it is shared between N_THREADS. */
|
/* 8KB is enough for 1024 CPUs. And it is shared between N_THREADS. */
|
||||||
|
|
@ -175,6 +181,11 @@ static void *patch_map_thread(void *arg)
|
||||||
val_ptr = &val;
|
val_ptr = &val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 2 seconds may be enough ? */
|
||||||
|
if (opts->retry_for_nomem)
|
||||||
|
ret = map_update_retriable(opts->map_fd, &i, val_ptr, 0,
|
||||||
|
40, retry_for_nomem_fn);
|
||||||
|
else
|
||||||
ret = bpf_map_update_elem(opts->map_fd, &i, val_ptr, 0);
|
ret = bpf_map_update_elem(opts->map_fd, &i, val_ptr, 0);
|
||||||
CHECK(ret < 0, "bpf_map_update_elem", "key=%d error: %s\n", i, strerror(errno));
|
CHECK(ret < 0, "bpf_map_update_elem", "key=%d error: %s\n", i, strerror(errno));
|
||||||
|
|
||||||
|
|
@ -296,6 +307,13 @@ static void __test(int map_fd)
|
||||||
else
|
else
|
||||||
opts.n /= 2;
|
opts.n /= 2;
|
||||||
|
|
||||||
|
/* per-cpu bpf memory allocator may not be able to allocate per-cpu
|
||||||
|
* pointer successfully and it can not refill free llist timely, and
|
||||||
|
* bpf_map_update_elem() will return -ENOMEM. so just retry to mitigate
|
||||||
|
* the problem temporarily.
|
||||||
|
*/
|
||||||
|
opts.retry_for_nomem = is_percpu(opts.map_type) && (info.map_flags & BPF_F_NO_PREALLOC);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Upsert keys [0, n) under some competition: with random values from
|
* Upsert keys [0, n) under some competition: with random values from
|
||||||
* N_THREADS threads. Check values, then delete all elements and check
|
* N_THREADS threads. Check values, then delete all elements and check
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue