]> git.proxmox.com Git - mirror_spl.git/blame - cmd/splat.c
Move dir
[mirror_spl.git] / cmd / splat.c
CommitLineData
564f6d15 1/* Solaris Porting Layer Aggressive Test (SPLAT) userspace interface */
f1ca4da6 2
3#include <stdlib.h>
4#include <stddef.h>
5#include <stdio.h>
6#include <string.h>
7#include <errno.h>
8#include <getopt.h>
9#include <assert.h>
10#include <fcntl.h>
f1ca4da6 11#include <sys/ioctl.h>
12#include <sys/stat.h>
13#include <sys/types.h>
14#include <unistd.h>
15#include "splat.h"
16
17#undef ioctl
18
19static const char shortOpts[] = "hvlat:xc";
20static const struct option longOpts[] = {
21 { "help", no_argument, 0, 'h' },
22 { "verbose", no_argument, 0, 'v' },
23 { "list", no_argument, 0, 'l' },
24 { "all", no_argument, 0, 'a' },
25 { "test", required_argument, 0, 't' },
26 { "exit", no_argument, 0, 'x' },
27 { "nocolor", no_argument, 0, 'c' },
28 { 0, 0, 0, 0 }
29};
30
564f6d15 31static List subsystems; /* Subsystem/tests */
f1ca4da6 32static int kztctl_fd; /* Control file descriptor */
33static char kzt_version[KZT_VERSION_SIZE]; /* Kernel version string */
34static char *kzt_buffer = NULL; /* Scratch space area */
35static int kzt_buffer_size = 0; /* Scratch space size */
36
37
564f6d15 38static void test_list(List, int);
f1ca4da6 39static int dev_clear(void);
564f6d15 40static void subsystem_fini(subsystem_t *);
41static void test_fini(test_t *);
f1ca4da6 42
43
44static int usage(void) {
45 fprintf(stderr, "usage: kzt [hvla] [-t <subsystem:<tests>>]\n");
46 fprintf(stderr,
47 " --help -h This help\n"
48 " --verbose -v Increase verbosity\n"
49 " --list -l List all tests in all subsystems\n"
50 " --all -a Run all tests in all subsystems\n"
51 " --test -t <sub:test> Run 'test' in subsystem 'sub'\n"
52 " --exit -x Exit on first test error\n"
53 " --nocolor -c Do not colorize output\n");
54 fprintf(stderr, "\n"
55 "Examples:\n"
56 " kzt -t kmem:all # Runs all kmem tests\n"
57 " kzt -t taskq:0x201 # Run taskq test 0x201\n");
58
59 return 0;
60}
61
62static subsystem_t *subsystem_init(kzt_user_t *desc)
63{
64 subsystem_t *sub;
65
66 sub = (subsystem_t *)malloc(sizeof(*sub));
67 if (sub == NULL)
68 return NULL;
69
70 memcpy(&sub->sub_desc, desc, sizeof(*desc));
f1ca4da6 71
564f6d15 72 sub->sub_tests = list_create((ListDelF)test_fini);
f1ca4da6 73 if (sub->sub_tests == NULL) {
74 free(sub);
75 return NULL;
76 }
77
78 return sub;
79}
80
81static void subsystem_fini(subsystem_t *sub)
82{
83 assert(sub != NULL);
f1ca4da6 84 free(sub);
85}
86
87static int subsystem_setup(void)
88{
89 kzt_cfg_t *cfg;
90 int i, rc, size, cfg_size;
91 subsystem_t *sub;
92 kzt_user_t *desc;
93
94 /* Aquire the number of registered subsystems */
95 cfg_size = sizeof(*cfg);
96 cfg = (kzt_cfg_t *)malloc(cfg_size);
97 if (cfg == NULL)
98 return -ENOMEM;
99
100 memset(cfg, 0, cfg_size);
101 cfg->cfg_magic = KZT_CFG_MAGIC;
102 cfg->cfg_cmd = KZT_CFG_SUBSYSTEM_COUNT;
103
104 rc = ioctl(kztctl_fd, KZT_CFG, cfg);
105 if (rc) {
106 fprintf(stderr, "Ioctl() error %lu / %d: %d\n",
107 (unsigned long) KZT_CFG, cfg->cfg_cmd, errno);
108 free(cfg);
109 return rc;
110 }
111
112 size = cfg->cfg_rc1;
113 free(cfg);
114
115 /* Based on the newly aquired number of subsystems allocate enough
116 * memory to get the descriptive information for them all. */
117 cfg_size = sizeof(*cfg) + size * sizeof(kzt_user_t);
118 cfg = (kzt_cfg_t *)malloc(cfg_size);
119 if (cfg == NULL)
120 return -ENOMEM;
121
122 memset(cfg, 0, cfg_size);
123 cfg->cfg_magic = KZT_CFG_MAGIC;
124 cfg->cfg_cmd = KZT_CFG_SUBSYSTEM_LIST;
125 cfg->cfg_data.kzt_subsystems.size = size;
126
127 rc = ioctl(kztctl_fd, KZT_CFG, cfg);
128 if (rc) {
129 fprintf(stderr, "Ioctl() error %lu / %d: %d\n",
130 (unsigned long) KZT_CFG, cfg->cfg_cmd, errno);
131 free(cfg);
132 return rc;
133 }
134
135 /* Add the new subsystems in to the global list */
136 size = cfg->cfg_rc1;
137 for (i = 0; i < size; i++) {
138 desc = &(cfg->cfg_data.kzt_subsystems.descs[i]);
139
140 sub = subsystem_init(desc);
141 if (sub == NULL) {
142 fprintf(stderr, "Error initializing subsystem: %s\n",
143 desc->name);
144 free(cfg);
145 return -ENOMEM;
146 }
147
564f6d15 148 list_append(subsystems, sub);
f1ca4da6 149 }
150
151 free(cfg);
152 return 0;
153}
154
564f6d15 155/* XXX - Commented out until we sort the lists */
156#if 0
f1ca4da6 157static int subsystem_compare(const void *l_arg, const void *r_arg, void *private)
158{
159 const subsystem_t *l = l_arg;
160 const subsystem_t *r = r_arg;
161
162 if (l->sub_desc.id > r->sub_desc.id)
163 return 1;
164
165 if (l->sub_desc.id < r->sub_desc.id)
166 return -1;
167
168 return 0;
169}
564f6d15 170#endif
f1ca4da6 171
564f6d15 172static void subsystem_list(List l, int indent)
f1ca4da6 173{
564f6d15 174 ListIterator i;
f1ca4da6 175 subsystem_t *sub;
176
177 fprintf(stdout,
178 "------------------------------- "
179 "Available KZT Tests "
180 "-------------------------------\n");
181
564f6d15 182 i = list_iterator_create(l);
183
184 while ((sub = list_next(i))) {
f1ca4da6 185 fprintf(stdout, "%*s0x%0*x %-*s ---- %s ----\n",
186 indent, "",
187 4, sub->sub_desc.id,
188 KZT_NAME_SIZE + 7, sub->sub_desc.name,
189 sub->sub_desc.desc);
190 test_list(sub->sub_tests, indent + 7);
191 }
564f6d15 192
193 list_iterator_destroy(i);
f1ca4da6 194}
195
196static test_t *test_init(subsystem_t *sub, kzt_user_t *desc)
197{
198 test_t *test;
199
200 test = (test_t *)malloc(sizeof(*test));
201 if (test == NULL)
202 return NULL;
203
204 test->test_sub = sub;
205 memcpy(&test->test_desc, desc, sizeof(*desc));
f1ca4da6 206
207 return test;
208}
209
210static void test_fini(test_t *test)
211{
212 assert(test != NULL);
f1ca4da6 213 free(test);
214}
215
216static int test_setup(subsystem_t *sub)
217{
218 kzt_cfg_t *cfg;
219 int i, rc, size;
220 test_t *test;
221 kzt_user_t *desc;
222
223 /* Aquire the number of registered tests for the give subsystem */
224 cfg = (kzt_cfg_t *)malloc(sizeof(*cfg));
225 if (cfg == NULL)
226 return -ENOMEM;
227
228 memset(cfg, 0, sizeof(*cfg));
229 cfg->cfg_magic = KZT_CFG_MAGIC;
230 cfg->cfg_cmd = KZT_CFG_TEST_COUNT;
231 cfg->cfg_arg1 = sub->sub_desc.id; /* Subsystem of interest */
232
233 rc = ioctl(kztctl_fd, KZT_CFG, cfg);
234 if (rc) {
235 fprintf(stderr, "Ioctl() error %lu / %d: %d\n",
236 (unsigned long) KZT_CFG, cfg->cfg_cmd, errno);
237 free(cfg);
238 return rc;
239 }
240
241 size = cfg->cfg_rc1;
242 free(cfg);
243
244 /* Based on the newly aquired number of tests allocate enough
245 * memory to get the descriptive information for them all. */
246 cfg = (kzt_cfg_t *)malloc(sizeof(*cfg) + size * sizeof(kzt_user_t));
247 if (cfg == NULL)
248 return -ENOMEM;
249
250 memset(cfg, 0, sizeof(*cfg) + size * sizeof(kzt_user_t));
251 cfg->cfg_magic = KZT_CFG_MAGIC;
252 cfg->cfg_cmd = KZT_CFG_TEST_LIST;
253 cfg->cfg_arg1 = sub->sub_desc.id; /* Subsystem of interest */
254 cfg->cfg_data.kzt_tests.size = size;
255
256 rc = ioctl(kztctl_fd, KZT_CFG, cfg);
257 if (rc) {
258 fprintf(stderr, "Ioctl() error %lu / %d: %d\n",
259 (unsigned long) KZT_CFG, cfg->cfg_cmd, errno);
260 free(cfg);
261 return rc;
262 }
263
264 /* Add the new tests in to the relevant subsystems */
265 size = cfg->cfg_rc1;
266 for (i = 0; i < size; i++) {
267 desc = &(cfg->cfg_data.kzt_tests.descs[i]);
268
269 test = test_init(sub, desc);
270 if (test == NULL) {
271 fprintf(stderr, "Error initializing test: %s\n",
272 desc->name);
273 free(cfg);
274 return -ENOMEM;
275 }
276
564f6d15 277 list_append(sub->sub_tests, test);
f1ca4da6 278 }
279
280 free(cfg);
281 return 0;
282}
283
564f6d15 284/* XXX - Commented out until we sort the lists */
285#if 0
f1ca4da6 286static int test_compare(const void *l_arg, const void *r_arg, void *private)
287{
288 const test_t *l = l_arg;
289 const test_t *r = r_arg;
290
291 if (l->test_desc.id > r->test_desc.id)
292 return 1;
293
294 if (l->test_desc.id < r->test_desc.id)
295 return -1;
296
297 return 0;
298}
564f6d15 299#endif
f1ca4da6 300
301static test_t *test_copy(test_t *test)
302{
303 return test_init(test->test_sub, &test->test_desc);
304}
305
564f6d15 306static void test_list(List l, int indent)
f1ca4da6 307{
564f6d15 308 ListIterator i;
f1ca4da6 309 test_t *test;
310
564f6d15 311 i = list_iterator_create(l);
312
313 while ((test = list_next(i)))
f1ca4da6 314 fprintf(stdout, "%*s0x%0*x %-*s %-*s\n",
315 indent, "",
316 04, test->test_desc.id,
317 KZT_NAME_SIZE, test->test_desc.name,
318 KZT_DESC_SIZE, test->test_desc.desc);
564f6d15 319
320 list_iterator_destroy(i);
f1ca4da6 321}
322
323static test_t *test_find(char *sub_str, char *test_str)
324{
564f6d15 325 ListIterator si, ti;
f1ca4da6 326 subsystem_t *sub;
327 test_t *test;
328 int sub_num, test_num;
329
330 /* No error checking here because it may not be a number, it's
331 * perfectly OK for it to be a string. Since we're just using
332 * it for comparison purposes this is all very safe.
333 */
334 sub_num = strtol(sub_str, NULL, 0);
335 test_num = strtol(test_str, NULL, 0);
336
564f6d15 337 si = list_iterator_create(subsystems);
338
339 while ((sub = list_next(si))) {
f1ca4da6 340
341 if (strncmp(sub->sub_desc.name, sub_str, KZT_NAME_SIZE) &&
342 sub->sub_desc.id != sub_num)
343 continue;
344
564f6d15 345 ti = list_iterator_create(sub->sub_tests);
346
347 while ((test = list_next(ti))) {
f1ca4da6 348
349 if (!strncmp(test->test_desc.name, test_str,
564f6d15 350 KZT_NAME_SIZE) || test->test_desc.id == test_num) {
351 list_iterator_destroy(ti);
352 list_iterator_destroy(si);
f1ca4da6 353 return test;
564f6d15 354 }
f1ca4da6 355 }
564f6d15 356
357 list_iterator_destroy(ti);
f1ca4da6 358 }
359
564f6d15 360 list_iterator_destroy(si);
361
f1ca4da6 362 return NULL;
363}
364
365static int test_add(cmd_args_t *args, test_t *test)
366{
367 test_t *tmp;
368
369 tmp = test_copy(test);
370 if (tmp == NULL)
371 return -ENOMEM;
372
564f6d15 373 list_append(args->args_tests, tmp);
f1ca4da6 374 return 0;
375}
376
377static int test_add_all(cmd_args_t *args)
378{
564f6d15 379 ListIterator si, ti;
f1ca4da6 380 subsystem_t *sub;
381 test_t *test;
382 int rc;
383
564f6d15 384 si = list_iterator_create(subsystems);
f1ca4da6 385
564f6d15 386 while ((sub = list_next(si))) {
387 ti = list_iterator_create(sub->sub_tests);
f1ca4da6 388
564f6d15 389 while ((test = list_next(ti))) {
390 if ((rc = test_add(args, test))) {
391 list_iterator_destroy(ti);
392 list_iterator_destroy(si);
f1ca4da6 393 return rc;
564f6d15 394 }
f1ca4da6 395 }
564f6d15 396
397 list_iterator_destroy(ti);
f1ca4da6 398 }
399
564f6d15 400 list_iterator_destroy(si);
401
f1ca4da6 402 return 0;
403}
404
405static int test_run(cmd_args_t *args, test_t *test)
406{
407 subsystem_t *sub = test->test_sub;
408 kzt_cmd_t *cmd;
409 int rc, cmd_size;
410
411 dev_clear();
412
413 cmd_size = sizeof(*cmd);
414 cmd = (kzt_cmd_t *)malloc(cmd_size);
415 if (cmd == NULL)
416 return -ENOMEM;
417
418 memset(cmd, 0, cmd_size);
419 cmd->cmd_magic = KZT_CMD_MAGIC;
420 cmd->cmd_subsystem = sub->sub_desc.id;
421 cmd->cmd_test = test->test_desc.id;
422 cmd->cmd_data_size = 0; /* Unused feature */
423
424 fprintf(stdout, "%*s:%-*s ",
425 KZT_NAME_SIZE, sub->sub_desc.name,
426 KZT_NAME_SIZE, test->test_desc.name);
427 fflush(stdout);
428 rc = ioctl(kztctl_fd, KZT_CMD, cmd);
429 if (args->args_do_color) {
430 fprintf(stdout, "%s %s\n", rc ?
431 COLOR_RED "Fail" COLOR_RESET :
432 COLOR_GREEN "Pass" COLOR_RESET,
433 rc ? strerror(errno) : "");
434 } else {
435 fprintf(stdout, "%s %s\n", rc ?
436 "Fail" : "Pass",
437 rc ? strerror(errno) : "");
438 }
439 fflush(stdout);
440 free(cmd);
441
442 if (args->args_verbose) {
443 if ((rc = read(kztctl_fd, kzt_buffer, kzt_buffer_size - 1)) < 0) {
444 fprintf(stdout, "Error reading results: %d\n", rc);
445 } else {
446 fprintf(stdout, "\n%s\n", kzt_buffer);
447 fflush(stdout);
448 }
449 }
450
451 return rc;
452}
453
454static int tests_run(cmd_args_t *args)
455{
564f6d15 456 ListIterator i;
f1ca4da6 457 test_t *test;
458 int rc;
459
460 fprintf(stdout,
461 "------------------------------- "
462 "Running KZT Tests "
463 "-------------------------------\n");
464
564f6d15 465 i = list_iterator_create(args->args_tests);
f1ca4da6 466
564f6d15 467 while ((test = list_next(i))) {
f1ca4da6 468 rc = test_run(args, test);
564f6d15 469 if (rc && args->args_exit_on_error) {
470 list_iterator_destroy(i);
f1ca4da6 471 return rc;
564f6d15 472 }
f1ca4da6 473 }
474
564f6d15 475 list_iterator_destroy(i);
f1ca4da6 476 return 0;
477}
478
479static int args_parse_test(cmd_args_t *args, char *str)
480{
564f6d15 481 ListIterator si, ti;
f1ca4da6 482 subsystem_t *s;
483 test_t *t;
484 char *sub_str, *test_str;
485 int sub_num, test_num;
486 int sub_all = 0, test_all = 0;
487 int rc, flag = 0;
488
489 test_str = strchr(str, ':');
490 if (test_str == NULL) {
491 fprintf(stderr, "Test must be of the "
492 "form <subsystem:test>\n");
493 return -EINVAL;
494 }
495
496 sub_str = str;
497 test_str[0] = '\0';
498 test_str = test_str + 1;
499
500 sub_num = strtol(sub_str, NULL, 0);
501 test_num = strtol(test_str, NULL, 0);
502
503 if (!strncasecmp(sub_str, "all", strlen(sub_str)) || (sub_num == -1))
504 sub_all = 1;
505
506 if (!strncasecmp(test_str, "all", strlen(test_str)) || (test_num == -1))
507 test_all = 1;
508
564f6d15 509 si = list_iterator_create(subsystems);
510
f1ca4da6 511 if (sub_all) {
512 if (test_all) {
513 /* Add all tests from all subsystems */
564f6d15 514 while ((s = list_next(si))) {
515 ti = list_iterator_create(s->sub_tests);
516 while ((t = list_next(ti))) {
517 if ((rc = test_add(args, t))) {
518 list_iterator_destroy(ti);
f1ca4da6 519 goto error_run;
564f6d15 520 }
521 }
522 list_iterator_destroy(ti);
523 }
f1ca4da6 524 } else {
525 /* Add a specific test from all subsystems */
564f6d15 526 while ((s = list_next(si))) {
527 if ((t = test_find(s->sub_desc.name,test_str))) {
528 if ((rc = test_add(args, t)))
f1ca4da6 529 goto error_run;
530
531 flag = 1;
532 }
533 }
534
535 if (!flag)
536 fprintf(stderr, "No tests '%s:%s' could be "
537 "found\n", sub_str, test_str);
538 }
539 } else {
540 if (test_all) {
541 /* Add all tests from a specific subsystem */
564f6d15 542 while ((s = list_next(si))) {
f1ca4da6 543 if (strncasecmp(sub_str, s->sub_desc.name,
544 strlen(sub_str)))
545 continue;
546
564f6d15 547 ti = list_iterator_create(s->sub_tests);
548 while ((t = list_next(ti))) {
549 if ((rc = test_add(args, t))) {
550 list_iterator_destroy(ti);
f1ca4da6 551 goto error_run;
564f6d15 552 }
553 }
554 list_iterator_destroy(ti);
f1ca4da6 555 }
556 } else {
557 /* Add a specific test from a specific subsystem */
564f6d15 558 if ((t = test_find(sub_str, test_str))) {
559 if ((rc = test_add(args, t)))
f1ca4da6 560 goto error_run;
561 } else {
562 fprintf(stderr, "Test '%s:%s' could not be "
563 "found\n", sub_str, test_str);
564 return -EINVAL;
565 }
566 }
567 }
568
564f6d15 569 list_iterator_destroy(si);
570
f1ca4da6 571 return 0;
572
573error_run:
564f6d15 574 list_iterator_destroy(si);
575
f1ca4da6 576 fprintf(stderr, "Test '%s:%s' not added to run list: %d\n",
577 sub_str, test_str, rc);
564f6d15 578
f1ca4da6 579 return rc;
580}
581
582static void args_fini(cmd_args_t *args)
583{
f1ca4da6 584 assert(args != NULL);
585
564f6d15 586 if (args->args_tests != NULL)
587 list_destroy(args->args_tests);
f1ca4da6 588
589 free(args);
590}
591
592static cmd_args_t *
593args_init(int argc, char **argv)
594{
595 cmd_args_t *args;
596 int c, rc;
597
598 if (argc == 1) {
599 usage();
600 return (cmd_args_t *) NULL;
601 }
602
603 /* Configure and populate the args structures */
604 args = malloc(sizeof(*args));
605 if (args == NULL)
606 return NULL;
607
608 memset(args, 0, sizeof(*args));
609 args->args_verbose = 0;
610 args->args_do_list = 0;
611 args->args_do_all = 0;
612 args->args_do_color = 1;
613 args->args_exit_on_error = 0;
564f6d15 614 args->args_tests = list_create((ListDelF)test_fini);
f1ca4da6 615 if (args->args_tests == NULL) {
616 args_fini(args);
617 return NULL;
618 }
619
620 while ((c = getopt_long(argc, argv, shortOpts, longOpts, NULL)) != -1){
621 switch (c) {
622 case 'v': args->args_verbose++; break;
623 case 'l': args->args_do_list = 1; break;
624 case 'a': args->args_do_all = 1; break;
625 case 'c': args->args_do_color = 0; break;
626 case 'x': args->args_exit_on_error = 1; break;
627 case 't':
628 if (args->args_do_all) {
629 fprintf(stderr, "Option -t <subsystem:test> is "
630 "useless when used with -a\n");
631 args_fini(args);
632 return NULL;
633 }
634
635 rc = args_parse_test(args, argv[optind - 1]);
636 if (rc) {
637 args_fini(args);
638 return NULL;
639 }
640 break;
641 case 'h':
642 case '?':
643 usage();
644 args_fini(args);
645 return NULL;
646 default:
647 fprintf(stderr, "Unknown option '%s'\n",
648 argv[optind - 1]);
649 break;
650 }
651 }
652
653 return args;
654}
655
656static int
657dev_clear(void)
658{
659 kzt_cfg_t cfg;
660 int rc;
661
662 memset(&cfg, 0, sizeof(cfg));
663 cfg.cfg_magic = KZT_CFG_MAGIC;
664 cfg.cfg_cmd = KZT_CFG_BUFFER_CLEAR;
665 cfg.cfg_arg1 = 0;
666
667 rc = ioctl(kztctl_fd, KZT_CFG, &cfg);
668 if (rc)
669 fprintf(stderr, "Ioctl() error %lu / %d: %d\n",
670 (unsigned long) KZT_CFG, cfg.cfg_cmd, errno);
671
672 lseek(kztctl_fd, 0, SEEK_SET);
673
674 return rc;
675}
676
677static int
678dev_size(int size)
679{
680 kzt_cfg_t cfg;
681 int rc;
682
683 memset(&cfg, 0, sizeof(cfg));
684 cfg.cfg_magic = KZT_CFG_MAGIC;
685 cfg.cfg_cmd = KZT_CFG_BUFFER_SIZE;
686 cfg.cfg_arg1 = size;
687
688 rc = ioctl(kztctl_fd, KZT_CFG, &cfg);
689 if (rc) {
690 fprintf(stderr, "Ioctl() error %lu / %d: %d\n",
691 (unsigned long) KZT_CFG, cfg.cfg_cmd, errno);
692 return rc;
693 }
694
695 return cfg.cfg_rc1;
696}
697
698static void
699dev_fini(void)
700{
701 if (kzt_buffer)
702 free(kzt_buffer);
703
704 if (kztctl_fd != -1) {
705 if (close(kztctl_fd) == -1) {
706 fprintf(stderr, "Unable to close %s: %d\n",
707 KZT_DEV, errno);
708 }
709 }
710}
711
712static int
713dev_init(void)
714{
564f6d15 715 ListIterator i;
f1ca4da6 716 subsystem_t *sub;
717 int rc;
718
719 kztctl_fd = open(KZT_DEV, O_RDONLY);
720 if (kztctl_fd == -1) {
721 fprintf(stderr, "Unable to open %s: %d\n"
722 "Is the kzt module loaded?\n", KZT_DEV, errno);
723 rc = errno;
724 goto error;
725 }
726
727 /* Determine kernel module version string */
728 memset(kzt_version, 0, KZT_VERSION_SIZE);
729 if ((rc = read(kztctl_fd, kzt_version, KZT_VERSION_SIZE - 1)) == -1)
730 goto error;
731
564f6d15 732 if ((rc = dev_clear()))
f1ca4da6 733 goto error;
734
735 if ((rc = dev_size(0)) < 0)
736 goto error;
737
738 kzt_buffer_size = rc;
739 kzt_buffer = (char *)malloc(kzt_buffer_size);
740 if (kzt_buffer == NULL) {
741 rc = -ENOMEM;
742 goto error;
743 }
744
745 memset(kzt_buffer, 0, kzt_buffer_size);
746
747 /* Determine available subsystems */
748 if ((rc = subsystem_setup()) != 0)
749 goto error;
750
751 /* Determine available tests for all subsystems */
564f6d15 752 i = list_iterator_create(subsystems);
753
754 while ((sub = list_next(i))) {
755 if ((rc = test_setup(sub)) != 0) {
756 list_iterator_destroy(i);
f1ca4da6 757 goto error;
564f6d15 758 }
759 }
f1ca4da6 760
564f6d15 761 list_iterator_destroy(i);
f1ca4da6 762 return 0;
763
764error:
765 if (kztctl_fd != -1) {
766 if (close(kztctl_fd) == -1) {
767 fprintf(stderr, "Unable to close %s: %d\n",
768 KZT_DEV, errno);
769 }
770 }
771
772 return rc;
773}
774
775int
776init(void)
777{
564f6d15 778 int rc = 0;
f1ca4da6 779
780 /* Allocate the subsystem list */
564f6d15 781 subsystems = list_create((ListDelF)subsystem_fini);
782 if (subsystems == NULL)
783 rc = ENOMEM;
f1ca4da6 784
564f6d15 785 return rc;
f1ca4da6 786}
787
788void
789fini(void)
790{
564f6d15 791 list_destroy(subsystems);
f1ca4da6 792}
793
794
795int
796main(int argc, char **argv)
797{
798 cmd_args_t *args = NULL;
799 int rc = 0;
800
801 /* General init */
564f6d15 802 if ((rc = init()))
f1ca4da6 803 return rc;
804
805 /* Device specific init */
564f6d15 806 if ((rc = dev_init()))
f1ca4da6 807 goto out;
808
809 /* Argument init and parsing */
810 if ((args = args_init(argc, argv)) == NULL) {
811 rc = -1;
812 goto out;
813 }
814
815 /* Generic kernel version string */
816 if (args->args_verbose)
817 fprintf(stdout, "%s", kzt_version);
818
819 /* Print the available test list and exit */
820 if (args->args_do_list) {
821 subsystem_list(subsystems, 0);
822 goto out;
823 }
824
825 /* Add all available test to the list of tests to run */
826 if (args->args_do_all) {
564f6d15 827 if ((rc = test_add_all(args)))
f1ca4da6 828 goto out;
829 }
830
831 /* Run all the requested tests */
564f6d15 832 if ((rc = tests_run(args)))
f1ca4da6 833 goto out;
834
835out:
836 if (args != NULL)
837 args_fini(args);
838
839 dev_fini();
840 fini();
841 return rc;
842}
843