Summary
The test_sk_storage_map_stress_free stress test reliably fails with ENOMEM
in the BPF CI environment since mid-June 2026. The root cause is commit
5063e7758899 switching sk_storage allocations from kzalloc(GFP_KERNEL) to
kmalloc_nolock(__GFP_ZERO), which fails immediately under memory pressure
instead of reclaiming memory.
Failure Details
- Test / Component:
test_sk_storage_map_stress_free in test_maps
- Frequency: Most runs — observed in 6+ independent CI runs since June 16
- Failure mode: ENOMEM from
bpf_map_update_elem() during socket storage stress creation
- Affected architectures: x86_64, aarch64 (all architectures with KASAN enabled)
- CI runs observed:
Root Cause Analysis
The stress test creates 4 threads, each opening 4096 sockets and attaching an
sk_storage entry via bpf_map_update_elem(BPF_NOEXIST). This allocates a
bpf_local_storage_elem (~80 bytes, more with KASAN) per socket.
Commit 5063e7758899 ("bpf: Use kmalloc_nolock() universally in local
storage", 2026-04-10) changed the allocation path for SK_STORAGE from:
kzalloc(size, GFP_KERNEL | __GFP_NOWARN) // can reclaim, sleep, page out
to:
kmalloc_nolock(size, __GFP_ZERO, node) // fails immediately if pools empty
kmalloc_nolock uses per-CPU pre-allocated sheaves. It cannot reclaim memory,
invoke the OOM killer, or wait for pages to be freed. Under memory pressure it
returns NULL immediately.
The CI VMs run with:
- 4GB RAM (
VMTEST_MEMORY=4G in libbpf/ci/run-vmtest/run.sh)
CONFIG_KASAN=y + CONFIG_KASAN_GENERIC=y (in ci/vmtest/configs/config.x86_64)
KASAN roughly doubles per-allocation memory usage (shadow memory, redzones).
Combined with 16K socket+storage allocations, this exhausts the pre-allocated
pools. The test then fails because it treats any ENOMEM as a fatal error.
Why it became visible now
The test was always borderline in 4GB KASAN VMs. Recent kernel changes
(e.g., 2148794eeaf2 "bpf: Raise maximum call chain depth to 16 frames",
Jun 14) incrementally increased memory usage, pushing this past the tipping
point. The underlying cause (kmalloc_nolock can't reclaim) has been present
since April 10.
Proposed Fix
Make the test tolerate ENOMEM by breaking out of the allocation loop early.
The test's purpose is to stress the sk_storage free path (closing sockets
triggers bpf_sk_storage_free). Partial allocation + full free achieves
the same coverage.
See: output/0001-selftests-bpf-Tolerate-ENOMEM-in-sk_storage_map-stre.patch
The fix adds two early-exit checks:
socket() returning ENOMEM/ENOBUFS → break (stop creating sockets)
bpf_map_update_elem() returning ENOMEM → break (stop inserting entries)
In both cases the thread proceeds normally: it notifies completion, waits for
the map to be closed, then closes all successfully-created sockets — still
exercising the free path as intended.
Impact
Without the fix, test_maps exits with code 255, causing the entire
test_maps CI job to fail. This blocks or produces misleading red signal
for every PR that lands while this issue is active, affecting developer
confidence in the CI system.
References
Summary
The
test_sk_storage_map_stress_freestress test reliably fails with ENOMEMin the BPF CI environment since mid-June 2026. The root cause is commit
5063e7758899 switching sk_storage allocations from
kzalloc(GFP_KERNEL)tokmalloc_nolock(__GFP_ZERO), which fails immediately under memory pressureinstead of reclaiming memory.
Failure Details
test_sk_storage_map_stress_freeintest_mapsbpf_map_update_elem()during socket storage stress creationRoot Cause Analysis
The stress test creates 4 threads, each opening 4096 sockets and attaching an
sk_storage entry via
bpf_map_update_elem(BPF_NOEXIST). This allocates abpf_local_storage_elem(~80 bytes, more with KASAN) per socket.Commit
5063e7758899("bpf: Use kmalloc_nolock() universally in localstorage", 2026-04-10) changed the allocation path for SK_STORAGE from:
to:
kmalloc_nolockuses per-CPU pre-allocated sheaves. It cannot reclaim memory,invoke the OOM killer, or wait for pages to be freed. Under memory pressure it
returns NULL immediately.
The CI VMs run with:
VMTEST_MEMORY=4Ginlibbpf/ci/run-vmtest/run.sh)CONFIG_KASAN=y+CONFIG_KASAN_GENERIC=y(inci/vmtest/configs/config.x86_64)KASAN roughly doubles per-allocation memory usage (shadow memory, redzones).
Combined with 16K socket+storage allocations, this exhausts the pre-allocated
pools. The test then fails because it treats any ENOMEM as a fatal error.
Why it became visible now
The test was always borderline in 4GB KASAN VMs. Recent kernel changes
(e.g.,
2148794eeaf2"bpf: Raise maximum call chain depth to 16 frames",Jun 14) incrementally increased memory usage, pushing this past the tipping
point. The underlying cause (kmalloc_nolock can't reclaim) has been present
since April 10.
Proposed Fix
Make the test tolerate ENOMEM by breaking out of the allocation loop early.
The test's purpose is to stress the sk_storage free path (closing sockets
triggers
bpf_sk_storage_free). Partial allocation + full free achievesthe same coverage.
See:
output/0001-selftests-bpf-Tolerate-ENOMEM-in-sk_storage_map-stre.patchThe fix adds two early-exit checks:
socket()returning ENOMEM/ENOBUFS → break (stop creating sockets)bpf_map_update_elem()returning ENOMEM → break (stop inserting entries)In both cases the thread proceeds normally: it notifies completion, waits for
the map to be closed, then closes all successfully-created sockets — still
exercising the free path as intended.
Impact
Without the fix,
test_mapsexits with code 255, causing the entiretest_mapsCI job to fail. This blocks or produces misleading red signalfor every PR that lands while this issue is active, affecting developer
confidence in the CI system.
References
github/libbpf/ci/run-vmtest/run.sh(VMTEST_MEMORY=4G)github/kernel-patches/vmtest/ci/vmtest/configs/config.x86_64