On Sun, Apr 07, 2024 at 09:08:48PM +0800, Yunsheng Lin wrote: > Basing on the lib/objpool.c, change it to something like a > ptrpool, so that we can utilize that to test the correctness > and performance of the page_frag. > > The testing is done by ensuring that the fragments allocated > from a frag_frag_cache instance is pushed into a ptrpool > instance in a kthread binded to the first cpu, and a kthread > binded to the current node will pop the fragmemt from the > ptrpool and call page_frag_alloc_va() to free the fragmemt. > > We may refactor out the common part between objpool and ptrpool > if this ptrpool thing turns out to be helpful for other place. > > Signed-off-by: Yunsheng Lin <linyunsheng@xxxxxxxxxx> ... > diff --git a/mm/page_frag_test.c b/mm/page_frag_test.c ... > +/* allocate and initialize percpu slots */ > +static int objpool_init_percpu_slots(struct objpool_head *pool, > + int nr_objs, gfp_t gfp) > +{ > + int i; > + > + for (i = 0; i < pool->nr_cpus; i++) { > + struct objpool_slot *slot; > + int size; > + > + /* skip the cpu node which could never be present */ > + if (!cpu_possible(i)) > + continue; > + > + size = struct_size(slot, entries, pool->capacity); > + > + /* > + * here we allocate percpu-slot & objs together in a single > + * allocation to make it more compact, taking advantage of > + * warm caches and TLB hits. in default vmalloc is used to > + * reduce the pressure of kernel slab system. as we know, > + * mimimal size of vmalloc is one page since vmalloc would nit: minimal > + * always align the requested size to page size > + */ > + if (gfp & GFP_ATOMIC) > + slot = kmalloc_node(size, gfp, cpu_to_node(i)); > + else > + slot = __vmalloc_node(size, sizeof(void *), gfp, > + cpu_to_node(i), > + __builtin_return_address(0)); > + if (!slot) > + return -ENOMEM; > + > + memset(slot, 0, size); > + pool->cpu_slots[i] = slot; > + > + objpool_init_percpu_slot(pool, slot); > + } > + > + return 0; > +} ... > +static struct objpool_head ptr_pool; > +static int nr_objs = 512; > +static int nr_test = 5120000; > +static atomic_t nthreads; > +static struct completion wait; > +struct page_frag_cache test_frag; nit: Is test_frag used outside of this file? If not, should it be static? ...