]> git.proxmox.com Git - mirror_spl-debian.git/blame - module/splat/splat-list.c
Add 3 missing typedefs.
[mirror_spl-debian.git] / module / splat / splat-list.c
CommitLineData
d702c04f
BB
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
27#include "splat-internal.h"
28
d702c04f
BB
29#define SPLAT_LIST_NAME "list"
30#define SPLAT_LIST_DESC "Kernel List Tests"
31
32#define SPLAT_LIST_TEST1_ID 0x0c01
33#define SPLAT_LIST_TEST1_NAME "create/destroy"
34#define SPLAT_LIST_TEST1_DESC "Create/destroy Test"
35
36#define SPLAT_LIST_TEST2_ID 0x0c02
434d1d0f 37#define SPLAT_LIST_TEST2_NAME "ins/rm head"
d702c04f
BB
38#define SPLAT_LIST_TEST2_DESC "Insert/remove head Test"
39
40#define SPLAT_LIST_TEST3_ID 0x0c03
434d1d0f 41#define SPLAT_LIST_TEST3_NAME "ins/rm tail"
d702c04f
BB
42#define SPLAT_LIST_TEST3_DESC "Insert/remove tail Test"
43
44#define SPLAT_LIST_TEST4_ID 0x0c04
45#define SPLAT_LIST_TEST4_NAME "insert_after"
46#define SPLAT_LIST_TEST4_DESC "Insert_after Test"
47
48#define SPLAT_LIST_TEST5_ID 0x0c05
49#define SPLAT_LIST_TEST5_NAME "insert_before"
50#define SPLAT_LIST_TEST5_DESC "Insert_before Test"
51
52#define SPLAT_LIST_TEST6_ID 0x0c06
53#define SPLAT_LIST_TEST6_NAME "remove"
54#define SPLAT_LIST_TEST6_DESC "Remove Test"
55
434d1d0f
BB
56#define SPLAT_LIST_TEST7_ID 0x0c7
57#define SPLAT_LIST_TEST7_NAME "active"
58#define SPLAT_LIST_TEST7_DESC "Active Test"
d702c04f
BB
59
60/* It is important that li_node is not the first element, this
61 * ensures the list_d2l/list_object macros are working correctly. */
62typedef struct list_item {
63 int li_data;
64 list_node_t li_node;
65} list_item_t;
66
67#define LIST_ORDER_STACK 0
68#define LIST_ORDER_QUEUE 1
69
70static int
71splat_list_test1(struct file *file, void *arg)
72{
73 list_t list;
74
75 splat_vprint(file, SPLAT_LIST_TEST1_NAME, "Creating list\n%s", "");
76 list_create(&list, sizeof(list_item_t), offsetof(list_item_t, li_node));
77
78 if (!list_is_empty(&list)) {
79 splat_vprint(file, SPLAT_LIST_TEST1_NAME,
80 "New list NOT empty%s\n", "");
81 /* list_destroy() intentionally skipped to avoid assert */
82 return -EEXIST;
83 }
84
85 splat_vprint(file, SPLAT_LIST_TEST1_NAME, "Destroying list\n%s", "");
86 list_destroy(&list);
87
88 /* Validate the list has been destroyed */
89 if (list_link_active(&list.list_head)) {
90 splat_vprint(file, SPLAT_LIST_TEST1_NAME,
91 "Destroyed list still active%s", "");
92 return -EIO;
93 }
94
95 return 0;
96}
97
98static int
99splat_list_validate(list_t *list, int size, int order, int mult)
100{
101 list_item_t *li;
102 int i;
103
104 /* Walk all items in list from head to verify stack or queue
105 * ordering. We bound the for loop by size+1 to ensure that
106 * we still terminate if there is list corruption. We also
107 * intentionally make things a little more complex than they
108 * need to be by using list_head/list_next for queues, and
109 * list_tail/list_prev for stacks. This is simply done for
110 * coverage and to ensure these function are working right.
111 */
112 for (i = 0, li = (order ? list_head(list) : list_tail(list));
113 i < size + 1 && li != NULL;
114 i++, li = (order ? list_next(list, li) : list_prev(list, li)))
115 if (li->li_data != i * mult)
116 return -EIDRM;
117
118 if (i != size)
119 return -E2BIG;
120
121 return 0;
122}
123
124static int
125splat_list_test2(struct file *file, void *arg)
126{
127 list_t list;
128 list_item_t *li;
129 int i, list_size = 8, rc = 0;
130
131 splat_vprint(file, SPLAT_LIST_TEST2_NAME, "Creating list\n%s", "");
132 list_create(&list, sizeof(list_item_t), offsetof(list_item_t, li_node));
133
134 /* Insert all items at the list head to form a stack */
135 splat_vprint(file, SPLAT_LIST_TEST2_NAME,
136 "Adding %d items to list head\n", list_size);
137 for (i = 0; i < list_size; i++) {
138 li = kmem_alloc(sizeof(list_item_t), KM_SLEEP);
139 if (li == NULL) {
140 rc = -ENOMEM;
141 goto out;
142 }
143
144 list_link_init(&li->li_node);
145 li->li_data = i;
146 list_insert_head(&list, li);
147 }
148
149 splat_vprint(file, SPLAT_LIST_TEST2_NAME,
150 "Validating %d item list is a stack\n", list_size);
151 rc = splat_list_validate(&list, list_size, LIST_ORDER_STACK, 1);
152 if (rc)
153 splat_vprint(file, SPLAT_LIST_TEST2_NAME,
154 "List validation failed, %d\n", rc);
155out:
156 /* Remove all items */
157 splat_vprint(file, SPLAT_LIST_TEST2_NAME,
158 "Removing %d items from list head\n", list_size);
159 while ((li = list_remove_head(&list)))
160 kmem_free(li, sizeof(list_item_t));
161
162 splat_vprint(file, SPLAT_LIST_TEST2_NAME, "Destroying list\n%s", "");
163 list_destroy(&list);
164
165 return rc;
166}
167
168static int
169splat_list_test3(struct file *file, void *arg)
170{
171 list_t list;
172 list_item_t *li;
173 int i, list_size = 8, rc = 0;
174
175 splat_vprint(file, SPLAT_LIST_TEST3_NAME, "Creating list\n%s", "");
176 list_create(&list, sizeof(list_item_t), offsetof(list_item_t, li_node));
177
178 /* Insert all items at the list tail to form a queue */
179 splat_vprint(file, SPLAT_LIST_TEST3_NAME,
180 "Adding %d items to list tail\n", list_size);
181 for (i = 0; i < list_size; i++) {
182 li = kmem_alloc(sizeof(list_item_t), KM_SLEEP);
183 if (li == NULL) {
184 rc = -ENOMEM;
185 goto out;
186 }
187
188 list_link_init(&li->li_node);
189 li->li_data = i;
190 list_insert_tail(&list, li);
191 }
192
193 splat_vprint(file, SPLAT_LIST_TEST3_NAME,
194 "Validating %d item list is a queue\n", list_size);
195 rc = splat_list_validate(&list, list_size, LIST_ORDER_QUEUE, 1);
196 if (rc)
197 splat_vprint(file, SPLAT_LIST_TEST3_NAME,
198 "List validation failed, %d\n", rc);
199out:
200 /* Remove all items */
201 splat_vprint(file, SPLAT_LIST_TEST3_NAME,
202 "Removing %d items from list tail\n", list_size);
203 while ((li = list_remove_tail(&list)))
204 kmem_free(li, sizeof(list_item_t));
205
206 splat_vprint(file, SPLAT_LIST_TEST3_NAME, "Destroying list\n%s", "");
207 list_destroy(&list);
208
209 return rc;
210}
211
212static int
213splat_list_test4(struct file *file, void *arg)
214{
215 list_t list;
216 list_item_t *li_new, *li_last = NULL;
217 int i, list_size = 8, rc = 0;
218
219 splat_vprint(file, SPLAT_LIST_TEST4_NAME, "Creating list\n%s", "");
220 list_create(&list, sizeof(list_item_t), offsetof(list_item_t, li_node));
221
222 /* Insert all items after the last item to form a queue */
223 splat_vprint(file, SPLAT_LIST_TEST4_NAME,
224 "Adding %d items each after the last item\n", list_size);
225 for (i = 0; i < list_size; i++) {
226 li_new = kmem_alloc(sizeof(list_item_t), KM_SLEEP);
227 if (li_new == NULL) {
228 rc = -ENOMEM;
229 goto out;
230 }
231
232 list_link_init(&li_new->li_node);
233 li_new->li_data = i;
234 list_insert_after(&list, li_last, li_new);
235 li_last = li_new;
236 }
237
238 splat_vprint(file, SPLAT_LIST_TEST4_NAME,
239 "Validating %d item list is a queue\n", list_size);
240 rc = splat_list_validate(&list, list_size, LIST_ORDER_QUEUE, 1);
241 if (rc)
242 splat_vprint(file, SPLAT_LIST_TEST4_NAME,
243 "List validation failed, %d\n", rc);
244out:
245 /* Remove all items */
246 splat_vprint(file, SPLAT_LIST_TEST4_NAME,
247 "Removing %d items from list tail\n", list_size);
248 while ((li_new = list_remove_head(&list)))
249 kmem_free(li_new, sizeof(list_item_t));
250
251 splat_vprint(file, SPLAT_LIST_TEST4_NAME, "Destroying list\n%s", "");
252 list_destroy(&list);
253
254 return rc;
255}
256
257static int
258splat_list_test5(struct file *file, void *arg)
259{
260 list_t list;
261 list_item_t *li_new, *li_last = NULL;
262 int i, list_size = 8, rc = 0;
263
264 splat_vprint(file, SPLAT_LIST_TEST5_NAME, "Creating list\n%s", "");
265 list_create(&list, sizeof(list_item_t), offsetof(list_item_t, li_node));
266
267 /* Insert all items before the last item to form a stack */
268 splat_vprint(file, SPLAT_LIST_TEST5_NAME,
269 "Adding %d items each before the last item\n", list_size);
270 for (i = 0; i < list_size; i++) {
271 li_new = kmem_alloc(sizeof(list_item_t), KM_SLEEP);
272 if (li_new == NULL) {
273 rc = -ENOMEM;
274 goto out;
275 }
276
277 list_link_init(&li_new->li_node);
278 li_new->li_data = i;
279 list_insert_before(&list, li_last, li_new);
280 li_last = li_new;
281 }
282
283 splat_vprint(file, SPLAT_LIST_TEST5_NAME,
284 "Validating %d item list is a queue\n", list_size);
285 rc = splat_list_validate(&list, list_size, LIST_ORDER_STACK, 1);
286 if (rc)
287 splat_vprint(file, SPLAT_LIST_TEST5_NAME,
288 "List validation failed, %d\n", rc);
289out:
290 /* Remove all items */
291 splat_vprint(file, SPLAT_LIST_TEST5_NAME,
292 "Removing %d items from list tail\n", list_size);
293 while ((li_new = list_remove_tail(&list)))
294 kmem_free(li_new, sizeof(list_item_t));
295
296 splat_vprint(file, SPLAT_LIST_TEST5_NAME, "Destroying list\n%s", "");
297 list_destroy(&list);
298
299 return rc;
300}
301
302static int
303splat_list_test6(struct file *file, void *arg)
304{
305 list_t list;
306 list_item_t *li, *li_prev;
307 int i, list_size = 8, rc = 0;
308
309 splat_vprint(file, SPLAT_LIST_TEST6_NAME, "Creating list\n%s", "");
310 list_create(&list, sizeof(list_item_t), offsetof(list_item_t, li_node));
311
312 /* Insert all items at the list tail to form a queue */
313 splat_vprint(file, SPLAT_LIST_TEST6_NAME,
314 "Adding %d items to list tail\n", list_size);
315 for (i = 0; i < list_size; i++) {
316 li = kmem_alloc(sizeof(list_item_t), KM_SLEEP);
317 if (li == NULL) {
318 rc = -ENOMEM;
319 goto out;
320 }
321
322 list_link_init(&li->li_node);
323 li->li_data = i;
324 list_insert_tail(&list, li);
325 }
326
327 /* Remove all odd items from the queue */
328 splat_vprint(file, SPLAT_LIST_TEST6_NAME,
96dded38 329 "Removing %d odd items from the list\n", list_size >> 1);
d702c04f
BB
330 for (li = list_head(&list); li != NULL; li = list_next(&list, li)) {
331 if (li->li_data % 2 == 1) {
332 li_prev = list_prev(&list, li);
333 list_remove(&list, li);
ae3b87f9 334 kmem_free(li, sizeof(list_item_t));
d702c04f
BB
335 li = li_prev;
336 }
337 }
338
339 splat_vprint(file, SPLAT_LIST_TEST6_NAME, "Validating %d item "
340 "list is a queue of only even elements\n", list_size / 2);
341 rc = splat_list_validate(&list, list_size / 2, LIST_ORDER_QUEUE, 2);
342 if (rc)
343 splat_vprint(file, SPLAT_LIST_TEST6_NAME,
344 "List validation failed, %d\n", rc);
345out:
346 /* Remove all items */
347 splat_vprint(file, SPLAT_LIST_TEST6_NAME,
348 "Removing %d items from list tail\n", list_size / 2);
349 while ((li = list_remove_tail(&list)))
350 kmem_free(li, sizeof(list_item_t));
351
352 splat_vprint(file, SPLAT_LIST_TEST6_NAME, "Destroying list\n%s", "");
353 list_destroy(&list);
354
355 return rc;
356}
357
434d1d0f
BB
358static int
359splat_list_test7(struct file *file, void *arg)
360{
361 list_t list;
362 list_item_t *li;
363 int rc = 0;
364
365 splat_vprint(file, SPLAT_LIST_TEST7_NAME, "Creating list\n%s", "");
366 list_create(&list, sizeof(list_item_t), offsetof(list_item_t, li_node));
367
368 li = kmem_alloc(sizeof(list_item_t), KM_SLEEP);
369 if (li == NULL) {
370 rc = -ENOMEM;
371 goto out;
372 }
373
374 /* Validate newly initialized node is inactive */
375 splat_vprint(file, SPLAT_LIST_TEST7_NAME, "Init list node\n%s", "");
376 list_link_init(&li->li_node);
377 if (list_link_active(&li->li_node)) {
378 splat_vprint(file, SPLAT_LIST_TEST7_NAME, "Newly initialized "
379 "list node should inactive %p/%p\n",
380 li->li_node.prev, li->li_node.next);
381 rc = -EINVAL;
63a93055 382 goto out_li;
434d1d0f
BB
383 }
384
385 /* Validate node is active when linked in to a list */
386 splat_vprint(file, SPLAT_LIST_TEST7_NAME, "Insert list node\n%s", "");
387 list_insert_head(&list, li);
388 if (!list_link_active(&li->li_node)) {
389 splat_vprint(file, SPLAT_LIST_TEST7_NAME, "List node "
390 "inserted in list should be active %p/%p\n",
391 li->li_node.prev, li->li_node.next);
392 rc = -EINVAL;
393 goto out;
394 }
395
396 /* Validate node is inactive when removed from list */
397 splat_vprint(file, SPLAT_LIST_TEST7_NAME, "Remove list node\n%s", "");
398 list_remove(&list, li);
399 if (list_link_active(&li->li_node)) {
400 splat_vprint(file, SPLAT_LIST_TEST7_NAME, "List node "
401 "removed from list should be inactive %p/%p\n",
402 li->li_node.prev, li->li_node.next);
403 rc = -EINVAL;
404 }
63a93055 405out_li:
434d1d0f
BB
406 kmem_free(li, sizeof(list_item_t));
407out:
408 /* Remove all items */
409 while ((li = list_remove_head(&list)))
410 kmem_free(li, sizeof(list_item_t));
411
412 splat_vprint(file, SPLAT_LIST_TEST7_NAME, "Destroying list\n%s", "");
413 list_destroy(&list);
414
415 return rc;
416}
417
d702c04f
BB
418splat_subsystem_t *
419splat_list_init(void)
420{
421 splat_subsystem_t *sub;
422
423 sub = kmalloc(sizeof(*sub), GFP_KERNEL);
424 if (sub == NULL)
425 return NULL;
426
427 memset(sub, 0, sizeof(*sub));
428 strncpy(sub->desc.name, SPLAT_LIST_NAME, SPLAT_NAME_SIZE);
429 strncpy(sub->desc.desc, SPLAT_LIST_DESC, SPLAT_DESC_SIZE);
430 INIT_LIST_HEAD(&sub->subsystem_list);
431 INIT_LIST_HEAD(&sub->test_list);
432 spin_lock_init(&sub->test_lock);
433 sub->desc.id = SPLAT_SUBSYSTEM_LIST;
434
435 SPLAT_TEST_INIT(sub, SPLAT_LIST_TEST1_NAME, SPLAT_LIST_TEST1_DESC,
436 SPLAT_LIST_TEST1_ID, splat_list_test1);
437 SPLAT_TEST_INIT(sub, SPLAT_LIST_TEST2_NAME, SPLAT_LIST_TEST2_DESC,
438 SPLAT_LIST_TEST2_ID, splat_list_test2);
439 SPLAT_TEST_INIT(sub, SPLAT_LIST_TEST3_NAME, SPLAT_LIST_TEST3_DESC,
440 SPLAT_LIST_TEST3_ID, splat_list_test3);
441 SPLAT_TEST_INIT(sub, SPLAT_LIST_TEST4_NAME, SPLAT_LIST_TEST4_DESC,
442 SPLAT_LIST_TEST4_ID, splat_list_test4);
443 SPLAT_TEST_INIT(sub, SPLAT_LIST_TEST5_NAME, SPLAT_LIST_TEST5_DESC,
444 SPLAT_LIST_TEST5_ID, splat_list_test5);
445 SPLAT_TEST_INIT(sub, SPLAT_LIST_TEST6_NAME, SPLAT_LIST_TEST6_DESC,
446 SPLAT_LIST_TEST6_ID, splat_list_test6);
434d1d0f
BB
447 SPLAT_TEST_INIT(sub, SPLAT_LIST_TEST7_NAME, SPLAT_LIST_TEST7_DESC,
448 SPLAT_LIST_TEST7_ID, splat_list_test7);
d702c04f
BB
449
450 return sub;
451}
452
453void
454splat_list_fini(splat_subsystem_t *sub)
455{
456 ASSERT(sub);
457
434d1d0f 458 SPLAT_TEST_FINI(sub, SPLAT_LIST_TEST7_ID);
d702c04f
BB
459 SPLAT_TEST_FINI(sub, SPLAT_LIST_TEST6_ID);
460 SPLAT_TEST_FINI(sub, SPLAT_LIST_TEST5_ID);
461 SPLAT_TEST_FINI(sub, SPLAT_LIST_TEST4_ID);
462 SPLAT_TEST_FINI(sub, SPLAT_LIST_TEST3_ID);
463 SPLAT_TEST_FINI(sub, SPLAT_LIST_TEST2_ID);
464 SPLAT_TEST_FINI(sub, SPLAT_LIST_TEST1_ID);
465
466 kfree(sub);
467}
468
469int
470splat_list_id(void)
471{
472 return SPLAT_SUBSYSTEM_LIST;
473}