1 #include <sys/zfs_context.h>
2 #include <sys/splat-ctl.h>
4 #define KZT_SUBSYSTEM_KMEM 0x0100
5 #define KZT_KMEM_NAME "kmem"
6 #define KZT_KMEM_DESC "Kernel Malloc/Slab Tests"
8 #define KZT_KMEM_TEST1_ID 0x0101
9 #define KZT_KMEM_TEST1_NAME "kmem_alloc"
10 #define KZT_KMEM_TEST1_DESC "Memory allocation test (kmem_alloc)"
12 #define KZT_KMEM_TEST2_ID 0x0102
13 #define KZT_KMEM_TEST2_NAME "kmem_zalloc"
14 #define KZT_KMEM_TEST2_DESC "Memory allocation test (kmem_zalloc)"
16 #define KZT_KMEM_TEST3_ID 0x0103
17 #define KZT_KMEM_TEST3_NAME "slab_alloc"
18 #define KZT_KMEM_TEST3_DESC "Slab constructor/destructor test"
20 #define KZT_KMEM_TEST4_ID 0x0104
21 #define KZT_KMEM_TEST4_NAME "slab_reap"
22 #define KZT_KMEM_TEST4_DESC "Slab reaping test"
24 #define KZT_KMEM_ALLOC_COUNT 10
25 /* XXX - This test may fail under tight memory conditions */
27 kzt_kmem_test1(struct file
*file
, void *arg
)
29 void *ptr
[KZT_KMEM_ALLOC_COUNT
];
33 while ((!rc
) && (size
< (PAGE_SIZE
* 16))) {
36 for (i
= 0; i
< KZT_KMEM_ALLOC_COUNT
; i
++) {
37 ptr
[i
] = kmem_alloc(size
, KM_SLEEP
);
42 for (i
= 0; i
< KZT_KMEM_ALLOC_COUNT
; i
++)
44 kmem_free(ptr
[i
], size
);
46 kzt_vprint(file
, KZT_KMEM_TEST1_NAME
,
47 "%d byte allocations, %d/%d successful\n",
48 size
, count
, KZT_KMEM_ALLOC_COUNT
);
49 if (count
!= KZT_KMEM_ALLOC_COUNT
)
59 kzt_kmem_test2(struct file
*file
, void *arg
)
61 void *ptr
[KZT_KMEM_ALLOC_COUNT
];
63 int i
, j
, count
, rc
= 0;
65 while ((!rc
) && (size
< (PAGE_SIZE
* 16))) {
68 for (i
= 0; i
< KZT_KMEM_ALLOC_COUNT
; i
++) {
69 ptr
[i
] = kmem_zalloc(size
, KM_SLEEP
);
74 /* Ensure buffer has been zero filled */
75 for (i
= 0; i
< KZT_KMEM_ALLOC_COUNT
; i
++) {
76 for (j
= 0; j
< size
; j
++) {
77 if (((char *)ptr
[i
])[j
] != '\0') {
78 kzt_vprint(file
, KZT_KMEM_TEST2_NAME
,
79 "%d-byte allocation was "
80 "not zeroed\n", size
);
86 for (i
= 0; i
< KZT_KMEM_ALLOC_COUNT
; i
++)
88 kmem_free(ptr
[i
], size
);
90 kzt_vprint(file
, KZT_KMEM_TEST2_NAME
,
91 "%d byte allocations, %d/%d successful\n",
92 size
, count
, KZT_KMEM_ALLOC_COUNT
);
93 if (count
!= KZT_KMEM_ALLOC_COUNT
)
102 #define KZT_KMEM_TEST_MAGIC 0x004488CCUL
103 #define KZT_KMEM_CACHE_NAME "kmem_test"
104 #define KZT_KMEM_CACHE_SIZE 256
105 #define KZT_KMEM_OBJ_COUNT 128
106 #define KZT_KMEM_OBJ_RECLAIM 64
108 typedef struct kmem_cache_data
{
109 char kcd_buf
[KZT_KMEM_CACHE_SIZE
];
110 unsigned long kcd_magic
;
114 typedef struct kmem_cache_priv
{
115 unsigned long kcp_magic
;
116 struct file
*kcp_file
;
117 kmem_cache_t
*kcp_cache
;
118 kmem_cache_data_t
*kcp_kcd
[KZT_KMEM_OBJ_COUNT
];
124 kzt_kmem_test34_constructor(void *ptr
, void *priv
, int flags
)
126 kmem_cache_data_t
*kcd
= (kmem_cache_data_t
*)ptr
;
127 kmem_cache_priv_t
*kcp
= (kmem_cache_priv_t
*)priv
;
130 memset(kcd
->kcd_buf
, 0xaa, KZT_KMEM_CACHE_SIZE
);
134 kcd
->kcd_magic
= kcp
->kcp_magic
;
143 kzt_kmem_test34_destructor(void *ptr
, void *priv
)
145 kmem_cache_data_t
*kcd
= (kmem_cache_data_t
*)ptr
;
146 kmem_cache_priv_t
*kcp
= (kmem_cache_priv_t
*)priv
;
149 memset(kcd
->kcd_buf
, 0xbb, KZT_KMEM_CACHE_SIZE
);
160 kzt_kmem_test3(struct file
*file
, void *arg
)
162 kmem_cache_t
*cache
= NULL
;
163 kmem_cache_data_t
*kcd
= NULL
;
164 kmem_cache_priv_t kcp
;
167 kcp
.kcp_magic
= KZT_KMEM_TEST_MAGIC
;
172 cache
= kmem_cache_create(KZT_KMEM_CACHE_NAME
, sizeof(*kcd
), 0,
173 kzt_kmem_test34_constructor
,
174 kzt_kmem_test34_destructor
,
175 NULL
, &kcp
, NULL
, 0);
177 kzt_vprint(file
, KZT_KMEM_TEST3_NAME
,
178 "Unable to create '%s'\n", KZT_KMEM_CACHE_NAME
);
182 kcd
= kmem_cache_alloc(cache
, 0);
184 kzt_vprint(file
, KZT_KMEM_TEST3_NAME
,
185 "Unable to allocate from '%s'\n",
186 KZT_KMEM_CACHE_NAME
);
191 if (!kcd
->kcd_flag
) {
192 kzt_vprint(file
, KZT_KMEM_TEST3_NAME
,
193 "Failed to run contructor for '%s'\n",
194 KZT_KMEM_CACHE_NAME
);
199 if (kcd
->kcd_magic
!= kcp
.kcp_magic
) {
200 kzt_vprint(file
, KZT_KMEM_TEST3_NAME
,
201 "Failed to pass private data to constructor "
202 "for '%s'\n", KZT_KMEM_CACHE_NAME
);
209 /* Destructor's run lazily so it hard to check correctness here.
210 * We assume if it doesn't crash the free worked properly */
211 kmem_cache_free(cache
, kcd
);
213 /* Destroy the entire cache which will force destructors to
214 * run and we can verify one was called for every object */
215 kmem_cache_destroy(cache
);
217 kzt_vprint(file
, KZT_KMEM_TEST3_NAME
,
218 "Failed to run destructor on all slab objects "
219 "for '%s'\n", KZT_KMEM_CACHE_NAME
);
223 kzt_vprint(file
, KZT_KMEM_TEST3_NAME
,
224 "%d allocated/destroyed objects for '%s'\n",
225 max
, KZT_KMEM_CACHE_NAME
);
231 kmem_cache_free(cache
, kcd
);
233 kmem_cache_destroy(cache
);
238 kzt_kmem_test4_reclaim(void *priv
)
240 kmem_cache_priv_t
*kcp
= (kmem_cache_priv_t
*)priv
;
243 kzt_vprint(kcp
->kcp_file
, KZT_KMEM_TEST4_NAME
,
244 "Reaping %d objects from '%s'\n",
245 KZT_KMEM_OBJ_RECLAIM
, KZT_KMEM_CACHE_NAME
);
246 for (i
= 0; i
< KZT_KMEM_OBJ_RECLAIM
; i
++) {
247 if (kcp
->kcp_kcd
[i
]) {
248 kmem_cache_free(kcp
->kcp_cache
, kcp
->kcp_kcd
[i
]);
249 kcp
->kcp_kcd
[i
] = NULL
;
257 kzt_kmem_test4(struct file
*file
, void *arg
)
260 kmem_cache_priv_t kcp
;
261 int i
, rc
= 0, max
, reclaim_percent
, target_percent
;
263 kcp
.kcp_magic
= KZT_KMEM_TEST_MAGIC
;
268 cache
= kmem_cache_create(KZT_KMEM_CACHE_NAME
,
269 sizeof(kmem_cache_data_t
), 0,
270 kzt_kmem_test34_constructor
,
271 kzt_kmem_test34_destructor
,
272 kzt_kmem_test4_reclaim
, &kcp
, NULL
, 0);
274 kzt_vprint(file
, KZT_KMEM_TEST4_NAME
,
275 "Unable to create '%s'\n", KZT_KMEM_CACHE_NAME
);
279 kcp
.kcp_cache
= cache
;
281 for (i
= 0; i
< KZT_KMEM_OBJ_COUNT
; i
++) {
282 /* All allocations need not succeed */
283 kcp
.kcp_kcd
[i
] = kmem_cache_alloc(cache
, 0);
284 if (!kcp
.kcp_kcd
[i
]) {
285 kzt_vprint(file
, KZT_KMEM_TEST4_NAME
,
286 "Unable to allocate from '%s'\n",
287 KZT_KMEM_CACHE_NAME
);
293 /* Force shrinker to run */
296 /* Reclaim reclaimed objects, this ensure the destructors are run */
297 kmem_cache_reap_now(cache
);
299 reclaim_percent
= ((kcp
.kcp_count
* 100) / max
);
300 target_percent
= (((KZT_KMEM_OBJ_COUNT
- KZT_KMEM_OBJ_RECLAIM
) * 100) /
302 kzt_vprint(file
, KZT_KMEM_TEST4_NAME
,
303 "%d%% (%d/%d) of previous size, target of "
304 "%d%%-%d%% for '%s'\n", reclaim_percent
, kcp
.kcp_count
,
305 max
, target_percent
- 10, target_percent
+ 10,
306 KZT_KMEM_CACHE_NAME
);
307 if ((reclaim_percent
< target_percent
- 10) ||
308 (reclaim_percent
> target_percent
+ 10))
311 /* Cleanup our mess */
312 for (i
= 0; i
< KZT_KMEM_OBJ_COUNT
; i
++)
314 kmem_cache_free(cache
, kcp
.kcp_kcd
[i
]);
316 kmem_cache_destroy(cache
);
324 kzt_subsystem_t
*sub
;
326 sub
= kmalloc(sizeof(*sub
), GFP_KERNEL
);
330 memset(sub
, 0, sizeof(*sub
));
331 strncpy(sub
->desc
.name
, KZT_KMEM_NAME
, KZT_NAME_SIZE
);
332 strncpy(sub
->desc
.desc
, KZT_KMEM_DESC
, KZT_DESC_SIZE
);
333 INIT_LIST_HEAD(&sub
->subsystem_list
);
334 INIT_LIST_HEAD(&sub
->test_list
);
335 spin_lock_init(&sub
->test_lock
);
336 sub
->desc
.id
= KZT_SUBSYSTEM_KMEM
;
338 KZT_TEST_INIT(sub
, KZT_KMEM_TEST1_NAME
, KZT_KMEM_TEST1_DESC
,
339 KZT_KMEM_TEST1_ID
, kzt_kmem_test1
);
340 KZT_TEST_INIT(sub
, KZT_KMEM_TEST2_NAME
, KZT_KMEM_TEST2_DESC
,
341 KZT_KMEM_TEST2_ID
, kzt_kmem_test2
);
342 KZT_TEST_INIT(sub
, KZT_KMEM_TEST3_NAME
, KZT_KMEM_TEST3_DESC
,
343 KZT_KMEM_TEST3_ID
, kzt_kmem_test3
);
344 KZT_TEST_INIT(sub
, KZT_KMEM_TEST4_NAME
, KZT_KMEM_TEST4_DESC
,
345 KZT_KMEM_TEST4_ID
, kzt_kmem_test4
);
351 kzt_kmem_fini(kzt_subsystem_t
*sub
)
354 KZT_TEST_FINI(sub
, KZT_KMEM_TEST4_ID
);
355 KZT_TEST_FINI(sub
, KZT_KMEM_TEST3_ID
);
356 KZT_TEST_FINI(sub
, KZT_KMEM_TEST2_ID
);
357 KZT_TEST_FINI(sub
, KZT_KMEM_TEST1_ID
);
364 return KZT_SUBSYSTEM_KMEM
;