]>
git.proxmox.com Git - mirror_zfs.git/blob - src/cmd/splat.c
1 /* Kernel ZFS Test (KZT) user space command interface */
12 #include <sys/ioctl.h>
14 #include <sys/types.h>
20 static const char shortOpts
[] = "hvlat:xc";
21 static const struct option longOpts
[] = {
22 { "help", no_argument
, 0, 'h' },
23 { "verbose", no_argument
, 0, 'v' },
24 { "list", no_argument
, 0, 'l' },
25 { "all", no_argument
, 0, 'a' },
26 { "test", required_argument
, 0, 't' },
27 { "exit", no_argument
, 0, 'x' },
28 { "nocolor", no_argument
, 0, 'c' },
32 static uu_list_t
*subsystems
; /* Subsystem/tests */
33 static uu_list_pool_t
*subsystem_pool
; /* Subsystem pool */
34 static uu_list_pool_t
*test_pool
; /* Test pool */
35 static int kztctl_fd
; /* Control file descriptor */
36 static char kzt_version
[KZT_VERSION_SIZE
]; /* Kernel version string */
37 static char *kzt_buffer
= NULL
; /* Scratch space area */
38 static int kzt_buffer_size
= 0; /* Scratch space size */
41 static void test_list(uu_list_t
*, int);
42 static int dev_clear(void);
45 static int usage(void) {
46 fprintf(stderr
, "usage: kzt [hvla] [-t <subsystem:<tests>>]\n");
48 " --help -h This help\n"
49 " --verbose -v Increase verbosity\n"
50 " --list -l List all tests in all subsystems\n"
51 " --all -a Run all tests in all subsystems\n"
52 " --test -t <sub:test> Run 'test' in subsystem 'sub'\n"
53 " --exit -x Exit on first test error\n"
54 " --nocolor -c Do not colorize output\n");
57 " kzt -t kmem:all # Runs all kmem tests\n"
58 " kzt -t taskq:0x201 # Run taskq test 0x201\n");
63 static subsystem_t
*subsystem_init(kzt_user_t
*desc
)
67 sub
= (subsystem_t
*)malloc(sizeof(*sub
));
71 memcpy(&sub
->sub_desc
, desc
, sizeof(*desc
));
72 uu_list_node_init(sub
, &sub
->sub_node
, subsystem_pool
);
74 sub
->sub_tests
= uu_list_create(test_pool
, NULL
, 0);
75 if (sub
->sub_tests
== NULL
) {
83 static void subsystem_fini(subsystem_t
*sub
)
87 uu_list_node_fini(sub
, &sub
->sub_node
, subsystem_pool
);
91 static int subsystem_setup(void)
94 int i
, rc
, size
, cfg_size
;
98 /* Aquire the number of registered subsystems */
99 cfg_size
= sizeof(*cfg
);
100 cfg
= (kzt_cfg_t
*)malloc(cfg_size
);
104 memset(cfg
, 0, cfg_size
);
105 cfg
->cfg_magic
= KZT_CFG_MAGIC
;
106 cfg
->cfg_cmd
= KZT_CFG_SUBSYSTEM_COUNT
;
108 rc
= ioctl(kztctl_fd
, KZT_CFG
, cfg
);
110 fprintf(stderr
, "Ioctl() error %lu / %d: %d\n",
111 (unsigned long) KZT_CFG
, cfg
->cfg_cmd
, errno
);
119 /* Based on the newly aquired number of subsystems allocate enough
120 * memory to get the descriptive information for them all. */
121 cfg_size
= sizeof(*cfg
) + size
* sizeof(kzt_user_t
);
122 cfg
= (kzt_cfg_t
*)malloc(cfg_size
);
126 memset(cfg
, 0, cfg_size
);
127 cfg
->cfg_magic
= KZT_CFG_MAGIC
;
128 cfg
->cfg_cmd
= KZT_CFG_SUBSYSTEM_LIST
;
129 cfg
->cfg_data
.kzt_subsystems
.size
= size
;
131 rc
= ioctl(kztctl_fd
, KZT_CFG
, cfg
);
133 fprintf(stderr
, "Ioctl() error %lu / %d: %d\n",
134 (unsigned long) KZT_CFG
, cfg
->cfg_cmd
, errno
);
139 /* Add the new subsystems in to the global list */
141 for (i
= 0; i
< size
; i
++) {
142 desc
= &(cfg
->cfg_data
.kzt_subsystems
.descs
[i
]);
144 sub
= subsystem_init(desc
);
146 fprintf(stderr
, "Error initializing subsystem: %s\n",
152 uu_list_insert(subsystems
, sub
, 0);
159 static int subsystem_compare(const void *l_arg
, const void *r_arg
, void *private)
161 const subsystem_t
*l
= l_arg
;
162 const subsystem_t
*r
= r_arg
;
164 if (l
->sub_desc
.id
> r
->sub_desc
.id
)
167 if (l
->sub_desc
.id
< r
->sub_desc
.id
)
173 static void subsystem_list(uu_list_t
*list
, int indent
)
178 "------------------------------- "
179 "Available KZT Tests "
180 "-------------------------------\n");
182 for (sub
= uu_list_first(list
); sub
!= NULL
;
183 sub
= uu_list_next(list
, sub
)) {
184 fprintf(stdout
, "%*s0x%0*x %-*s ---- %s ----\n",
187 KZT_NAME_SIZE
+ 7, sub
->sub_desc
.name
,
189 test_list(sub
->sub_tests
, indent
+ 7);
193 static test_t
*test_init(subsystem_t
*sub
, kzt_user_t
*desc
)
197 test
= (test_t
*)malloc(sizeof(*test
));
201 test
->test_sub
= sub
;
202 memcpy(&test
->test_desc
, desc
, sizeof(*desc
));
203 uu_list_node_init(test
, &test
->test_node
, test_pool
);
208 static void test_fini(test_t
*test
)
210 assert(test
!= NULL
);
212 uu_list_node_fini(test
, &test
->test_node
, test_pool
);
216 static int test_setup(subsystem_t
*sub
)
223 /* Aquire the number of registered tests for the give subsystem */
224 cfg
= (kzt_cfg_t
*)malloc(sizeof(*cfg
));
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 */
233 rc
= ioctl(kztctl_fd
, KZT_CFG
, cfg
);
235 fprintf(stderr
, "Ioctl() error %lu / %d: %d\n",
236 (unsigned long) KZT_CFG
, cfg
->cfg_cmd
, errno
);
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
));
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
;
256 rc
= ioctl(kztctl_fd
, KZT_CFG
, cfg
);
258 fprintf(stderr
, "Ioctl() error %lu / %d: %d\n",
259 (unsigned long) KZT_CFG
, cfg
->cfg_cmd
, errno
);
264 /* Add the new tests in to the relevant subsystems */
266 for (i
= 0; i
< size
; i
++) {
267 desc
= &(cfg
->cfg_data
.kzt_tests
.descs
[i
]);
269 test
= test_init(sub
, desc
);
271 fprintf(stderr
, "Error initializing test: %s\n",
277 uu_list_insert(sub
->sub_tests
, test
, 0);
284 static int test_compare(const void *l_arg
, const void *r_arg
, void *private)
286 const test_t
*l
= l_arg
;
287 const test_t
*r
= r_arg
;
289 if (l
->test_desc
.id
> r
->test_desc
.id
)
292 if (l
->test_desc
.id
< r
->test_desc
.id
)
298 static test_t
*test_copy(test_t
*test
)
300 return test_init(test
->test_sub
, &test
->test_desc
);
303 static void test_list(uu_list_t
*list
, int indent
)
307 for (test
= uu_list_first(list
); test
!= NULL
;
308 test
= uu_list_next(list
, test
))
309 fprintf(stdout
, "%*s0x%0*x %-*s %-*s\n",
311 04, test
->test_desc
.id
,
312 KZT_NAME_SIZE
, test
->test_desc
.name
,
313 KZT_DESC_SIZE
, test
->test_desc
.desc
);
316 static test_t
*test_find(char *sub_str
, char *test_str
)
320 int sub_num
, test_num
;
322 /* No error checking here because it may not be a number, it's
323 * perfectly OK for it to be a string. Since we're just using
324 * it for comparison purposes this is all very safe.
326 sub_num
= strtol(sub_str
, NULL
, 0);
327 test_num
= strtol(test_str
, NULL
, 0);
329 for (sub
= uu_list_first(subsystems
); sub
!= NULL
;
330 sub
= uu_list_next(subsystems
, sub
)) {
332 if (strncmp(sub
->sub_desc
.name
, sub_str
, KZT_NAME_SIZE
) &&
333 sub
->sub_desc
.id
!= sub_num
)
336 for (test
= uu_list_first(sub
->sub_tests
); test
!= NULL
;
337 test
= uu_list_next(sub
->sub_tests
, test
)) {
339 if (!strncmp(test
->test_desc
.name
, test_str
,
340 KZT_NAME_SIZE
) || test
->test_desc
.id
== test_num
)
348 static int test_add(cmd_args_t
*args
, test_t
*test
)
352 tmp
= test_copy(test
);
356 uu_list_insert(args
->args_tests
, tmp
, 0);
360 static int test_add_all(cmd_args_t
*args
)
366 for (sub
= uu_list_first(subsystems
); sub
!= NULL
;
367 sub
= uu_list_next(subsystems
, sub
)) {
369 for (test
= uu_list_first(sub
->sub_tests
); test
!= NULL
;
370 test
= uu_list_next(sub
->sub_tests
, test
)) {
372 if (rc
= test_add(args
, test
))
380 static int test_run(cmd_args_t
*args
, test_t
*test
)
382 subsystem_t
*sub
= test
->test_sub
;
388 cmd_size
= sizeof(*cmd
);
389 cmd
= (kzt_cmd_t
*)malloc(cmd_size
);
393 memset(cmd
, 0, cmd_size
);
394 cmd
->cmd_magic
= KZT_CMD_MAGIC
;
395 cmd
->cmd_subsystem
= sub
->sub_desc
.id
;
396 cmd
->cmd_test
= test
->test_desc
.id
;
397 cmd
->cmd_data_size
= 0; /* Unused feature */
399 fprintf(stdout
, "%*s:%-*s ",
400 KZT_NAME_SIZE
, sub
->sub_desc
.name
,
401 KZT_NAME_SIZE
, test
->test_desc
.name
);
403 rc
= ioctl(kztctl_fd
, KZT_CMD
, cmd
);
404 if (args
->args_do_color
) {
405 fprintf(stdout
, "%s %s\n", rc
?
406 COLOR_RED
"Fail" COLOR_RESET
:
407 COLOR_GREEN
"Pass" COLOR_RESET
,
408 rc
? strerror(errno
) : "");
410 fprintf(stdout
, "%s %s\n", rc
?
412 rc
? strerror(errno
) : "");
417 if (args
->args_verbose
) {
418 if ((rc
= read(kztctl_fd
, kzt_buffer
, kzt_buffer_size
- 1)) < 0) {
419 fprintf(stdout
, "Error reading results: %d\n", rc
);
421 fprintf(stdout
, "\n%s\n", kzt_buffer
);
429 static int tests_run(cmd_args_t
*args
)
435 "------------------------------- "
437 "-------------------------------\n");
439 for (test
= uu_list_first(args
->args_tests
); test
!= NULL
;
440 test
= uu_list_next(args
->args_tests
, test
)) {
442 rc
= test_run(args
, test
);
443 if (rc
&& args
->args_exit_on_error
)
450 static int args_parse_test(cmd_args_t
*args
, char *str
)
454 char *sub_str
, *test_str
;
455 int sub_num
, test_num
;
456 int sub_all
= 0, test_all
= 0;
459 test_str
= strchr(str
, ':');
460 if (test_str
== NULL
) {
461 fprintf(stderr
, "Test must be of the "
462 "form <subsystem:test>\n");
468 test_str
= test_str
+ 1;
470 sub_num
= strtol(sub_str
, NULL
, 0);
471 test_num
= strtol(test_str
, NULL
, 0);
473 if (!strncasecmp(sub_str
, "all", strlen(sub_str
)) || (sub_num
== -1))
476 if (!strncasecmp(test_str
, "all", strlen(test_str
)) || (test_num
== -1))
481 /* Add all tests from all subsystems */
482 for (s
= uu_list_first(subsystems
); s
!= NULL
;
483 s
= uu_list_next(subsystems
, s
))
484 for (t
= uu_list_first(s
->sub_tests
);t
!= NULL
;
485 t
= uu_list_next(s
->sub_tests
, t
))
486 if (rc
= test_add(args
, t
))
489 /* Add a specific test from all subsystems */
490 for (s
= uu_list_first(subsystems
); s
!= NULL
;
491 s
= uu_list_next(subsystems
, s
)) {
492 if (t
= test_find(s
->sub_desc
.name
,test_str
)) {
493 if (rc
= test_add(args
, t
))
501 fprintf(stderr
, "No tests '%s:%s' could be "
502 "found\n", sub_str
, test_str
);
506 /* Add all tests from a specific subsystem */
507 for (s
= uu_list_first(subsystems
); s
!= NULL
;
508 s
= uu_list_next(subsystems
, s
)) {
509 if (strncasecmp(sub_str
, s
->sub_desc
.name
,
513 for (t
= uu_list_first(s
->sub_tests
);t
!= NULL
;
514 t
= uu_list_next(s
->sub_tests
, t
))
515 if (rc
= test_add(args
, t
))
519 /* Add a specific test from a specific subsystem */
520 if (t
= test_find(sub_str
, test_str
)) {
521 if (rc
= test_add(args
, t
))
524 fprintf(stderr
, "Test '%s:%s' could not be "
525 "found\n", sub_str
, test_str
);
534 fprintf(stderr
, "Test '%s:%s' not added to run list: %d\n",
535 sub_str
, test_str
, rc
);
539 static void args_fini(cmd_args_t
*args
)
541 struct cmd_test
*ptr1
, *ptr2
;
543 assert(args
!= NULL
);
547 if (args
->args_tests
!= NULL
) {
548 uu_list_destroy(args
->args_tests
);
555 args_init(int argc
, char **argv
)
562 return (cmd_args_t
*) NULL
;
565 /* Configure and populate the args structures */
566 args
= malloc(sizeof(*args
));
570 memset(args
, 0, sizeof(*args
));
571 args
->args_verbose
= 0;
572 args
->args_do_list
= 0;
573 args
->args_do_all
= 0;
574 args
->args_do_color
= 1;
575 args
->args_exit_on_error
= 0;
576 args
->args_tests
= uu_list_create(test_pool
, NULL
, 0);
577 if (args
->args_tests
== NULL
) {
582 while ((c
= getopt_long(argc
, argv
, shortOpts
, longOpts
, NULL
)) != -1){
584 case 'v': args
->args_verbose
++; break;
585 case 'l': args
->args_do_list
= 1; break;
586 case 'a': args
->args_do_all
= 1; break;
587 case 'c': args
->args_do_color
= 0; break;
588 case 'x': args
->args_exit_on_error
= 1; break;
590 if (args
->args_do_all
) {
591 fprintf(stderr
, "Option -t <subsystem:test> is "
592 "useless when used with -a\n");
597 rc
= args_parse_test(args
, argv
[optind
- 1]);
609 fprintf(stderr
, "Unknown option '%s'\n",
624 memset(&cfg
, 0, sizeof(cfg
));
625 cfg
.cfg_magic
= KZT_CFG_MAGIC
;
626 cfg
.cfg_cmd
= KZT_CFG_BUFFER_CLEAR
;
629 rc
= ioctl(kztctl_fd
, KZT_CFG
, &cfg
);
631 fprintf(stderr
, "Ioctl() error %lu / %d: %d\n",
632 (unsigned long) KZT_CFG
, cfg
.cfg_cmd
, errno
);
634 lseek(kztctl_fd
, 0, SEEK_SET
);
645 memset(&cfg
, 0, sizeof(cfg
));
646 cfg
.cfg_magic
= KZT_CFG_MAGIC
;
647 cfg
.cfg_cmd
= KZT_CFG_BUFFER_SIZE
;
650 rc
= ioctl(kztctl_fd
, KZT_CFG
, &cfg
);
652 fprintf(stderr
, "Ioctl() error %lu / %d: %d\n",
653 (unsigned long) KZT_CFG
, cfg
.cfg_cmd
, errno
);
666 if (kztctl_fd
!= -1) {
667 if (close(kztctl_fd
) == -1) {
668 fprintf(stderr
, "Unable to close %s: %d\n",
680 kztctl_fd
= open(KZT_DEV
, O_RDONLY
);
681 if (kztctl_fd
== -1) {
682 fprintf(stderr
, "Unable to open %s: %d\n"
683 "Is the kzt module loaded?\n", KZT_DEV
, errno
);
688 /* Determine kernel module version string */
689 memset(kzt_version
, 0, KZT_VERSION_SIZE
);
690 if ((rc
= read(kztctl_fd
, kzt_version
, KZT_VERSION_SIZE
- 1)) == -1)
693 if (rc
= dev_clear())
696 if ((rc
= dev_size(0)) < 0)
699 kzt_buffer_size
= rc
;
700 kzt_buffer
= (char *)malloc(kzt_buffer_size
);
701 if (kzt_buffer
== NULL
) {
706 memset(kzt_buffer
, 0, kzt_buffer_size
);
708 /* Determine available subsystems */
709 if ((rc
= subsystem_setup()) != 0)
712 /* Determine available tests for all subsystems */
713 for (sub
= uu_list_first(subsystems
); sub
!= NULL
;
714 sub
= uu_list_next(subsystems
, sub
))
715 if ((rc
= test_setup(sub
)) != 0)
721 if (kztctl_fd
!= -1) {
722 if (close(kztctl_fd
) == -1) {
723 fprintf(stderr
, "Unable to close %s: %d\n",
736 /* Configure the subsystem pool */
737 subsystem_pool
= uu_list_pool_create("sub_pool", sizeof(subsystem_t
),
738 offsetof(subsystem_t
, sub_node
),
739 subsystem_compare
, 0);
740 if (subsystem_pool
== NULL
)
743 /* Configure the test pool */
744 test_pool
= uu_list_pool_create("test_pool", sizeof(test_t
),
745 offsetof(test_t
, test_node
),
747 if (test_pool
== NULL
) {
748 uu_list_pool_destroy(subsystem_pool
);
752 /* Allocate the subsystem list */
753 subsystems
= uu_list_create(subsystem_pool
, NULL
, 0);
754 if (subsystems
== NULL
) {
755 uu_list_pool_destroy(test_pool
);
756 uu_list_pool_destroy(subsystem_pool
);
766 /* XXX - Cleanup destroy lists release memory */
768 /* XXX - Remove contents of list first */
769 uu_list_destroy(subsystems
);
774 main(int argc
, char **argv
)
776 cmd_args_t
*args
= NULL
;
783 /* Device specific init */
787 /* Argument init and parsing */
788 if ((args
= args_init(argc
, argv
)) == NULL
) {
793 /* Generic kernel version string */
794 if (args
->args_verbose
)
795 fprintf(stdout
, "%s", kzt_version
);
797 /* Print the available test list and exit */
798 if (args
->args_do_list
) {
799 subsystem_list(subsystems
, 0);
803 /* Add all available test to the list of tests to run */
804 if (args
->args_do_all
) {
805 if (rc
= test_add_all(args
))
809 /* Run all the requested tests */
810 if (rc
= tests_run(args
))