xref: /linux-6.15/io_uring/alloc_cache.h (revision fa359552)
1 #ifndef IOU_ALLOC_CACHE_H
2 #define IOU_ALLOC_CACHE_H
3 
4 /*
5  * Don't allow the cache to grow beyond this size.
6  */
7 #define IO_ALLOC_CACHE_MAX	128
8 
9 #if defined(CONFIG_KASAN)
10 static inline void io_alloc_cache_kasan(struct iovec **iov, int *nr)
11 {
12 	kfree(*iov);
13 	*iov = NULL;
14 	*nr = 0;
15 }
16 #else
17 static inline void io_alloc_cache_kasan(struct iovec **iov, int *nr)
18 {
19 }
20 #endif
21 
22 static inline bool io_alloc_cache_put(struct io_alloc_cache *cache,
23 				      void *entry)
24 {
25 	if (cache->nr_cached < cache->max_cached) {
26 		if (!kasan_mempool_poison_object(entry))
27 			return false;
28 		cache->entries[cache->nr_cached++] = entry;
29 		return true;
30 	}
31 	return false;
32 }
33 
34 static inline void *io_alloc_cache_get(struct io_alloc_cache *cache)
35 {
36 	if (cache->nr_cached) {
37 		void *entry = cache->entries[--cache->nr_cached];
38 
39 		/*
40 		 * If KASAN is enabled, always clear the initial bytes that
41 		 * must be zeroed post alloc, in case any of them overlap
42 		 * with KASAN storage.
43 		 */
44 #if defined(CONFIG_KASAN)
45 		kasan_mempool_unpoison_object(entry, cache->elem_size);
46 		if (cache->init_clear)
47 			memset(entry, 0, cache->init_clear);
48 #endif
49 		return entry;
50 	}
51 
52 	return NULL;
53 }
54 
55 static inline void *io_cache_alloc(struct io_alloc_cache *cache, gfp_t gfp)
56 {
57 	void *obj;
58 
59 	obj = io_alloc_cache_get(cache);
60 	if (obj)
61 		return obj;
62 
63 	obj = kmalloc(cache->elem_size, gfp);
64 	if (obj && cache->init_clear)
65 		memset(obj, 0, cache->init_clear);
66 	return obj;
67 }
68 
69 /* returns false if the cache was initialized properly */
70 static inline bool io_alloc_cache_init(struct io_alloc_cache *cache,
71 				       unsigned max_nr, unsigned int size,
72 				       unsigned int init_bytes)
73 {
74 	cache->entries = kvmalloc_array(max_nr, sizeof(void *), GFP_KERNEL);
75 	if (cache->entries) {
76 		cache->nr_cached = 0;
77 		cache->max_cached = max_nr;
78 		cache->elem_size = size;
79 		cache->init_clear = init_bytes;
80 		return false;
81 	}
82 	return true;
83 }
84 
85 static inline void io_alloc_cache_free(struct io_alloc_cache *cache,
86 				       void (*free)(const void *))
87 {
88 	void *entry;
89 
90 	if (!cache->entries)
91 		return;
92 
93 	while ((entry = io_alloc_cache_get(cache)) != NULL)
94 		free(entry);
95 
96 	kvfree(cache->entries);
97 	cache->entries = NULL;
98 }
99 #endif
100