* [PATCH bpf 0/2] selftests/bpf: Fix task work false failures and cleanup
@ 2026-09-17 8:08 Yun Lu
2026-09-17 8:08 ` [PATCH bpf 1/2] selftests/bpf: Fix timing-dependent assertions in task work stress test Yun Lu
2026-09-17 8:08 ` [PATCH bpf 2/2] selftests/bpf: Clean up child when task_work__open() fails Yun Lu
0 siblings, 2 replies; 7+ messages in thread
From: Yun Lu @ 2026-09-17 8:08 UTC (permalink / raw)
To: andrii, eddyz87, ihor.solodrai, ast, daniel, memxor, martin.lau,
song, yonghong.song, jolsa, emil, shuah
Cc: bpf, linux-kselftest
From: Yun Lu <luyun@kylinos.cn>
Hi,
This series fixes two independent issues in the BPF task work
selftests.
1/2 removes timing-dependent assumptions from the stress
test while retaining its callback accounting checks.
2/2 routes a task_work__open() failure through the common cleanup
path so that the pipe fds are closed and the forked child is woken
and reaped.
The stress test was run 50 times normally and 50 times with single-CPU
affinity, with all runs passing. A single-scheduler diagnostic also
reproduced the original zero-contention false failure and passed after
the fix.
Thanks,
Yun Lu
Yun Lu (2):
selftests/bpf: Fix timing-dependent assertions in task work stress test
selftests/bpf: Clean up child when task_work__open() fails
.../bpf/prog_tests/task_work_stress.c | 6 ++----
.../selftests/bpf/prog_tests/test_task_work.c | 2 +-
2 files changed, 3 insertions(+), 5 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 7+ messages in thread
* [PATCH bpf 1/2] selftests/bpf: Fix timing-dependent assertions in task work stress test
2026-09-17 8:08 [PATCH bpf 0/2] selftests/bpf: Fix task work false failures and cleanup Yun Lu
@ 2026-09-17 8:08 ` Yun Lu
2026-09-17 9:00 ` bot+bpf-ci
2026-09-17 14:39 ` Alexei Starovoitov
2026-09-17 8:08 ` [PATCH bpf 2/2] selftests/bpf: Clean up child when task_work__open() fails Yun Lu
1 sibling, 2 replies; 7+ messages in thread
From: Yun Lu @ 2026-09-17 8:08 UTC (permalink / raw)
To: andrii, eddyz87, ihor.solodrai, ast, daniel, memxor, martin.lau,
song, yonghong.song, jolsa, emil, shuah
Cc: bpf, linux-kselftest
From: Yun Lu <luyun@kylinos.cn>
task_work_run() assumes every stress run observes both scheduler
contention and, when the delete thread is enabled, cancellation of at
least one pending callback.
Neither outcome is guaranteed. Contention is observed only when another
scheduler selects the same one of 128 map values while its task work is
outstanding. A valid run can therefore have no scheduling errors. This
was reproduced with a single scheduler: more than one million callbacks
were scheduled and completed while schedule_error remained zero.
Likewise, a successful map deletion may remove a value after its
callback has completed. delete_success can therefore be nonzero without
callback_success being smaller than callback_scheduled.
Drop the assertion that schedule_error is nonzero. Keep requiring exact
callback accounting when deletion is disabled. With deletion enabled,
allow equal counts but still reject callback_success greater than
callback_scheduled.
Fixes: c6ae18e0af5e ("selftests/bpf: add bpf task work stress tests")
Signed-off-by: Yun Lu <luyun@kylinos.cn>
---
tools/testing/selftests/bpf/prog_tests/task_work_stress.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/tools/testing/selftests/bpf/prog_tests/task_work_stress.c b/tools/testing/selftests/bpf/prog_tests/task_work_stress.c
index 450d17d91a56..d61636ed5e3d 100644
--- a/tools/testing/selftests/bpf/prog_tests/task_work_stress.c
+++ b/tools/testing/selftests/bpf/prog_tests/task_work_stress.c
@@ -105,13 +105,11 @@ static void task_work_run(bool enable_delete)
pthread_join(tid_del, NULL);
ASSERT_GT(skel->bss->callback_scheduled, 0, "work scheduled");
- /* Some scheduling attempts should have failed due to contention */
- ASSERT_GT(skel->bss->schedule_error, 0, "schedule error");
if (enable_delete) {
- /* If delete thread is enabled, it has cancelled some callbacks */
ASSERT_GT(skel->bss->delete_success, 0, "delete success");
- ASSERT_LT(skel->bss->callback_success, skel->bss->callback_scheduled, "callbacks");
+ /* Deletion may race after the task work has already run. */
+ ASSERT_LE(skel->bss->callback_success, skel->bss->callback_scheduled, "callbacks");
} else {
/* Without delete thread number of scheduled callbacks is the same as fired */
ASSERT_EQ(skel->bss->callback_success, skel->bss->callback_scheduled, "callbacks");
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* [PATCH bpf 2/2] selftests/bpf: Clean up child when task_work__open() fails
2026-09-17 8:08 [PATCH bpf 0/2] selftests/bpf: Fix task work false failures and cleanup Yun Lu
2026-09-17 8:08 ` [PATCH bpf 1/2] selftests/bpf: Fix timing-dependent assertions in task work stress test Yun Lu
@ 2026-09-17 8:08 ` Yun Lu
1 sibling, 0 replies; 7+ messages in thread
From: Yun Lu @ 2026-09-17 8:08 UTC (permalink / raw)
To: andrii, eddyz87, ihor.solodrai, ast, daniel, memxor, martin.lau,
song, yonghong.song, jolsa, emil, shuah
Cc: bpf, linux-kselftest
From: Yun Lu <luyun@kylinos.cn>
task_work_run() forks a child that blocks reading a pipe until the
parent wakes it. If task_work__open() fails afterwards, the parent
returns without closing either pipe fd or waiting for the child.
Because the parent retains the write end, the child remains blocked in
read() until test_progs exits.
Route this failure through the common cleanup path. At this point
cleanup is safe: pe_fd is -1, link is NULL, task_work__destroy() accepts
NULL, and the pid > 0 branch closes the read end, wakes the child,
closes the write end and waits for it.
This is the last early return after a successful fork. The fork failure
path already closes both pipe fds after commit 5730dacb3f17
("selftests/bpf: Task_work selftest cleanup fixes").
Fixes: 39fd74dfd5d2 ("selftests/bpf: BPF task work scheduling tests")
Signed-off-by: Yun Lu <luyun@kylinos.cn>
---
tools/testing/selftests/bpf/prog_tests/test_task_work.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/tools/testing/selftests/bpf/prog_tests/test_task_work.c b/tools/testing/selftests/bpf/prog_tests/test_task_work.c
index 774b31a5f6ca..fe0cb1702eaa 100644
--- a/tools/testing/selftests/bpf/prog_tests/test_task_work.c
+++ b/tools/testing/selftests/bpf/prog_tests/test_task_work.c
@@ -85,7 +85,7 @@ static void task_work_run(const char *prog_name, const char *map_name)
skel = task_work__open();
if (!ASSERT_OK_PTR(skel, "task_work__open"))
- return;
+ goto cleanup;
bpf_object__for_each_program(prog, skel->obj) {
bpf_program__set_autoload(prog, false);
--
2.43.0
^ permalink raw reply related [flat|nested] 7+ messages in thread
* Re: [PATCH bpf 1/2] selftests/bpf: Fix timing-dependent assertions in task work stress test
2026-09-17 8:08 ` [PATCH bpf 1/2] selftests/bpf: Fix timing-dependent assertions in task work stress test Yun Lu
@ 2026-09-17 9:00 ` bot+bpf-ci
2026-09-17 12:31 ` luyun
2026-09-17 14:39 ` Alexei Starovoitov
1 sibling, 1 reply; 7+ messages in thread
From: bot+bpf-ci @ 2026-09-17 9:00 UTC (permalink / raw)
To: luyun_611, andrii, eddyz87, ihor.solodrai, ast, daniel, memxor,
martin.lau, song, yonghong.song, jolsa, emil, shuah
Cc: bpf, linux-kselftest, ast, andrii, daniel, martin.lau, eddyz87,
yonghong.song, mason, ihor.solodrai
[-- Attachment #1: Type: text/plain, Size: 2233 bytes --]
> task_work_run() assumes every stress run observes both scheduler
> contention and, when the delete thread is enabled, cancellation of at
> least one pending callback.
>
> Neither outcome is guaranteed. Contention is observed only when another
> scheduler selects the same one of 128 map values while its task work is
> outstanding. A valid run can therefore have no scheduling errors. This
> was reproduced with a single scheduler: more than one million callbacks
> were scheduled and completed while schedule_error remained zero.
This isn't a bug, but would it read more clearly to say something like 'the
task_work_stress test helper' (or name the file) instead of the bare
task_work_run() in the opening sentence? There are three functions with
that name in the tree: kernel/task_work.c, prog_tests/test_task_work.c, and
the static helper being changed here in prog_tests/task_work_stress.c, so
the bare name could be mistaken for the kernel function on first reading.
This isn't a bug, but was nthreads reduced locally to get the
single-scheduler run quoted here? The test hardcodes 'int nthreads = 16;'
(prog_tests/task_work_stress.c:50) and the only environment knob is
BPF_TASK_WORK_TEST_TIME for the duration. A reader trying to reproduce the
quoted numbers has no way to get there without editing the file. It might
help to say so explicitly, or give the 16-thread numbers, since the test
has no knob for the thread count.
> Likewise, a successful map deletion may remove a value after its
> callback has completed. delete_success can therefore be nonzero without
> callback_success being smaller than callback_scheduled.
>
> Drop the assertion that schedule_error is nonzero. Keep requiring exact
> callback accounting when deletion is disabled. With deletion enabled,
> allow equal counts but still reject callback_success greater than
> callback_scheduled.
>
> Fixes: c6ae18e0af5e ("selftests/bpf: add bpf task work stress tests")
> Signed-off-by: Yun Lu <luyun@kylinos.cn>
---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
CI run summary: https://github.com/kernel-patches/bpf/actions/runs/35199472874
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH bpf 1/2] selftests/bpf: Fix timing-dependent assertions in task work stress test
2026-09-17 9:00 ` bot+bpf-ci
@ 2026-09-17 12:31 ` luyun
0 siblings, 0 replies; 7+ messages in thread
From: luyun @ 2026-09-17 12:31 UTC (permalink / raw)
To: bot+bpf-ci, andrii, eddyz87, ihor.solodrai, ast, daniel, memxor,
martin.lau, song, yonghong.song, jolsa, emil, shuah
Cc: bpf, linux-kselftest, martin.lau, mason
在 2026/9/17 17:00, bot+bpf-ci@kernel.org 写道:
>> task_work_run() assumes every stress run observes both scheduler
>> contention and, when the delete thread is enabled, cancellation of at
>> least one pending callback.
>>
>> Neither outcome is guaranteed. Contention is observed only when another
>> scheduler selects the same one of 128 map values while its task work is
>> outstanding. A valid run can therefore have no scheduling errors. This
>> was reproduced with a single scheduler: more than one million callbacks
>> were scheduled and completed while schedule_error remained zero.
> This isn't a bug, but would it read more clearly to say something like 'the
> task_work_stress test helper' (or name the file) instead of the bare
> task_work_run() in the opening sentence? There are three functions with
> that name in the tree: kernel/task_work.c, prog_tests/test_task_work.c, and
> the static helper being changed here in prog_tests/task_work_stress.c, so
> the bare name could be mistaken for the kernel function on first reading.
Agreed. The opening sentence will be reworded to "The task_work_run()
helper in prog_tests/task_work_stress.c assumes ...", so it cannot be
mistaken for the kernel function of the same name.
> This isn't a bug, but was nthreads reduced locally to get the
> single-scheduler run quoted here? The test hardcodes 'int nthreads = 16;'
> (prog_tests/task_work_stress.c:50) and the only environment knob is
> BPF_TASK_WORK_TEST_TIME for the duration. A reader trying to reproduce the
> quoted numbers has no way to get there without editing the file. It might
> help to say so explicitly, or give the 16-thread numbers, since the test
> has no knob for the thread count.
Yes, that run came from a modified copy of the test with the scheduler
thread count reduced to 1. v2 will state this explicitly: "reproduced
with a modified copy of the test running a single scheduler thread
(nthreads is hardcoded to 16 and the test has no knob for it)".
These are commit message changes only; the code will be identical to
v1, and 2/2 is unchanged. If there are no further comments on the two
patches, I will send out v2 later.
Thanks,
Yun Lu
>> Likewise, a successful map deletion may remove a value after its
>> callback has completed. delete_success can therefore be nonzero without
>> callback_success being smaller than callback_scheduled.
>>
>> Drop the assertion that schedule_error is nonzero. Keep requiring exact
>> callback accounting when deletion is disabled. With deletion enabled,
>> allow equal counts but still reject callback_success greater than
>> callback_scheduled.
>>
>> Fixes: c6ae18e0af5e ("selftests/bpf: add bpf task work stress tests")
>> Signed-off-by: Yun Lu <luyun@kylinos.cn>
>
> ---
> AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
> See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md
>
> CI run summary: https://github.com/kernel-patches/bpf/actions/runs/35199472874
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH bpf 1/2] selftests/bpf: Fix timing-dependent assertions in task work stress test
2026-09-17 8:08 ` [PATCH bpf 1/2] selftests/bpf: Fix timing-dependent assertions in task work stress test Yun Lu
2026-09-17 9:00 ` bot+bpf-ci
@ 2026-09-17 14:39 ` Alexei Starovoitov
2026-09-18 2:36 ` luyun
1 sibling, 1 reply; 7+ messages in thread
From: Alexei Starovoitov @ 2026-09-17 14:39 UTC (permalink / raw)
To: Yun Lu, andrii, eddyz87, ihor.solodrai, daniel, memxor,
martin.lau, song, yonghong.song, jolsa, emil, shuah
Cc: bpf, linux-kselftest
On Thu, Sep 17, 2026 at 04:08 PM Yun Lu <luyun_611@163.com> wrote:
> From: Yun Lu <luyun@kylinos.cn>
>
> task_work_run() assumes every stress run observes both scheduler
> contention and, when the delete thread is enabled, cancellation of at
> least one pending callback.
>
> Neither outcome is guaranteed. Contention is observed only when another
> scheduler selects the same one of 128 map values while its task work is
> outstanding. A valid run can therefore have no scheduling errors. This
> was reproduced with a single scheduler: more than one million callbacks
> were scheduled and completed while schedule_error remained zero.
So it was "reproduced" by changing nthreads from 16 to 1 ?
That's not a fix. With 16 threads hammering 128 entries for a second
schedule_error > 0 and callback_success < callback_scheduled are the
point of the test. They check that the -EBUSY path in
bpf_task_work_acquire_ctx() and the cancel path in
bpf_task_work_cancel_and_free() were actual
ly exercised. Without them
the stress test only checks that nothing crashed.
If the unmodified test fails somewhere, show the log.
Patch 2 is fine on its own. Send it alone against bpf-next.
pw-bot: cr
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH bpf 1/2] selftests/bpf: Fix timing-dependent assertions in task work stress test
2026-09-17 14:39 ` Alexei Starovoitov
@ 2026-09-18 2:36 ` luyun
0 siblings, 0 replies; 7+ messages in thread
From: luyun @ 2026-09-18 2:36 UTC (permalink / raw)
To: Alexei Starovoitov, andrii, eddyz87, ihor.solodrai, daniel,
memxor, martin.lau, song, yonghong.song, jolsa, emil, shuah
Cc: bpf, linux-kselftest
在 2026/9/17 22:39, Alexei Starovoitov 写道:
> On Thu, Sep 17, 2026 at 04:08 PM Yun Lu <luyun_611@163.com> wrote:
>> From: Yun Lu <luyun@kylinos.cn>
>>
>> task_work_run() assumes every stress run observes both scheduler
>> contention and, when the delete thread is enabled, cancellation of at
>> least one pending callback.
>>
>> Neither outcome is guaranteed. Contention is observed only when another
>> scheduler selects the same one of 128 map values while its task work is
>> outstanding. A valid run can therefore have no scheduling errors. This
>> was reproduced with a single scheduler: more than one million callbacks
>> were scheduled and completed while schedule_error remained zero.
> So it was "reproduced" by changing nthreads from 16 to 1 ?
> That's not a fix. With 16 threads hammering 128 entries for a second
> schedule_error > 0 and callback_success < callback_scheduled are the
> point of the test. They check that the -EBUSY path in
> bpf_task_work_acquire_ctx() and the cancel path in
> bpf_task_work_cancel_and_free() were actual
> ly exercised. Without them
> the stress test only checks that nothing crashed.
> If the unmodified test fails somewhere, show the log.
Hi, Alexei
Thanks for the clarification. You are right that the zero-contention
result was obtained only after locally changing nthreads from 16 to 1,
so it does not reproduce a failure of the unmodified stress test.
I reran the unmodified test with nthreads = 16 for 100 iterations in
the default environment, 100 iterations with all threads restricted to
one CPU, and 100 iterations in a single-vCPU QEMU guest. All runs
passed, so I do not have a failure log for the upstream test
configuration.
>
> Patch 2 is fine on its own. Send it alone against bpf-next.
OK, I will drop patch 1 and resend patch 2 alone against bpf-next.
Thanks,
Yun Lu
>
> pw-bot: cr
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-09-18 2:37 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-17 8:08 [PATCH bpf 0/2] selftests/bpf: Fix task work false failures and cleanup Yun Lu
2026-09-17 8:08 ` [PATCH bpf 1/2] selftests/bpf: Fix timing-dependent assertions in task work stress test Yun Lu
2026-09-17 9:00 ` bot+bpf-ci
2026-09-17 12:31 ` luyun
2026-09-17 14:39 ` Alexei Starovoitov
2026-09-18 2:36 ` luyun
2026-09-17 8:08 ` [PATCH bpf 2/2] selftests/bpf: Clean up child when task_work__open() fails Yun Lu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox