From: Yun Lu Add a deleted-value case to task_work_stress. A syscall program looks up a HASH value, deletes it and schedules task work through the retained pointer. Assert that scheduling returns -ENOENT; positive step codes distinguish setup failures from the unfixed kernel's return value of 0. Reuse process_work(), which only counts callbacks and does not dereference the old key or value. Signed-off-by: Yun Lu --- ...elftests/bpf/prog_tests/task_work_stress.c | 18 ++++++++++++++++++ ...ing/selftests/bpf/progs/task_work_stress.c | 17 +++++++++++++++++ 2 files changed, 35 insertions(+) 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..90d6d696537d 100644 --- a/tools/testing/selftests/bpf/prog_tests/task_work_stress.c +++ b/tools/testing/selftests/bpf/prog_tests/task_work_stress.c @@ -121,8 +121,26 @@ cleanup: task_work_stress__destroy(skel); } +static void task_work_deleted(void) +{ + LIBBPF_OPTS(bpf_test_run_opts, opts); + struct task_work_stress *skel; + int err; + + skel = task_work_stress__open_and_load(); + if (!ASSERT_OK_PTR(skel, "open_and_load")) + return; + err = bpf_prog_test_run_opts(bpf_program__fd(skel->progs.schedule_deleted_task_work), + &opts); + if (ASSERT_OK(err, "schedule_deleted_task_work")) + ASSERT_EQ((int)opts.retval, -ENOENT, "deleted schedule rejected"); + task_work_stress__destroy(skel); +} + void test_task_work_stress(void) { + if (test__start_subtest("deleted")) + task_work_deleted(); if (test__start_subtest("no_delete")) task_work_run(false); if (test__start_subtest("with_delete")) diff --git a/tools/testing/selftests/bpf/progs/task_work_stress.c b/tools/testing/selftests/bpf/progs/task_work_stress.c index 1d4378f351ef..5f47133ad308 100644 --- a/tools/testing/selftests/bpf/progs/task_work_stress.c +++ b/tools/testing/selftests/bpf/progs/task_work_stress.c @@ -71,3 +71,20 @@ int delete_task_work(void *ctx) __sync_fetch_and_add(&delete_success, 1); return 0; } + +SEC("syscall") +int schedule_deleted_task_work(void *ctx) +{ + struct elem empty = {}, *value; + int key = 0; + + if (bpf_map_update_elem(&hmap, &key, &empty, BPF_NOEXIST)) + return 1; + value = bpf_map_lookup_elem(&hmap, &key); + if (!value) + return 2; + if (bpf_map_delete_elem(&hmap, &key)) + return 3; + return bpf_task_work_schedule_signal(bpf_get_current_task_btf(), + &value->tw, &hmap, process_work); +} -- 2.43.0