Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tools/testing: Add support for prefilled slab sheafs

Add the prefilled sheaf structs to the slab header and the associated
functions to the testing/shared/linux.c file.

Signed-off-by: Liam R. Howlett <Liam.Howlett@oracle.com>
Reviewed-by: Suren Baghdasaryan <surenb@google.com>
Signed-off-by: Vlastimil Babka <vbabka@suse.cz>

authored by

Liam R. Howlett and committed by
Vlastimil Babka
fdbebab1 025f9310

+117
+28
tools/include/linux/slab.h
··· 123 123 void (*ctor)(void *); 124 124 }; 125 125 126 + struct slab_sheaf { 127 + union { 128 + struct list_head barn_list; 129 + /* only used for prefilled sheafs */ 130 + unsigned int capacity; 131 + }; 132 + struct kmem_cache *cache; 133 + unsigned int size; 134 + int node; /* only used for rcu_sheaf */ 135 + void *objects[]; 136 + }; 137 + 126 138 static inline void *kzalloc(size_t size, gfp_t gfp) 127 139 { 128 140 return kmalloc(size, gfp | __GFP_ZERO); ··· 185 173 void kmem_cache_free_bulk(struct kmem_cache *cachep, size_t size, void **list); 186 174 int kmem_cache_alloc_bulk(struct kmem_cache *cachep, gfp_t gfp, size_t size, 187 175 void **list); 176 + struct slab_sheaf * 177 + kmem_cache_prefill_sheaf(struct kmem_cache *s, gfp_t gfp, unsigned int size); 178 + 179 + void * 180 + kmem_cache_alloc_from_sheaf(struct kmem_cache *s, gfp_t gfp, 181 + struct slab_sheaf *sheaf); 182 + 183 + void kmem_cache_return_sheaf(struct kmem_cache *s, gfp_t gfp, 184 + struct slab_sheaf *sheaf); 185 + int kmem_cache_refill_sheaf(struct kmem_cache *s, gfp_t gfp, 186 + struct slab_sheaf **sheafp, unsigned int size); 187 + 188 + static inline unsigned int kmem_cache_sheaf_size(struct slab_sheaf *sheaf) 189 + { 190 + return sheaf->size; 191 + } 188 192 189 193 #endif /* _TOOLS_SLAB_H */
+89
tools/testing/shared/linux.c
··· 137 137 if (kmalloc_verbose) 138 138 pr_debug("Bulk free %p[0-%zu]\n", list, size - 1); 139 139 140 + if (cachep->exec_callback) { 141 + if (cachep->callback) 142 + cachep->callback(cachep->private); 143 + cachep->exec_callback = false; 144 + } 145 + 140 146 pthread_mutex_lock(&cachep->lock); 141 147 for (int i = 0; i < size; i++) 142 148 kmem_cache_free_locked(cachep, list[i]); ··· 246 240 ret->private = NULL; 247 241 248 242 return ret; 243 + } 244 + 245 + struct slab_sheaf * 246 + kmem_cache_prefill_sheaf(struct kmem_cache *s, gfp_t gfp, unsigned int size) 247 + { 248 + struct slab_sheaf *sheaf; 249 + unsigned int capacity; 250 + 251 + if (s->exec_callback) { 252 + if (s->callback) 253 + s->callback(s->private); 254 + s->exec_callback = false; 255 + } 256 + 257 + capacity = max(size, s->sheaf_capacity); 258 + 259 + sheaf = calloc(1, sizeof(*sheaf) + sizeof(void *) * capacity); 260 + if (!sheaf) 261 + return NULL; 262 + 263 + sheaf->cache = s; 264 + sheaf->capacity = capacity; 265 + sheaf->size = kmem_cache_alloc_bulk(s, gfp, size, sheaf->objects); 266 + if (!sheaf->size) { 267 + free(sheaf); 268 + return NULL; 269 + } 270 + 271 + return sheaf; 272 + } 273 + 274 + int kmem_cache_refill_sheaf(struct kmem_cache *s, gfp_t gfp, 275 + struct slab_sheaf **sheafp, unsigned int size) 276 + { 277 + struct slab_sheaf *sheaf = *sheafp; 278 + int refill; 279 + 280 + if (sheaf->size >= size) 281 + return 0; 282 + 283 + if (size > sheaf->capacity) { 284 + sheaf = kmem_cache_prefill_sheaf(s, gfp, size); 285 + if (!sheaf) 286 + return -ENOMEM; 287 + 288 + kmem_cache_return_sheaf(s, gfp, *sheafp); 289 + *sheafp = sheaf; 290 + return 0; 291 + } 292 + 293 + refill = kmem_cache_alloc_bulk(s, gfp, size - sheaf->size, 294 + &sheaf->objects[sheaf->size]); 295 + if (!refill) 296 + return -ENOMEM; 297 + 298 + sheaf->size += refill; 299 + return 0; 300 + } 301 + 302 + void kmem_cache_return_sheaf(struct kmem_cache *s, gfp_t gfp, 303 + struct slab_sheaf *sheaf) 304 + { 305 + if (sheaf->size) 306 + kmem_cache_free_bulk(s, sheaf->size, &sheaf->objects[0]); 307 + 308 + free(sheaf); 309 + } 310 + 311 + void * 312 + kmem_cache_alloc_from_sheaf(struct kmem_cache *s, gfp_t gfp, 313 + struct slab_sheaf *sheaf) 314 + { 315 + void *obj; 316 + 317 + if (sheaf->size == 0) { 318 + printf("Nothing left in sheaf!\n"); 319 + return NULL; 320 + } 321 + 322 + obj = sheaf->objects[--sheaf->size]; 323 + sheaf->objects[sheaf->size] = NULL; 324 + 325 + return obj; 249 326 } 250 327 251 328 /*