xref: /spdk/lib/ftl/utils/ftl_mempool.c (revision a6dbe3721eb3b5990707fc3e378c95e505dd8ab5)
1 /*   SPDX-License-Identifier: BSD-3-Clause
2  *   Copyright (C) 2022 Intel Corporation.
3  *   All rights reserved.
4  */
5 
6 #include "spdk/stdinc.h"
7 #include "spdk/queue.h"
8 #include "spdk/util.h"
9 #include "spdk/env.h"
10 #include "spdk/likely.h"
11 
12 #include "ftl_mempool.h"
13 #include "ftl_bitmap.h"
14 
15 struct ftl_mempool_element {
16 	SLIST_ENTRY(ftl_mempool_element) entry;
17 };
18 
19 struct ftl_mempool {
20 	SLIST_HEAD(, ftl_mempool_element) list;
21 	size_t element_size;
22 	void *buffer;
23 	size_t buffer_size;
24 	size_t count;
25 	size_t alignment;
26 	int socket_id;
27 	struct ftl_bitmap *inuse_bmp;
28 	void *inuse_buf;
29 };
30 
31 static inline bool is_element_valid(struct ftl_mempool *mpool,
32 				    void *element)  __attribute__((unused));
33 
34 static inline bool ftl_mempool_is_initialized(struct ftl_mempool *mpool) __attribute__((unused));
35 
36 static size_t
element_size_aligned(size_t size,size_t alignment)37 element_size_aligned(size_t size, size_t alignment)
38 {
39 	if (!alignment) {
40 		return size;
41 	}
42 
43 	if (size % alignment) {
44 		return (size / alignment + 1) * alignment;
45 	}
46 
47 	return size;
48 }
49 
50 static inline bool
is_element_valid(struct ftl_mempool * mpool,void * element)51 is_element_valid(struct ftl_mempool *mpool, void *element)
52 {
53 	if (element < mpool->buffer) {
54 		return false;
55 	}
56 
57 	if (element + mpool->element_size > mpool->buffer + mpool->buffer_size) {
58 		return false;
59 	}
60 
61 	if (!mpool->alignment) {
62 		return true;
63 	}
64 
65 	if ((size_t)element % mpool->alignment) {
66 		return false;
67 	}
68 
69 	if ((element - mpool->buffer) % mpool->element_size != 0) {
70 		return false;
71 	}
72 
73 	return true;
74 }
75 
ftl_mempool_create(size_t count,size_t size,size_t alignment,int socket_id)76 struct ftl_mempool *ftl_mempool_create(size_t count, size_t size,
77 				       size_t alignment, int socket_id)
78 {
79 	struct ftl_mempool *mp;
80 	void *buffer;
81 	size_t i;
82 
83 	assert(count > 0);
84 	assert(size > 0);
85 
86 	if (!spdk_u64_is_pow2(alignment)) {
87 		return NULL;
88 	}
89 
90 	mp = calloc(1, sizeof(*mp));
91 	if (!mp) {
92 		return NULL;
93 	}
94 
95 	size = spdk_max(size, sizeof(struct ftl_mempool_element));
96 
97 	mp->count = count;
98 	mp->element_size = element_size_aligned(size, alignment);
99 	mp->alignment = alignment;
100 	mp->socket_id = socket_id;
101 	SLIST_INIT(&mp->list);
102 
103 	mp->buffer_size = mp->element_size * mp->count;
104 	mp->buffer = spdk_dma_malloc_socket(mp->buffer_size, mp->alignment,
105 					    NULL, socket_id);
106 	if (!mp->buffer) {
107 		free(mp);
108 		return NULL;
109 	}
110 
111 	buffer = mp->buffer;
112 	for (i = 0; i < count; i++, buffer += mp->element_size) {
113 		struct ftl_mempool_element *el = buffer;
114 		assert(is_element_valid(mp, el));
115 		SLIST_INSERT_HEAD(&mp->list, el, entry);
116 	}
117 
118 	return mp;
119 }
120 
121 void
ftl_mempool_destroy(struct ftl_mempool * mpool)122 ftl_mempool_destroy(struct ftl_mempool *mpool)
123 {
124 	if (!mpool) {
125 		return;
126 	}
127 
128 	spdk_dma_free(mpool->buffer);
129 	free(mpool);
130 }
131 
132 static inline bool
ftl_mempool_is_initialized(struct ftl_mempool * mpool)133 ftl_mempool_is_initialized(struct ftl_mempool *mpool)
134 {
135 	return mpool->inuse_buf == NULL;
136 }
137 
138 void *
ftl_mempool_get(struct ftl_mempool * mpool)139 ftl_mempool_get(struct ftl_mempool *mpool)
140 {
141 	struct ftl_mempool_element *el;
142 
143 	assert(ftl_mempool_is_initialized(mpool));
144 	if (spdk_unlikely(SLIST_EMPTY(&mpool->list))) {
145 		return NULL;
146 	}
147 
148 	el = SLIST_FIRST(&mpool->list);
149 	SLIST_REMOVE_HEAD(&mpool->list, entry);
150 
151 	return el;
152 }
153 
154 void
ftl_mempool_put(struct ftl_mempool * mpool,void * element)155 ftl_mempool_put(struct ftl_mempool *mpool, void *element)
156 {
157 	struct ftl_mempool_element *el = element;
158 
159 	assert(ftl_mempool_is_initialized(mpool));
160 	assert(is_element_valid(mpool, element));
161 	SLIST_INSERT_HEAD(&mpool->list, el, entry);
162 }
163 
164 struct ftl_mempool *
ftl_mempool_create_ext(void * buffer,size_t count,size_t size,size_t alignment)165 ftl_mempool_create_ext(void *buffer, size_t count, size_t size, size_t alignment)
166 {
167 	struct ftl_mempool *mp;
168 	size_t inuse_buf_sz;
169 
170 	assert(buffer);
171 	assert(count > 0);
172 	assert(size > 0);
173 
174 	mp = calloc(1, sizeof(*mp));
175 	if (!mp) {
176 		goto error;
177 	}
178 
179 	size = spdk_max(size, sizeof(struct ftl_mempool_element));
180 
181 	mp->count = count;
182 	mp->element_size = element_size_aligned(size, alignment);
183 	mp->alignment = alignment;
184 	SLIST_INIT(&mp->list);
185 
186 	/* Calculate underlying inuse_bmp's buf size */
187 	inuse_buf_sz = spdk_divide_round_up(mp->count, 8);
188 	/* The bitmap size must be a multiple of word size (8b) - round up */
189 	if (inuse_buf_sz & 7UL) {
190 		inuse_buf_sz &= ~7UL;
191 		inuse_buf_sz += 8;
192 	}
193 
194 	mp->inuse_buf = calloc(1, inuse_buf_sz);
195 	if (!mp->inuse_buf) {
196 		goto error;
197 	}
198 
199 	mp->inuse_bmp = ftl_bitmap_create(mp->inuse_buf, inuse_buf_sz);
200 	if (!mp->inuse_bmp) {
201 		goto error;
202 	}
203 
204 	/* Map the buffer */
205 	mp->buffer_size = mp->element_size * mp->count;
206 	mp->buffer = buffer;
207 
208 	return mp;
209 
210 error:
211 	ftl_mempool_destroy_ext(mp);
212 	return NULL;
213 }
214 
215 void
ftl_mempool_destroy_ext(struct ftl_mempool * mpool)216 ftl_mempool_destroy_ext(struct ftl_mempool *mpool)
217 {
218 	if (!mpool) {
219 		return;
220 	}
221 
222 	if (mpool->inuse_bmp) {
223 		ftl_bitmap_destroy(mpool->inuse_bmp);
224 	}
225 	free(mpool->inuse_buf);
226 	free(mpool);
227 }
228 
229 void
ftl_mempool_initialize_ext(struct ftl_mempool * mpool)230 ftl_mempool_initialize_ext(struct ftl_mempool *mpool)
231 {
232 	struct ftl_mempool_element *el;
233 	void *buffer = mpool->buffer;
234 	size_t i;
235 
236 	assert(!ftl_mempool_is_initialized(mpool));
237 
238 	for (i = 0; i < mpool->count; i++, buffer += mpool->element_size) {
239 		if (ftl_bitmap_get(mpool->inuse_bmp, i)) {
240 			continue;
241 		}
242 		el = buffer;
243 		assert(is_element_valid(mpool, el));
244 		SLIST_INSERT_HEAD(&mpool->list, el, entry);
245 	}
246 
247 	ftl_bitmap_destroy(mpool->inuse_bmp);
248 	mpool->inuse_bmp = NULL;
249 
250 	free(mpool->inuse_buf);
251 	mpool->inuse_buf = NULL;
252 }
253 
254 ftl_df_obj_id
ftl_mempool_get_df_obj_id(struct ftl_mempool * mpool,void * df_obj_ptr)255 ftl_mempool_get_df_obj_id(struct ftl_mempool *mpool, void *df_obj_ptr)
256 {
257 	return ftl_df_get_obj_id(mpool->buffer, df_obj_ptr);
258 }
259 
260 size_t
ftl_mempool_get_df_obj_index(struct ftl_mempool * mpool,void * df_obj_ptr)261 ftl_mempool_get_df_obj_index(struct ftl_mempool *mpool, void *df_obj_ptr)
262 {
263 	return ftl_mempool_get_df_obj_id(mpool, df_obj_ptr) / mpool->element_size;
264 }
265 
266 void *
ftl_mempool_get_df_ptr(struct ftl_mempool * mpool,ftl_df_obj_id df_obj_id)267 ftl_mempool_get_df_ptr(struct ftl_mempool *mpool, ftl_df_obj_id df_obj_id)
268 {
269 	return ftl_df_get_obj_ptr(mpool->buffer, df_obj_id);
270 }
271 
272 void *
ftl_mempool_claim_df(struct ftl_mempool * mpool,ftl_df_obj_id df_obj_id)273 ftl_mempool_claim_df(struct ftl_mempool *mpool, ftl_df_obj_id df_obj_id)
274 {
275 	struct ftl_mempool_element *el = ftl_df_get_obj_ptr(mpool->buffer, df_obj_id);
276 
277 	assert(!ftl_mempool_is_initialized(mpool));
278 	assert(df_obj_id % mpool->element_size == 0);
279 	assert(df_obj_id / mpool->element_size < mpool->count);
280 
281 	ftl_bitmap_set(mpool->inuse_bmp, df_obj_id / mpool->element_size);
282 	return el;
283 }
284 
285 void
ftl_mempool_release_df(struct ftl_mempool * mpool,ftl_df_obj_id df_obj_id)286 ftl_mempool_release_df(struct ftl_mempool *mpool, ftl_df_obj_id df_obj_id)
287 {
288 	assert(!ftl_mempool_is_initialized(mpool));
289 	assert(df_obj_id % mpool->element_size == 0);
290 	assert(df_obj_id / mpool->element_size < mpool->count);
291 
292 	ftl_bitmap_clear(mpool->inuse_bmp, df_obj_id / mpool->element_size);
293 }
294