We now use different code paths in the internal allocator when allocating arena memory, depending on whether the caller is sleepable or not. These paths mostly differ functionally for large allocations, so add extra testing for that case. Signed-off-by: Emil Tsalapatis --- .../bpf/progs/verifier_arena_large.c | 59 +++++++++++++++---- 1 file changed, 49 insertions(+), 10 deletions(-) diff --git a/tools/testing/selftests/bpf/progs/verifier_arena_large.c b/tools/testing/selftests/bpf/progs/verifier_arena_large.c index 6ab8730d4878..e002815b6929 100644 --- a/tools/testing/selftests/bpf/progs/verifier_arena_large.c +++ b/tools/testing/selftests/bpf/progs/verifier_arena_large.c @@ -11,6 +11,8 @@ #define ARENA_SIZE (1ull << 32) +volatile int zero = 0; + struct { __uint(type, BPF_MAP_TYPE_ARENA); __uint(map_flags, BPF_F_MMAPABLE); @@ -284,6 +286,7 @@ int big_alloc2(void *ctx) return 0; } +/* Nonsleepable because it binds to a socket program. */ SEC("socket") __success __retval(0) int big_alloc3(void *ctx) @@ -291,24 +294,60 @@ int big_alloc3(void *ctx) #if defined(__BPF_FEATURE_ADDR_SPACE_CAST) char __arena *pages; u64 i; + int err = 0; /* - * Allocate 2051 pages in one go to check how kmalloc_nolock() handles large requests. - * Since kmalloc_nolock() can allocate up to 1024 struct page * at a time, this call should - * result in three batches: two batches of 1024 pages each, followed by a final batch of 3 - * pages. + * Allocate 1025 pages in one go to check how kmalloc_nolock() handles large requests. + * Since kmalloc_nolock() can allocate up to 1024 struct page * at a time, this is the + * smallest request that exercises multiple batches, limiting the time spent with IRQs + * disabled. */ + pages = bpf_arena_alloc_pages(&arena, NULL, 1025, NUMA_NO_NODE, 0); + if (!pages) + return 1; + + for (i = zero; i < 1025 && can_loop; i++) + pages[i * PAGE_SIZE] = 123; + + for (i = zero; i < 1025 && can_loop; i++) { + if (pages[i * PAGE_SIZE] == 123) + continue; + err = 2; + break; + } + + bpf_arena_free_pages(&arena, pages, 1025); + return err; +#endif + return 0; +} + +/* SYSCALL programs are always sleepable. */ +SEC("syscall") +__success __retval(0) +int big_alloc4(void *ctx) +{ +#if defined(__BPF_FEATURE_ADDR_SPACE_CAST) + char __arena *pages; + u64 i; + int err = 0; + pages = bpf_arena_alloc_pages(&arena, NULL, 2051, NUMA_NO_NODE, 0); if (!pages) - return 0; + return 1; - bpf_for(i, 0, 2051) - pages[i * PAGE_SIZE] = 123; - bpf_for(i, 0, 2051) - if (pages[i * PAGE_SIZE] != 123) - return i; + for (i = zero; i < 2051 && can_loop; i++) + pages[i * PAGE_SIZE] = 123; + + for (i = zero; i < 2051 && can_loop; i++) { + if (pages[i * PAGE_SIZE] == 123) + continue; + err = 2; + break; + } bpf_arena_free_pages(&arena, pages, 2051); + return err; #endif return 0; } -- 2.52.0