xref: /linux/io_uring/alloc_cache.h (revision 37a93dd5c49b5fda807fd204edf2547c3493319c)
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