]>
Commit | Line | Data |
---|---|---|
715f6251 | 1 | /* |
2 | * This file is part of the SPL: Solaris Porting Layer. | |
3 | * | |
4 | * Copyright (c) 2008 Lawrence Livermore National Security, LLC. | |
5 | * Produced at Lawrence Livermore National Laboratory | |
6 | * Written by: | |
7 | * Brian Behlendorf <behlendorf1@llnl.gov>, | |
8 | * Herb Wartens <wartens2@llnl.gov>, | |
9 | * Jim Garlick <garlick@llnl.gov> | |
10 | * UCRL-CODE-235197 | |
11 | * | |
12 | * This is free software; you can redistribute it and/or modify it | |
13 | * under the terms of the GNU General Public License as published by | |
14 | * the Free Software Foundation; either version 2 of the License, or | |
15 | * (at your option) any later version. | |
16 | * | |
17 | * This is distributed in the hope that it will be useful, but WITHOUT | |
18 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
19 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
20 | * for more details. | |
21 | * | |
22 | * You should have received a copy of the GNU General Public License along | |
23 | * with this program; if not, write to the Free Software Foundation, Inc., | |
24 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |
25 | */ | |
26 | ||
7c50328b | 27 | #include "splat-internal.h" |
f1ca4da6 | 28 | |
7c50328b | 29 | #define SPLAT_SUBSYSTEM_KMEM 0x0100 |
30 | #define SPLAT_KMEM_NAME "kmem" | |
31 | #define SPLAT_KMEM_DESC "Kernel Malloc/Slab Tests" | |
f1ca4da6 | 32 | |
7c50328b | 33 | #define SPLAT_KMEM_TEST1_ID 0x0101 |
34 | #define SPLAT_KMEM_TEST1_NAME "kmem_alloc" | |
35 | #define SPLAT_KMEM_TEST1_DESC "Memory allocation test (kmem_alloc)" | |
f1ca4da6 | 36 | |
7c50328b | 37 | #define SPLAT_KMEM_TEST2_ID 0x0102 |
38 | #define SPLAT_KMEM_TEST2_NAME "kmem_zalloc" | |
39 | #define SPLAT_KMEM_TEST2_DESC "Memory allocation test (kmem_zalloc)" | |
f1ca4da6 | 40 | |
7c50328b | 41 | #define SPLAT_KMEM_TEST3_ID 0x0103 |
2fb9b26a | 42 | #define SPLAT_KMEM_TEST3_NAME "vmem_alloc" |
43 | #define SPLAT_KMEM_TEST3_DESC "Memory allocation test (vmem_alloc)" | |
f1ca4da6 | 44 | |
7c50328b | 45 | #define SPLAT_KMEM_TEST4_ID 0x0104 |
2fb9b26a | 46 | #define SPLAT_KMEM_TEST4_NAME "vmem_zalloc" |
47 | #define SPLAT_KMEM_TEST4_DESC "Memory allocation test (vmem_zalloc)" | |
f1ca4da6 | 48 | |
79b31f36 | 49 | #define SPLAT_KMEM_TEST5_ID 0x0105 |
2fb9b26a | 50 | #define SPLAT_KMEM_TEST5_NAME "kmem_cache1" |
51 | #define SPLAT_KMEM_TEST5_DESC "Slab ctor/dtor test (small)" | |
52 | ||
53 | #define SPLAT_KMEM_TEST6_ID 0x0106 | |
54 | #define SPLAT_KMEM_TEST6_NAME "kmem_cache2" | |
55 | #define SPLAT_KMEM_TEST6_DESC "Slab ctor/dtor test (large)" | |
56 | ||
57 | #define SPLAT_KMEM_TEST7_ID 0x0107 | |
58 | #define SPLAT_KMEM_TEST7_NAME "kmem_reap" | |
59 | #define SPLAT_KMEM_TEST7_DESC "Slab reaping test" | |
79b31f36 | 60 | |
7c50328b | 61 | #define SPLAT_KMEM_ALLOC_COUNT 10 |
79b31f36 | 62 | #define SPLAT_VMEM_ALLOC_COUNT 10 |
63 | ||
f1ca4da6 | 64 | /* XXX - This test may fail under tight memory conditions */ |
65 | static int | |
7c50328b | 66 | splat_kmem_test1(struct file *file, void *arg) |
f1ca4da6 | 67 | { |
7c50328b | 68 | void *ptr[SPLAT_KMEM_ALLOC_COUNT]; |
f1ca4da6 | 69 | int size = PAGE_SIZE; |
70 | int i, count, rc = 0; | |
71 | ||
c19c06f3 | 72 | /* We are intentionally going to push kmem_alloc to its max |
73 | * allocation size, so suppress the console warnings for now */ | |
74 | kmem_set_warning(0); | |
75 | ||
79b31f36 | 76 | while ((!rc) && (size <= (PAGE_SIZE * 32))) { |
f1ca4da6 | 77 | count = 0; |
78 | ||
7c50328b | 79 | for (i = 0; i < SPLAT_KMEM_ALLOC_COUNT; i++) { |
f1ca4da6 | 80 | ptr[i] = kmem_alloc(size, KM_SLEEP); |
81 | if (ptr[i]) | |
82 | count++; | |
83 | } | |
84 | ||
7c50328b | 85 | for (i = 0; i < SPLAT_KMEM_ALLOC_COUNT; i++) |
f1ca4da6 | 86 | if (ptr[i]) |
87 | kmem_free(ptr[i], size); | |
88 | ||
7c50328b | 89 | splat_vprint(file, SPLAT_KMEM_TEST1_NAME, |
f1ca4da6 | 90 | "%d byte allocations, %d/%d successful\n", |
7c50328b | 91 | size, count, SPLAT_KMEM_ALLOC_COUNT); |
92 | if (count != SPLAT_KMEM_ALLOC_COUNT) | |
f1ca4da6 | 93 | rc = -ENOMEM; |
94 | ||
95 | size *= 2; | |
96 | } | |
97 | ||
c19c06f3 | 98 | kmem_set_warning(1); |
99 | ||
f1ca4da6 | 100 | return rc; |
101 | } | |
102 | ||
103 | static int | |
7c50328b | 104 | splat_kmem_test2(struct file *file, void *arg) |
f1ca4da6 | 105 | { |
7c50328b | 106 | void *ptr[SPLAT_KMEM_ALLOC_COUNT]; |
f1ca4da6 | 107 | int size = PAGE_SIZE; |
108 | int i, j, count, rc = 0; | |
109 | ||
c19c06f3 | 110 | /* We are intentionally going to push kmem_alloc to its max |
111 | * allocation size, so suppress the console warnings for now */ | |
112 | kmem_set_warning(0); | |
113 | ||
79b31f36 | 114 | while ((!rc) && (size <= (PAGE_SIZE * 32))) { |
f1ca4da6 | 115 | count = 0; |
116 | ||
7c50328b | 117 | for (i = 0; i < SPLAT_KMEM_ALLOC_COUNT; i++) { |
f1ca4da6 | 118 | ptr[i] = kmem_zalloc(size, KM_SLEEP); |
119 | if (ptr[i]) | |
120 | count++; | |
121 | } | |
122 | ||
123 | /* Ensure buffer has been zero filled */ | |
7c50328b | 124 | for (i = 0; i < SPLAT_KMEM_ALLOC_COUNT; i++) { |
f1ca4da6 | 125 | for (j = 0; j < size; j++) { |
126 | if (((char *)ptr[i])[j] != '\0') { | |
7c50328b | 127 | splat_vprint(file, SPLAT_KMEM_TEST2_NAME, |
f1ca4da6 | 128 | "%d-byte allocation was " |
129 | "not zeroed\n", size); | |
130 | rc = -EFAULT; | |
131 | } | |
132 | } | |
133 | } | |
134 | ||
7c50328b | 135 | for (i = 0; i < SPLAT_KMEM_ALLOC_COUNT; i++) |
f1ca4da6 | 136 | if (ptr[i]) |
137 | kmem_free(ptr[i], size); | |
138 | ||
7c50328b | 139 | splat_vprint(file, SPLAT_KMEM_TEST2_NAME, |
f1ca4da6 | 140 | "%d byte allocations, %d/%d successful\n", |
7c50328b | 141 | size, count, SPLAT_KMEM_ALLOC_COUNT); |
142 | if (count != SPLAT_KMEM_ALLOC_COUNT) | |
f1ca4da6 | 143 | rc = -ENOMEM; |
144 | ||
145 | size *= 2; | |
146 | } | |
147 | ||
c19c06f3 | 148 | kmem_set_warning(1); |
149 | ||
f1ca4da6 | 150 | return rc; |
151 | } | |
152 | ||
2fb9b26a | 153 | static int |
154 | splat_kmem_test3(struct file *file, void *arg) | |
155 | { | |
156 | void *ptr[SPLAT_VMEM_ALLOC_COUNT]; | |
157 | int size = PAGE_SIZE; | |
158 | int i, count, rc = 0; | |
159 | ||
160 | while ((!rc) && (size <= (PAGE_SIZE * 1024))) { | |
161 | count = 0; | |
162 | ||
163 | for (i = 0; i < SPLAT_VMEM_ALLOC_COUNT; i++) { | |
164 | ptr[i] = vmem_alloc(size, KM_SLEEP); | |
165 | if (ptr[i]) | |
166 | count++; | |
167 | } | |
168 | ||
169 | for (i = 0; i < SPLAT_VMEM_ALLOC_COUNT; i++) | |
170 | if (ptr[i]) | |
171 | vmem_free(ptr[i], size); | |
172 | ||
173 | splat_vprint(file, SPLAT_KMEM_TEST3_NAME, | |
174 | "%d byte allocations, %d/%d successful\n", | |
175 | size, count, SPLAT_VMEM_ALLOC_COUNT); | |
176 | if (count != SPLAT_VMEM_ALLOC_COUNT) | |
177 | rc = -ENOMEM; | |
178 | ||
179 | size *= 2; | |
180 | } | |
181 | ||
182 | return rc; | |
183 | } | |
184 | ||
185 | static int | |
186 | splat_kmem_test4(struct file *file, void *arg) | |
187 | { | |
188 | void *ptr[SPLAT_VMEM_ALLOC_COUNT]; | |
189 | int size = PAGE_SIZE; | |
190 | int i, j, count, rc = 0; | |
191 | ||
192 | while ((!rc) && (size <= (PAGE_SIZE * 1024))) { | |
193 | count = 0; | |
194 | ||
195 | for (i = 0; i < SPLAT_VMEM_ALLOC_COUNT; i++) { | |
196 | ptr[i] = vmem_zalloc(size, KM_SLEEP); | |
197 | if (ptr[i]) | |
198 | count++; | |
199 | } | |
200 | ||
201 | /* Ensure buffer has been zero filled */ | |
202 | for (i = 0; i < SPLAT_VMEM_ALLOC_COUNT; i++) { | |
203 | for (j = 0; j < size; j++) { | |
204 | if (((char *)ptr[i])[j] != '\0') { | |
205 | splat_vprint(file, SPLAT_KMEM_TEST4_NAME, | |
206 | "%d-byte allocation was " | |
207 | "not zeroed\n", size); | |
208 | rc = -EFAULT; | |
209 | } | |
210 | } | |
211 | } | |
212 | ||
213 | for (i = 0; i < SPLAT_VMEM_ALLOC_COUNT; i++) | |
214 | if (ptr[i]) | |
215 | vmem_free(ptr[i], size); | |
216 | ||
217 | splat_vprint(file, SPLAT_KMEM_TEST4_NAME, | |
218 | "%d byte allocations, %d/%d successful\n", | |
219 | size, count, SPLAT_VMEM_ALLOC_COUNT); | |
220 | if (count != SPLAT_VMEM_ALLOC_COUNT) | |
221 | rc = -ENOMEM; | |
222 | ||
223 | size *= 2; | |
224 | } | |
225 | ||
226 | return rc; | |
227 | } | |
228 | ||
7c50328b | 229 | #define SPLAT_KMEM_TEST_MAGIC 0x004488CCUL |
230 | #define SPLAT_KMEM_CACHE_NAME "kmem_test" | |
7c50328b | 231 | #define SPLAT_KMEM_OBJ_COUNT 128 |
2fb9b26a | 232 | #define SPLAT_KMEM_OBJ_RECLAIM 16 |
f1ca4da6 | 233 | |
234 | typedef struct kmem_cache_data { | |
f1ca4da6 | 235 | unsigned long kcd_magic; |
236 | int kcd_flag; | |
2fb9b26a | 237 | char kcd_buf[0]; |
f1ca4da6 | 238 | } kmem_cache_data_t; |
239 | ||
240 | typedef struct kmem_cache_priv { | |
241 | unsigned long kcp_magic; | |
242 | struct file *kcp_file; | |
243 | kmem_cache_t *kcp_cache; | |
7c50328b | 244 | kmem_cache_data_t *kcp_kcd[SPLAT_KMEM_OBJ_COUNT]; |
2fb9b26a | 245 | int kcp_size; |
f1ca4da6 | 246 | int kcp_count; |
247 | int kcp_rc; | |
248 | } kmem_cache_priv_t; | |
249 | ||
250 | static int | |
2fb9b26a | 251 | splat_kmem_cache_test_constructor(void *ptr, void *priv, int flags) |
f1ca4da6 | 252 | { |
f1ca4da6 | 253 | kmem_cache_priv_t *kcp = (kmem_cache_priv_t *)priv; |
2fb9b26a | 254 | kmem_cache_data_t *kcd = (kmem_cache_data_t *)ptr; |
f1ca4da6 | 255 | |
256 | if (kcd) { | |
f1ca4da6 | 257 | if (kcp) { |
d6a26c6a | 258 | kcd->kcd_magic = kcp->kcp_magic; |
f1ca4da6 | 259 | kcp->kcp_count++; |
260 | } | |
2fb9b26a | 261 | |
262 | memset(kcd->kcd_buf, 0xaa, kcp->kcp_size - (sizeof *kcd)); | |
263 | kcd->kcd_flag = 1; | |
f1ca4da6 | 264 | } |
265 | ||
266 | return 0; | |
267 | } | |
268 | ||
269 | static void | |
2fb9b26a | 270 | splat_kmem_cache_test_destructor(void *ptr, void *priv) |
f1ca4da6 | 271 | { |
f1ca4da6 | 272 | kmem_cache_priv_t *kcp = (kmem_cache_priv_t *)priv; |
2fb9b26a | 273 | kmem_cache_data_t *kcd = (kmem_cache_data_t *)ptr; |
f1ca4da6 | 274 | |
275 | if (kcd) { | |
2fb9b26a | 276 | if (kcp) { |
277 | kcd->kcd_magic = 0; | |
f1ca4da6 | 278 | kcp->kcp_count--; |
2fb9b26a | 279 | } |
280 | ||
281 | memset(kcd->kcd_buf, 0xbb, kcp->kcp_size - (sizeof *kcd)); | |
282 | kcd->kcd_flag = 0; | |
f1ca4da6 | 283 | } |
284 | ||
285 | return; | |
286 | } | |
287 | ||
288 | static int | |
2fb9b26a | 289 | splat_kmem_cache_size_test(struct file *file, void *arg, |
290 | char *name, int size, int flags) | |
f1ca4da6 | 291 | { |
292 | kmem_cache_t *cache = NULL; | |
293 | kmem_cache_data_t *kcd = NULL; | |
294 | kmem_cache_priv_t kcp; | |
295 | int rc = 0, max; | |
296 | ||
7c50328b | 297 | kcp.kcp_magic = SPLAT_KMEM_TEST_MAGIC; |
f1ca4da6 | 298 | kcp.kcp_file = file; |
2fb9b26a | 299 | kcp.kcp_size = size; |
f1ca4da6 | 300 | kcp.kcp_count = 0; |
301 | kcp.kcp_rc = 0; | |
302 | ||
2fb9b26a | 303 | cache = kmem_cache_create(SPLAT_KMEM_CACHE_NAME, kcp.kcp_size, 0, |
304 | splat_kmem_cache_test_constructor, | |
305 | splat_kmem_cache_test_destructor, | |
306 | NULL, &kcp, NULL, flags); | |
f1ca4da6 | 307 | if (!cache) { |
2fb9b26a | 308 | splat_vprint(file, name, |
7c50328b | 309 | "Unable to create '%s'\n", SPLAT_KMEM_CACHE_NAME); |
f1ca4da6 | 310 | return -ENOMEM; |
311 | } | |
312 | ||
2fb9b26a | 313 | kcd = kmem_cache_alloc(cache, KM_SLEEP); |
f1ca4da6 | 314 | if (!kcd) { |
2fb9b26a | 315 | splat_vprint(file, name, |
f1ca4da6 | 316 | "Unable to allocate from '%s'\n", |
7c50328b | 317 | SPLAT_KMEM_CACHE_NAME); |
f1ca4da6 | 318 | rc = -EINVAL; |
319 | goto out_free; | |
320 | } | |
321 | ||
322 | if (!kcd->kcd_flag) { | |
2fb9b26a | 323 | splat_vprint(file, name, |
f1ca4da6 | 324 | "Failed to run contructor for '%s'\n", |
7c50328b | 325 | SPLAT_KMEM_CACHE_NAME); |
f1ca4da6 | 326 | rc = -EINVAL; |
327 | goto out_free; | |
328 | } | |
329 | ||
330 | if (kcd->kcd_magic != kcp.kcp_magic) { | |
2fb9b26a | 331 | splat_vprint(file, name, |
f1ca4da6 | 332 | "Failed to pass private data to constructor " |
7c50328b | 333 | "for '%s'\n", SPLAT_KMEM_CACHE_NAME); |
f1ca4da6 | 334 | rc = -EINVAL; |
335 | goto out_free; | |
336 | } | |
337 | ||
338 | max = kcp.kcp_count; | |
f1ca4da6 | 339 | kmem_cache_free(cache, kcd); |
340 | ||
341 | /* Destroy the entire cache which will force destructors to | |
342 | * run and we can verify one was called for every object */ | |
343 | kmem_cache_destroy(cache); | |
344 | if (kcp.kcp_count) { | |
2fb9b26a | 345 | splat_vprint(file, name, |
f1ca4da6 | 346 | "Failed to run destructor on all slab objects " |
7c50328b | 347 | "for '%s'\n", SPLAT_KMEM_CACHE_NAME); |
f1ca4da6 | 348 | rc = -EINVAL; |
349 | } | |
350 | ||
2fb9b26a | 351 | splat_vprint(file, name, |
352 | "Successfully ran ctors/dtors for %d elements in '%s'\n", | |
7c50328b | 353 | max, SPLAT_KMEM_CACHE_NAME); |
f1ca4da6 | 354 | |
355 | return rc; | |
356 | ||
357 | out_free: | |
358 | if (kcd) | |
359 | kmem_cache_free(cache, kcd); | |
f1b59d26 | 360 | |
f1ca4da6 | 361 | kmem_cache_destroy(cache); |
362 | return rc; | |
363 | } | |
364 | ||
2fb9b26a | 365 | static int |
366 | splat_kmem_test5(struct file *file, void *arg) | |
367 | { | |
368 | return splat_kmem_cache_size_test(file, arg, SPLAT_KMEM_TEST5_NAME, | |
369 | sizeof(kmem_cache_data_t) * 1, 0); | |
370 | } | |
371 | ||
372 | static int | |
373 | splat_kmem_test6(struct file *file, void *arg) | |
374 | { | |
375 | return splat_kmem_cache_size_test(file, arg, SPLAT_KMEM_TEST6_NAME, | |
376 | sizeof(kmem_cache_data_t) * 1024, 0); | |
377 | } | |
378 | ||
f1ca4da6 | 379 | static void |
2fb9b26a | 380 | splat_kmem_cache_test_reclaim(void *priv) |
f1ca4da6 | 381 | { |
382 | kmem_cache_priv_t *kcp = (kmem_cache_priv_t *)priv; | |
2fb9b26a | 383 | int i, count; |
384 | ||
385 | count = min(SPLAT_KMEM_OBJ_RECLAIM, kcp->kcp_count); | |
386 | splat_vprint(kcp->kcp_file, SPLAT_KMEM_TEST7_NAME, | |
387 | "Reaping %d objects from '%s'\n", count, | |
388 | SPLAT_KMEM_CACHE_NAME); | |
f1ca4da6 | 389 | |
2fb9b26a | 390 | for (i = 0; i < SPLAT_KMEM_OBJ_COUNT; i++) { |
f1ca4da6 | 391 | if (kcp->kcp_kcd[i]) { |
392 | kmem_cache_free(kcp->kcp_cache, kcp->kcp_kcd[i]); | |
393 | kcp->kcp_kcd[i] = NULL; | |
2fb9b26a | 394 | |
395 | if (--count == 0) | |
396 | break; | |
f1ca4da6 | 397 | } |
398 | } | |
399 | ||
400 | return; | |
401 | } | |
402 | ||
403 | static int | |
2fb9b26a | 404 | splat_kmem_test7(struct file *file, void *arg) |
f1ca4da6 | 405 | { |
406 | kmem_cache_t *cache; | |
407 | kmem_cache_priv_t kcp; | |
2fb9b26a | 408 | int i, rc = 0; |
f1ca4da6 | 409 | |
7c50328b | 410 | kcp.kcp_magic = SPLAT_KMEM_TEST_MAGIC; |
f1ca4da6 | 411 | kcp.kcp_file = file; |
2fb9b26a | 412 | kcp.kcp_size = 256; |
f1ca4da6 | 413 | kcp.kcp_count = 0; |
414 | kcp.kcp_rc = 0; | |
415 | ||
2fb9b26a | 416 | cache = kmem_cache_create(SPLAT_KMEM_CACHE_NAME, kcp.kcp_size, 0, |
417 | splat_kmem_cache_test_constructor, | |
418 | splat_kmem_cache_test_destructor, | |
419 | splat_kmem_cache_test_reclaim, | |
420 | &kcp, NULL, 0); | |
f1ca4da6 | 421 | if (!cache) { |
2fb9b26a | 422 | splat_vprint(file, SPLAT_KMEM_TEST7_NAME, |
7c50328b | 423 | "Unable to create '%s'\n", SPLAT_KMEM_CACHE_NAME); |
f1ca4da6 | 424 | return -ENOMEM; |
425 | } | |
426 | ||
427 | kcp.kcp_cache = cache; | |
428 | ||
7c50328b | 429 | for (i = 0; i < SPLAT_KMEM_OBJ_COUNT; i++) { |
f1b59d26 | 430 | /* All allocations need not succeed */ |
2fb9b26a | 431 | kcp.kcp_kcd[i] = kmem_cache_alloc(cache, KM_SLEEP); |
f1ca4da6 | 432 | if (!kcp.kcp_kcd[i]) { |
2fb9b26a | 433 | splat_vprint(file, SPLAT_KMEM_TEST7_NAME, |
f1ca4da6 | 434 | "Unable to allocate from '%s'\n", |
7c50328b | 435 | SPLAT_KMEM_CACHE_NAME); |
f1ca4da6 | 436 | } |
437 | } | |
438 | ||
2fb9b26a | 439 | ASSERT(kcp.kcp_count > 0); |
440 | ||
441 | /* Request the slab cache free any objects it can. For a few reasons | |
442 | * this may not immediately result in more free memory even if objects | |
443 | * are freed. First off, due to fragmentation we may not be able to | |
444 | * reclaim any slabs. Secondly, even if we do we fully clear some | |
445 | * slabs we will not want to immedately reclaim all of them because | |
446 | * we may contend with cache allocs and thrash. What we want to see | |
447 | * is slab size decrease more gradually as it becomes clear they | |
448 | * will not be needed. This should be acheivable in less than minute | |
449 | * if it takes longer than this something has gone wrong. | |
450 | */ | |
451 | for (i = 0; i < 60; i++) { | |
452 | kmem_cache_reap_now(cache); | |
453 | splat_vprint(file, SPLAT_KMEM_TEST7_NAME, | |
454 | "%s cache objects %d, slabs %u/%u objs %u/%u\n", | |
455 | SPLAT_KMEM_CACHE_NAME, kcp.kcp_count, | |
456 | (unsigned)cache->skc_slab_alloc, | |
457 | (unsigned)cache->skc_slab_total, | |
458 | (unsigned)cache->skc_obj_alloc, | |
459 | (unsigned)cache->skc_obj_total); | |
460 | ||
461 | if (cache->skc_obj_total == 0) | |
462 | break; | |
463 | ||
464 | set_current_state(TASK_INTERRUPTIBLE); | |
465 | schedule_timeout(HZ); | |
466 | } | |
467 | ||
468 | if (cache->skc_obj_total == 0) { | |
469 | splat_vprint(file, SPLAT_KMEM_TEST7_NAME, | |
470 | "Successfully created %d objects " | |
471 | "in cache %s and reclaimed them\n", | |
472 | SPLAT_KMEM_OBJ_COUNT, SPLAT_KMEM_CACHE_NAME); | |
473 | } else { | |
474 | splat_vprint(file, SPLAT_KMEM_TEST7_NAME, | |
475 | "Failed to reclaim %u/%d objects from cache %s\n", | |
476 | (unsigned)cache->skc_obj_total, SPLAT_KMEM_OBJ_COUNT, | |
477 | SPLAT_KMEM_CACHE_NAME); | |
478 | rc = -ENOMEM; | |
479 | } | |
f1ca4da6 | 480 | |
2fb9b26a | 481 | /* Cleanup our mess (for failure case of time expiring) */ |
7c50328b | 482 | for (i = 0; i < SPLAT_KMEM_OBJ_COUNT; i++) |
f1ca4da6 | 483 | if (kcp.kcp_kcd[i]) |
484 | kmem_cache_free(cache, kcp.kcp_kcd[i]); | |
485 | ||
486 | kmem_cache_destroy(cache); | |
487 | ||
488 | return rc; | |
489 | } | |
490 | ||
7c50328b | 491 | splat_subsystem_t * |
492 | splat_kmem_init(void) | |
f1ca4da6 | 493 | { |
7c50328b | 494 | splat_subsystem_t *sub; |
f1ca4da6 | 495 | |
496 | sub = kmalloc(sizeof(*sub), GFP_KERNEL); | |
497 | if (sub == NULL) | |
498 | return NULL; | |
499 | ||
500 | memset(sub, 0, sizeof(*sub)); | |
7c50328b | 501 | strncpy(sub->desc.name, SPLAT_KMEM_NAME, SPLAT_NAME_SIZE); |
502 | strncpy(sub->desc.desc, SPLAT_KMEM_DESC, SPLAT_DESC_SIZE); | |
f1ca4da6 | 503 | INIT_LIST_HEAD(&sub->subsystem_list); |
504 | INIT_LIST_HEAD(&sub->test_list); | |
505 | spin_lock_init(&sub->test_lock); | |
7c50328b | 506 | sub->desc.id = SPLAT_SUBSYSTEM_KMEM; |
f1ca4da6 | 507 | |
7c50328b | 508 | SPLAT_TEST_INIT(sub, SPLAT_KMEM_TEST1_NAME, SPLAT_KMEM_TEST1_DESC, |
509 | SPLAT_KMEM_TEST1_ID, splat_kmem_test1); | |
510 | SPLAT_TEST_INIT(sub, SPLAT_KMEM_TEST2_NAME, SPLAT_KMEM_TEST2_DESC, | |
511 | SPLAT_KMEM_TEST2_ID, splat_kmem_test2); | |
512 | SPLAT_TEST_INIT(sub, SPLAT_KMEM_TEST3_NAME, SPLAT_KMEM_TEST3_DESC, | |
513 | SPLAT_KMEM_TEST3_ID, splat_kmem_test3); | |
514 | SPLAT_TEST_INIT(sub, SPLAT_KMEM_TEST4_NAME, SPLAT_KMEM_TEST4_DESC, | |
515 | SPLAT_KMEM_TEST4_ID, splat_kmem_test4); | |
79b31f36 | 516 | SPLAT_TEST_INIT(sub, SPLAT_KMEM_TEST5_NAME, SPLAT_KMEM_TEST5_DESC, |
517 | SPLAT_KMEM_TEST5_ID, splat_kmem_test5); | |
2fb9b26a | 518 | SPLAT_TEST_INIT(sub, SPLAT_KMEM_TEST6_NAME, SPLAT_KMEM_TEST6_DESC, |
519 | SPLAT_KMEM_TEST6_ID, splat_kmem_test6); | |
520 | SPLAT_TEST_INIT(sub, SPLAT_KMEM_TEST7_NAME, SPLAT_KMEM_TEST7_DESC, | |
521 | SPLAT_KMEM_TEST7_ID, splat_kmem_test7); | |
f1ca4da6 | 522 | |
523 | return sub; | |
524 | } | |
525 | ||
526 | void | |
7c50328b | 527 | splat_kmem_fini(splat_subsystem_t *sub) |
f1ca4da6 | 528 | { |
529 | ASSERT(sub); | |
2fb9b26a | 530 | SPLAT_TEST_FINI(sub, SPLAT_KMEM_TEST7_ID); |
531 | SPLAT_TEST_FINI(sub, SPLAT_KMEM_TEST6_ID); | |
79b31f36 | 532 | SPLAT_TEST_FINI(sub, SPLAT_KMEM_TEST5_ID); |
7c50328b | 533 | SPLAT_TEST_FINI(sub, SPLAT_KMEM_TEST4_ID); |
534 | SPLAT_TEST_FINI(sub, SPLAT_KMEM_TEST3_ID); | |
535 | SPLAT_TEST_FINI(sub, SPLAT_KMEM_TEST2_ID); | |
536 | SPLAT_TEST_FINI(sub, SPLAT_KMEM_TEST1_ID); | |
f1ca4da6 | 537 | |
538 | kfree(sub); | |
539 | } | |
540 | ||
541 | int | |
7c50328b | 542 | splat_kmem_id(void) { |
543 | return SPLAT_SUBSYSTEM_KMEM; | |
f1ca4da6 | 544 | } |