1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef IOU_ALLOC_CACHE_H 3 #define IOU_ALLOC_CACHE_H 4 5 #include <linux/io_uring_types.h> 6 #include <linux/kasan.h> 7 8 /* 9 * Don't allow the cache to grow beyond this size. 10 */ 11 #define IO_ALLOC_CACHE_MAX 128 12 13 void io_alloc_cache_free(struct io_alloc_cache *cache, 14 void (*free)(const void *)); 15 bool io_alloc_cache_init(struct io_alloc_cache *cache, 16 unsigned max_nr, unsigned int size, 17 unsigned int init_bytes); 18 19 void *io_cache_alloc_new(struct io_alloc_cache *cache, gfp_t gfp); 20 21 static inline bool io_alloc_cache_put(struct io_alloc_cache *cache, 22 void *entry) 23 { 24 if (cache->nr_cached < cache->max_cached) { 25 if (!kasan_mempool_poison_object(entry)) 26 return false; 27 cache->entries[cache->nr_cached++] = entry; 28 return true; 29 } 30 return false; 31 } 32 33 static inline void *io_alloc_cache_get(struct io_alloc_cache *cache) 34 { 35 if (cache->nr_cached) { 36 void *entry = cache->entries[--cache->nr_cached]; 37 38 /* 39 * If KASAN is enabled, always clear the initial bytes that 40 * must be zeroed post alloc, in case any of them overlap 41 * with KASAN storage. 42 */ 43 #if defined(CONFIG_KASAN) 44 kasan_mempool_unpoison_object(entry, cache->elem_size); 45 if (cache->init_clear) 46 memset(entry, 0, cache->init_clear); 47 #endif 48 return entry; 49 } 50 51 return NULL; 52 } 53 54 static inline void *io_cache_alloc(struct io_alloc_cache *cache, gfp_t gfp) 55 { 56 void *obj; 57 58 obj = io_alloc_cache_get(cache); 59 if (obj) 60 return obj; 61 return io_cache_alloc_new(cache, gfp); 62 } 63 64 static inline void io_cache_free(struct io_alloc_cache *cache, void *obj) 65 { 66 if (!io_alloc_cache_put(cache, obj)) 67 kfree(obj); 68 } 69 70 #endif 71