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