From: Liam R. Howlett Date: Tue, 3 Dec 2024 16:46:31 +0000 (-0500) Subject: tools: Add sheafs support to testing infrastructure X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=450aaa98a0c2342e255a76b7b4b950c0c60ddbe1;p=users%2Fjedix%2Flinux-maple.git tools: Add sheafs support to testing infrastructure Allocate a sheaf and fill it to the count amount. Does not fill to the sheaf limit to detect incorrect allocation requests. Signed-off-by: Liam R. Howlett --- diff --git a/tools/include/linux/slab.h b/tools/include/linux/slab.h index a475364cfd9f..f466a4135c5c 100644 --- a/tools/include/linux/slab.h +++ b/tools/include/linux/slab.h @@ -22,6 +22,13 @@ enum slab_state { FULL }; +struct slab_sheaf { + struct kmem_cache *cache; + unsigned int size; + bool oversized; + void *objects[]; +}; + struct kmem_cache_args { unsigned int align; unsigned int sheaf_capacity; @@ -79,4 +86,21 @@ void kmem_cache_free_bulk(struct kmem_cache *cachep, size_t size, void **list); int kmem_cache_alloc_bulk(struct kmem_cache *cachep, gfp_t gfp, size_t size, void **list); +struct slab_sheaf * +kmem_cache_prefill_sheaf(struct kmem_cache *s, gfp_t gfp, unsigned int count); + +void * +kmem_cache_alloc_from_sheaf(struct kmem_cache *s, gfp_t gfp, + struct slab_sheaf *sheaf); + +void kmem_cache_return_sheaf(struct kmem_cache *s, gfp_t gfp, + struct slab_sheaf *sheaf); +int kmem_cache_refill_sheaf(struct kmem_cache *s, gfp_t gfp, + struct slab_sheaf *sheaf); + +static inline unsigned int kmem_cache_sheaf_count(struct slab_sheaf *sheaf) +{ + return sheaf->size; +} + #endif /* _TOOLS_SLAB_H */ diff --git a/tools/testing/shared/linux.c b/tools/testing/shared/linux.c index 9f5fd722f27f..6936d3f7acf2 100644 --- a/tools/testing/shared/linux.c +++ b/tools/testing/shared/linux.c @@ -181,6 +181,12 @@ int kmem_cache_alloc_bulk(struct kmem_cache *cachep, gfp_t gfp, size_t size, if (kmalloc_verbose) pr_debug("Bulk alloc %lu\n", size); + if (cachep->exec_callback) { + if (cachep->callback) + cachep->callback(cachep->private); + cachep->exec_callback = false; + } + pthread_mutex_lock(&cachep->lock); if (cachep->nr_objs >= size) { struct radix_tree_node *node; @@ -270,6 +276,77 @@ __kmem_cache_create_args(const char *name, unsigned int size, return ret; } +struct slab_sheaf * +kmem_cache_prefill_sheaf(struct kmem_cache *s, gfp_t gfp, unsigned int count) +{ + struct slab_sheaf *sheaf; + size_t size; + bool oversized = false; + + if (count > s->sheaf_capacity) { + size = sizeof(*sheaf) + sizeof(void *) * count; + oversized = true; + } else { + size = sizeof(*sheaf) + sizeof(void *) * s->sheaf_capacity; + } + + sheaf = malloc(size); + if (!sheaf) { + return NULL; + } + + memset(sheaf, 0, size); + sheaf->cache = s; + sheaf->oversized = oversized; + sheaf->size = kmem_cache_alloc_bulk(s, gfp, count, sheaf->objects); + if (!sheaf->size) { + free(sheaf); + return NULL; + } + + return sheaf; +} + +int kmem_cache_refill_sheaf(struct kmem_cache *s, gfp_t gfp, + struct slab_sheaf *sheaf) +{ + unsigned char refill; + + refill = s->sheaf_capacity - sheaf->size; + if (!refill) + return 0; + + refill = kmem_cache_alloc_bulk(s, gfp, refill, + &sheaf->objects[sheaf->size]); + if (!refill) + return -ENOMEM; + + sheaf->size += refill; + return 0; +} + +void kmem_cache_return_sheaf(struct kmem_cache *s, gfp_t gfp, + struct slab_sheaf *sheaf) +{ + if (sheaf->size) { + //s->non_kernel += sheaf->size; + kmem_cache_free_bulk(s, sheaf->size, &sheaf->objects[0]); + } + free(sheaf); +} + +void * +kmem_cache_alloc_from_sheaf(struct kmem_cache *s, gfp_t gfp, + struct slab_sheaf *sheaf) +{ + if (sheaf->size == 0) { + printf("Nothing left in sheaf!\n"); + return NULL; + } + + return sheaf->objects[--sheaf->size]; +} + /* * Test the test infrastructure for kem_cache_alloc/free and bulk counterparts. */