]>
git.proxmox.com Git - mirror_spl.git/blob - module/splat/splat-list.c
1 /*****************************************************************************\
2 * Copyright (C) 2007-2010 Lawrence Livermore National Security, LLC.
3 * Copyright (C) 2007 The Regents of the University of California.
4 * Produced at Lawrence Livermore National Laboratory (cf, DISCLAIMER).
5 * Written by Brian Behlendorf <behlendorf1@llnl.gov>.
8 * This file is part of the SPL, Solaris Porting Layer.
9 * For details, see <http://zfsonlinux.org/>.
11 * The SPL is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the
13 * Free Software Foundation; either version 2 of the License, or (at your
14 * option) any later version.
16 * The SPL is distributed in the hope that it will be useful, but WITHOUT
17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
18 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 * You should have received a copy of the GNU General Public License along
22 * with the SPL. If not, see <http://www.gnu.org/licenses/>.
23 *****************************************************************************
24 * Solaris Porting LAyer Tests (SPLAT) List Tests.
25 \*****************************************************************************/
29 #include "splat-internal.h"
31 #define SPLAT_LIST_NAME "list"
32 #define SPLAT_LIST_DESC "Kernel List Tests"
34 #define SPLAT_LIST_TEST1_ID 0x0c01
35 #define SPLAT_LIST_TEST1_NAME "create/destroy"
36 #define SPLAT_LIST_TEST1_DESC "Create/destroy Test"
38 #define SPLAT_LIST_TEST2_ID 0x0c02
39 #define SPLAT_LIST_TEST2_NAME "ins/rm head"
40 #define SPLAT_LIST_TEST2_DESC "Insert/remove head Test"
42 #define SPLAT_LIST_TEST3_ID 0x0c03
43 #define SPLAT_LIST_TEST3_NAME "ins/rm tail"
44 #define SPLAT_LIST_TEST3_DESC "Insert/remove tail Test"
46 #define SPLAT_LIST_TEST4_ID 0x0c04
47 #define SPLAT_LIST_TEST4_NAME "insert_after"
48 #define SPLAT_LIST_TEST4_DESC "Insert_after Test"
50 #define SPLAT_LIST_TEST5_ID 0x0c05
51 #define SPLAT_LIST_TEST5_NAME "insert_before"
52 #define SPLAT_LIST_TEST5_DESC "Insert_before Test"
54 #define SPLAT_LIST_TEST6_ID 0x0c06
55 #define SPLAT_LIST_TEST6_NAME "remove"
56 #define SPLAT_LIST_TEST6_DESC "Remove Test"
58 #define SPLAT_LIST_TEST7_ID 0x0c7
59 #define SPLAT_LIST_TEST7_NAME "active"
60 #define SPLAT_LIST_TEST7_DESC "Active Test"
62 /* It is important that li_node is not the first element, this
63 * ensures the list_d2l/list_object macros are working correctly. */
64 typedef struct list_item
{
69 #define LIST_ORDER_STACK 0
70 #define LIST_ORDER_QUEUE 1
73 splat_list_test1(struct file
*file
, void *arg
)
77 splat_vprint(file
, SPLAT_LIST_TEST1_NAME
, "Creating list\n%s", "");
78 list_create(&list
, sizeof(list_item_t
), offsetof(list_item_t
, li_node
));
80 if (!list_is_empty(&list
)) {
81 splat_vprint(file
, SPLAT_LIST_TEST1_NAME
,
82 "New list NOT empty%s\n", "");
83 /* list_destroy() intentionally skipped to avoid assert */
87 splat_vprint(file
, SPLAT_LIST_TEST1_NAME
, "Destroying list\n%s", "");
90 /* Validate the list has been destroyed */
91 if (list_link_active(&list
.list_head
)) {
92 splat_vprint(file
, SPLAT_LIST_TEST1_NAME
,
93 "Destroyed list still active%s", "");
101 splat_list_validate(list_t
*list
, int size
, int order
, int mult
)
106 /* Walk all items in list from head to verify stack or queue
107 * ordering. We bound the for loop by size+1 to ensure that
108 * we still terminate if there is list corruption. We also
109 * intentionally make things a little more complex than they
110 * need to be by using list_head/list_next for queues, and
111 * list_tail/list_prev for stacks. This is simply done for
112 * coverage and to ensure these function are working right.
114 for (i
= 0, li
= (order
? list_head(list
) : list_tail(list
));
115 i
< size
+ 1 && li
!= NULL
;
116 i
++, li
= (order
? list_next(list
, li
) : list_prev(list
, li
)))
117 if (li
->li_data
!= i
* mult
)
127 splat_list_test2(struct file
*file
, void *arg
)
131 int i
, list_size
= 8, rc
= 0;
133 splat_vprint(file
, SPLAT_LIST_TEST2_NAME
, "Creating list\n%s", "");
134 list_create(&list
, sizeof(list_item_t
), offsetof(list_item_t
, li_node
));
136 /* Insert all items at the list head to form a stack */
137 splat_vprint(file
, SPLAT_LIST_TEST2_NAME
,
138 "Adding %d items to list head\n", list_size
);
139 for (i
= 0; i
< list_size
; i
++) {
140 li
= kmem_alloc(sizeof(list_item_t
), KM_SLEEP
);
146 list_link_init(&li
->li_node
);
148 list_insert_head(&list
, li
);
151 splat_vprint(file
, SPLAT_LIST_TEST2_NAME
,
152 "Validating %d item list is a stack\n", list_size
);
153 rc
= splat_list_validate(&list
, list_size
, LIST_ORDER_STACK
, 1);
155 splat_vprint(file
, SPLAT_LIST_TEST2_NAME
,
156 "List validation failed, %d\n", rc
);
158 /* Remove all items */
159 splat_vprint(file
, SPLAT_LIST_TEST2_NAME
,
160 "Removing %d items from list head\n", list_size
);
161 while ((li
= list_remove_head(&list
)))
162 kmem_free(li
, sizeof(list_item_t
));
164 splat_vprint(file
, SPLAT_LIST_TEST2_NAME
, "Destroying list\n%s", "");
171 splat_list_test3(struct file
*file
, void *arg
)
175 int i
, list_size
= 8, rc
= 0;
177 splat_vprint(file
, SPLAT_LIST_TEST3_NAME
, "Creating list\n%s", "");
178 list_create(&list
, sizeof(list_item_t
), offsetof(list_item_t
, li_node
));
180 /* Insert all items at the list tail to form a queue */
181 splat_vprint(file
, SPLAT_LIST_TEST3_NAME
,
182 "Adding %d items to list tail\n", list_size
);
183 for (i
= 0; i
< list_size
; i
++) {
184 li
= kmem_alloc(sizeof(list_item_t
), KM_SLEEP
);
190 list_link_init(&li
->li_node
);
192 list_insert_tail(&list
, li
);
195 splat_vprint(file
, SPLAT_LIST_TEST3_NAME
,
196 "Validating %d item list is a queue\n", list_size
);
197 rc
= splat_list_validate(&list
, list_size
, LIST_ORDER_QUEUE
, 1);
199 splat_vprint(file
, SPLAT_LIST_TEST3_NAME
,
200 "List validation failed, %d\n", rc
);
202 /* Remove all items */
203 splat_vprint(file
, SPLAT_LIST_TEST3_NAME
,
204 "Removing %d items from list tail\n", list_size
);
205 while ((li
= list_remove_tail(&list
)))
206 kmem_free(li
, sizeof(list_item_t
));
208 splat_vprint(file
, SPLAT_LIST_TEST3_NAME
, "Destroying list\n%s", "");
215 splat_list_test4(struct file
*file
, void *arg
)
218 list_item_t
*li_new
, *li_last
= NULL
;
219 int i
, list_size
= 8, rc
= 0;
221 splat_vprint(file
, SPLAT_LIST_TEST4_NAME
, "Creating list\n%s", "");
222 list_create(&list
, sizeof(list_item_t
), offsetof(list_item_t
, li_node
));
224 /* Insert all items after the last item to form a queue */
225 splat_vprint(file
, SPLAT_LIST_TEST4_NAME
,
226 "Adding %d items each after the last item\n", list_size
);
227 for (i
= 0; i
< list_size
; i
++) {
228 li_new
= kmem_alloc(sizeof(list_item_t
), KM_SLEEP
);
229 if (li_new
== NULL
) {
234 list_link_init(&li_new
->li_node
);
236 list_insert_after(&list
, li_last
, li_new
);
240 splat_vprint(file
, SPLAT_LIST_TEST4_NAME
,
241 "Validating %d item list is a queue\n", list_size
);
242 rc
= splat_list_validate(&list
, list_size
, LIST_ORDER_QUEUE
, 1);
244 splat_vprint(file
, SPLAT_LIST_TEST4_NAME
,
245 "List validation failed, %d\n", rc
);
247 /* Remove all items */
248 splat_vprint(file
, SPLAT_LIST_TEST4_NAME
,
249 "Removing %d items from list tail\n", list_size
);
250 while ((li_new
= list_remove_head(&list
)))
251 kmem_free(li_new
, sizeof(list_item_t
));
253 splat_vprint(file
, SPLAT_LIST_TEST4_NAME
, "Destroying list\n%s", "");
260 splat_list_test5(struct file
*file
, void *arg
)
263 list_item_t
*li_new
, *li_last
= NULL
;
264 int i
, list_size
= 8, rc
= 0;
266 splat_vprint(file
, SPLAT_LIST_TEST5_NAME
, "Creating list\n%s", "");
267 list_create(&list
, sizeof(list_item_t
), offsetof(list_item_t
, li_node
));
269 /* Insert all items before the last item to form a stack */
270 splat_vprint(file
, SPLAT_LIST_TEST5_NAME
,
271 "Adding %d items each before the last item\n", list_size
);
272 for (i
= 0; i
< list_size
; i
++) {
273 li_new
= kmem_alloc(sizeof(list_item_t
), KM_SLEEP
);
274 if (li_new
== NULL
) {
279 list_link_init(&li_new
->li_node
);
281 list_insert_before(&list
, li_last
, li_new
);
285 splat_vprint(file
, SPLAT_LIST_TEST5_NAME
,
286 "Validating %d item list is a queue\n", list_size
);
287 rc
= splat_list_validate(&list
, list_size
, LIST_ORDER_STACK
, 1);
289 splat_vprint(file
, SPLAT_LIST_TEST5_NAME
,
290 "List validation failed, %d\n", rc
);
292 /* Remove all items */
293 splat_vprint(file
, SPLAT_LIST_TEST5_NAME
,
294 "Removing %d items from list tail\n", list_size
);
295 while ((li_new
= list_remove_tail(&list
)))
296 kmem_free(li_new
, sizeof(list_item_t
));
298 splat_vprint(file
, SPLAT_LIST_TEST5_NAME
, "Destroying list\n%s", "");
305 splat_list_test6(struct file
*file
, void *arg
)
308 list_item_t
*li
, *li_prev
;
309 int i
, list_size
= 8, rc
= 0;
311 splat_vprint(file
, SPLAT_LIST_TEST6_NAME
, "Creating list\n%s", "");
312 list_create(&list
, sizeof(list_item_t
), offsetof(list_item_t
, li_node
));
314 /* Insert all items at the list tail to form a queue */
315 splat_vprint(file
, SPLAT_LIST_TEST6_NAME
,
316 "Adding %d items to list tail\n", list_size
);
317 for (i
= 0; i
< list_size
; i
++) {
318 li
= kmem_alloc(sizeof(list_item_t
), KM_SLEEP
);
324 list_link_init(&li
->li_node
);
326 list_insert_tail(&list
, li
);
329 /* Remove all odd items from the queue */
330 splat_vprint(file
, SPLAT_LIST_TEST6_NAME
,
331 "Removing %d odd items from the list\n", list_size
>> 1);
332 for (li
= list_head(&list
); li
!= NULL
; li
= list_next(&list
, li
)) {
333 if (li
->li_data
% 2 == 1) {
334 li_prev
= list_prev(&list
, li
);
335 list_remove(&list
, li
);
336 kmem_free(li
, sizeof(list_item_t
));
341 splat_vprint(file
, SPLAT_LIST_TEST6_NAME
, "Validating %d item "
342 "list is a queue of only even elements\n", list_size
/ 2);
343 rc
= splat_list_validate(&list
, list_size
/ 2, LIST_ORDER_QUEUE
, 2);
345 splat_vprint(file
, SPLAT_LIST_TEST6_NAME
,
346 "List validation failed, %d\n", rc
);
348 /* Remove all items */
349 splat_vprint(file
, SPLAT_LIST_TEST6_NAME
,
350 "Removing %d items from list tail\n", list_size
/ 2);
351 while ((li
= list_remove_tail(&list
)))
352 kmem_free(li
, sizeof(list_item_t
));
354 splat_vprint(file
, SPLAT_LIST_TEST6_NAME
, "Destroying list\n%s", "");
361 splat_list_test7(struct file
*file
, void *arg
)
367 splat_vprint(file
, SPLAT_LIST_TEST7_NAME
, "Creating list\n%s", "");
368 list_create(&list
, sizeof(list_item_t
), offsetof(list_item_t
, li_node
));
370 li
= kmem_alloc(sizeof(list_item_t
), KM_SLEEP
);
376 /* Validate newly initialized node is inactive */
377 splat_vprint(file
, SPLAT_LIST_TEST7_NAME
, "Init list node\n%s", "");
378 list_link_init(&li
->li_node
);
379 if (list_link_active(&li
->li_node
)) {
380 splat_vprint(file
, SPLAT_LIST_TEST7_NAME
, "Newly initialized "
381 "list node should inactive %p/%p\n",
382 li
->li_node
.prev
, li
->li_node
.next
);
387 /* Validate node is active when linked in to a list */
388 splat_vprint(file
, SPLAT_LIST_TEST7_NAME
, "Insert list node\n%s", "");
389 list_insert_head(&list
, li
);
390 if (!list_link_active(&li
->li_node
)) {
391 splat_vprint(file
, SPLAT_LIST_TEST7_NAME
, "List node "
392 "inserted in list should be active %p/%p\n",
393 li
->li_node
.prev
, li
->li_node
.next
);
398 /* Validate node is inactive when removed from list */
399 splat_vprint(file
, SPLAT_LIST_TEST7_NAME
, "Remove list node\n%s", "");
400 list_remove(&list
, li
);
401 if (list_link_active(&li
->li_node
)) {
402 splat_vprint(file
, SPLAT_LIST_TEST7_NAME
, "List node "
403 "removed from list should be inactive %p/%p\n",
404 li
->li_node
.prev
, li
->li_node
.next
);
408 kmem_free(li
, sizeof(list_item_t
));
410 /* Remove all items */
411 while ((li
= list_remove_head(&list
)))
412 kmem_free(li
, sizeof(list_item_t
));
414 splat_vprint(file
, SPLAT_LIST_TEST7_NAME
, "Destroying list\n%s", "");
421 splat_list_init(void)
423 splat_subsystem_t
*sub
;
425 sub
= kmalloc(sizeof(*sub
), GFP_KERNEL
);
429 memset(sub
, 0, sizeof(*sub
));
430 strncpy(sub
->desc
.name
, SPLAT_LIST_NAME
, SPLAT_NAME_SIZE
);
431 strncpy(sub
->desc
.desc
, SPLAT_LIST_DESC
, SPLAT_DESC_SIZE
);
432 INIT_LIST_HEAD(&sub
->subsystem_list
);
433 INIT_LIST_HEAD(&sub
->test_list
);
434 spin_lock_init(&sub
->test_lock
);
435 sub
->desc
.id
= SPLAT_SUBSYSTEM_LIST
;
437 splat_test_init(sub
, SPLAT_LIST_TEST1_NAME
, SPLAT_LIST_TEST1_DESC
,
438 SPLAT_LIST_TEST1_ID
, splat_list_test1
);
439 splat_test_init(sub
, SPLAT_LIST_TEST2_NAME
, SPLAT_LIST_TEST2_DESC
,
440 SPLAT_LIST_TEST2_ID
, splat_list_test2
);
441 splat_test_init(sub
, SPLAT_LIST_TEST3_NAME
, SPLAT_LIST_TEST3_DESC
,
442 SPLAT_LIST_TEST3_ID
, splat_list_test3
);
443 splat_test_init(sub
, SPLAT_LIST_TEST4_NAME
, SPLAT_LIST_TEST4_DESC
,
444 SPLAT_LIST_TEST4_ID
, splat_list_test4
);
445 splat_test_init(sub
, SPLAT_LIST_TEST5_NAME
, SPLAT_LIST_TEST5_DESC
,
446 SPLAT_LIST_TEST5_ID
, splat_list_test5
);
447 splat_test_init(sub
, SPLAT_LIST_TEST6_NAME
, SPLAT_LIST_TEST6_DESC
,
448 SPLAT_LIST_TEST6_ID
, splat_list_test6
);
449 splat_test_init(sub
, SPLAT_LIST_TEST7_NAME
, SPLAT_LIST_TEST7_DESC
,
450 SPLAT_LIST_TEST7_ID
, splat_list_test7
);
456 splat_list_fini(splat_subsystem_t
*sub
)
460 splat_test_fini(sub
, SPLAT_LIST_TEST7_ID
);
461 splat_test_fini(sub
, SPLAT_LIST_TEST6_ID
);
462 splat_test_fini(sub
, SPLAT_LIST_TEST5_ID
);
463 splat_test_fini(sub
, SPLAT_LIST_TEST4_ID
);
464 splat_test_fini(sub
, SPLAT_LIST_TEST3_ID
);
465 splat_test_fini(sub
, SPLAT_LIST_TEST2_ID
);
466 splat_test_fini(sub
, SPLAT_LIST_TEST1_ID
);
474 return SPLAT_SUBSYSTEM_LIST
;