Re: [PATCH bpf-next 4/5] selftests/bpf: Avoid flaky resize value test for percpu data

Leon Hwang <[email protected]>
Newsgroups org.kernel.vger.linux-kselftest,org.kernel.vger.bpf,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
On 15/8/26 02:24, [email protected] wrote:
>> diff --git a/tools/testing/selftests/bpf/prog_tests/global_data_init.c b/tools/testing/selftests/bpf/prog_tests/global_data_init.c
>> index 7d6bda909295..2f0dbeb88934 100644
>> --- a/tools/testing/selftests/bpf/prog_tests/global_data_init.c
>> +++ b/tools/testing/selftests/bpf/prog_tests/global_data_init.c
> 
> [ ... ]
> 
>> @@ -126,11 +123,11 @@ static void test_percpu_data_on_cpus(struct bpf_map *map, int map_fd, int prog_f
>>  static void test_global_percpu_data_init(void)
>>  {
>>  	struct test_global_percpu_data__percpu init_value = {};
>> +	const __u32 desired_sz = sysconf(_SC_PAGE_SIZE) * 2;
>>  	struct test_global_percpu_data__percpu *init_data;
>> -	const __u32 desired_sz = sysconf(_SC_PAGE_SIZE);
> 
> Does multiplying by 2 here break the test on 64K page systems?
> 
> Per-CPU array value sizes are capped by the kernel:
> 
>   /* percpu map value size is bound by PCPU_MIN_UNIT_SIZE */
>   if (percpu && round_up(attr->value_size, 8) > PCPU_MIN_UNIT_SIZE)
>           return -E2BIG;
> 
> in kernel/bpf/arraymap.c:array_map_alloc_check(), where PCPU_MIN_UNIT_SIZE
> is defined as:
> 
>   #define PCPU_MIN_UNIT_SIZE  PFN_ALIGN(32 << 10)
> 
> which equals max(32768, PAGE_SIZE).
> 
> The old code was safe by construction: desired_sz == PAGE_SIZE <=
> PFN_ALIGN(32768) == PCPU_MIN_UNIT_SIZE. Doubling it breaks that:
> 
>   PAGE_SIZE  4096 -> limit 32768, request   8192  OK
>   PAGE_SIZE 16384 -> limit 32768, request  32768  OK (exactly at limit)
>   PAGE_SIZE 65536 -> limit 65536, request 131072  -E2BIG
> 
> On kernels built with 64K pages (arm64 CONFIG_ARM64_64K_PAGES, ppc64)
> bpf_map__set_value_size() still succeeds (it is purely userspace
> bookkeeping), all four assertions that follow it pass, and then map
> creation fails inside test_global_percpu_data__load():
> 
>>  	err = test_global_percpu_data__load(skel);
>>  	if (!ASSERT_OK(err, "test_global_percpu_data__load"))
>>  		goto out;
> 
> The "global_percpu_data/init" subtest fails, and test_percpu_data_on_cpus()
> is never reached. That is a new failure introduced by this patch (with
> desired_sz == PAGE_SIZE the same configuration created a 65536-byte per-CPU
> value, which is exactly at the limit and accepted).
> 
> Note that the neighbouring resize test in global_map_resize.c deliberately
> does not scale a per-CPU map by page size for this reason. At line 46 it
> uses:
> 
>   new_sz = sizeof(skel->data_percpu_arr->percpu_arr[0]) *
>            libbpf_num_possible_cpus();
> 
> A size that is independent of PAGE_SIZE would still force the mmap region
> to move, which is what the new skel->percpu_arr reassignment and the
> arr[0] == -1 check are there to exercise, without hitting the per-CPU
> allocator bound.
> 

To avoid breaking the test on 64K page systems, run the resize subtest
only on 4K page systems.

From maintenance view, I think it's better to add a dedicated subtest to
test bpf_map__set_value_size() for percpu data. Then, it will be able to
skip the subtest when sysconf(_SC_PAGE_SIZE) != 4K.

Thanks,
Leon
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.