linux/tools/testing/selftests/bpf/progs/lru_lock_nmi.c
Mykyta Yatsenko 6e1e4a9d60 selftests/bpf: Stress LRU rqspinlock recovery paths
Introduces stress test for bpf_lru_list that exercises
lock-failures and orphan-recovery, added by the LRU rqspinlock
conversion.

Runs three subtests: common LRU, per-CPU LRU lists (BPF_F_NO_COMMON_LRU),
and per-CPU LRU map. Each pins one userspace hammer per CPU and attaches
the perf_event NMI BPF prog (update+delete mix) on every online CPU.
Pre-fix, lockdep fires the "INITIAL USE -> IN-NMI" splat during stress.

After stress test, drain_then_verify_capacity() drains every key
and refills the lru map.
A stranded node on any CPU's pool would have forced eviction of
a just-inserted key on that CPU, surfacing here as a missing lookup.

Marked serial_ because per-CPU pinning and high-rate HW perf events
would perturb parallel tests.

Signed-off-by: Mykyta Yatsenko <yatsenko@meta.com>
Link: https://lore.kernel.org/r/20260607-lru_map_spin-v3-3-bcd9332e911b@meta.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
2026-06-07 18:46:13 -07:00

34 lines
695 B
C

// SPDX-License-Identifier: GPL-2.0
#include <vmlinux.h>
#include <bpf/bpf_helpers.h>
struct {
__uint(type, BPF_MAP_TYPE_LRU_HASH);
__uint(max_entries, 64);
__type(key, __u32);
__type(value, __u64);
} lru_map SEC(".maps");
int hits;
SEC("perf_event")
int oncpu(void *ctx)
{
/*
* Key range deliberately wider than max_entries to force LRU
* eviction on every other update.
*/
__u32 key = bpf_get_prandom_u32() % 128;
bool do_update = bpf_get_prandom_u32() & 1;
__u64 val = 1;
if (do_update)
bpf_map_update_elem(&lru_map, &key, &val, BPF_ANY);
else
bpf_map_delete_elem(&lru_map, &key);
__sync_fetch_and_add(&hits, 1);
return 0;
}
char _license[] SEC("license") = "GPL";