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://github.com/behlendorf/spl/>.
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) Test Control Interface.
26 * The 'splat' (Solaris Porting LAyer Tests) module is designed as a
27 * framework which runs various in kernel regression tests to validate
28 * the SPL primitives honor the Solaris ABI.
30 * The splat module is constructed of various splat_* source files each
31 * of which contain regression tests for a particular subsystem. For
32 * example, the splat_kmem.c file contains all the tests for validating
33 * the kmem interfaces have been implemented correctly. When the splat
34 * module is loaded splat_*_init() will be called for each subsystems
35 * tests. It is the responsibility of splat_*_init() to register all
36 * the tests for this subsystem using the SPLAT_TEST_INIT() macro.
37 * Similarly splat_*_fini() is called when the splat module is removed
38 * and is responsible for unregistering its tests via the SPLAT_TEST_FINI
39 * macro. Once a test is registered it can then be run with an ioctl()
40 * call which specifies the subsystem and test to be run. The provided
41 * splat command line tool can be used to display all available
42 * subsystems and tests. It can also be used to run the full suite
43 * of regression tests or particular tests.
44 \*****************************************************************************/
46 #include <linux/module.h>
47 #include <linux/slab.h>
48 #include <linux/vmalloc.h>
49 #include <linux/cdev.h>
51 #include <linux/uaccess.h>
52 #include <sys/types.h>
53 #include <sys/debug.h>
54 #include "splat-internal.h"
56 static spl_class
*splat_class
;
57 static spl_device
*splat_device
;
58 static struct list_head splat_module_list
;
59 static spinlock_t splat_module_lock
;
62 splat_open(struct inode
*inode
, struct file
*file
)
64 unsigned int minor
= iminor(inode
);
67 if (minor
>= SPLAT_MINORS
)
70 info
= (splat_info_t
*)kmalloc(sizeof(*info
), GFP_KERNEL
);
74 mutex_init(&info
->info_lock
);
75 info
->info_size
= SPLAT_INFO_BUFFER_SIZE
;
76 info
->info_buffer
= (char *)vmalloc(SPLAT_INFO_BUFFER_SIZE
);
77 if (info
->info_buffer
== NULL
) {
81 memset(info
->info_buffer
, 0, info
->info_size
);
83 info
->info_head
= info
->info_buffer
;
84 file
->private_data
= (void *)info
;
86 splat_print(file
, "%s\n", spl_version
);
92 splat_release(struct inode
*inode
, struct file
*file
)
94 unsigned int minor
= iminor(inode
);
95 splat_info_t
*info
= (splat_info_t
*)file
->private_data
;
97 if (minor
>= SPLAT_MINORS
)
101 ASSERT(info
->info_buffer
);
103 mutex_destroy(&info
->info_lock
);
104 vfree(info
->info_buffer
);
111 splat_buffer_clear(struct file
*file
, splat_cfg_t
*kcfg
, unsigned long arg
)
113 splat_info_t
*info
= (splat_info_t
*)file
->private_data
;
116 ASSERT(info
->info_buffer
);
118 mutex_lock(&info
->info_lock
);
119 memset(info
->info_buffer
, 0, info
->info_size
);
120 info
->info_head
= info
->info_buffer
;
121 mutex_unlock(&info
->info_lock
);
127 splat_buffer_size(struct file
*file
, splat_cfg_t
*kcfg
, unsigned long arg
)
129 splat_info_t
*info
= (splat_info_t
*)file
->private_data
;
131 int min
, size
, rc
= 0;
134 ASSERT(info
->info_buffer
);
136 mutex_lock(&info
->info_lock
);
137 if (kcfg
->cfg_arg1
> 0) {
139 size
= kcfg
->cfg_arg1
;
140 buf
= (char *)vmalloc(size
);
146 /* Zero fill and truncate contents when coping buffer */
147 min
= ((size
< info
->info_size
) ? size
: info
->info_size
);
148 memset(buf
, 0, size
);
149 memcpy(buf
, info
->info_buffer
, min
);
150 vfree(info
->info_buffer
);
151 info
->info_size
= size
;
152 info
->info_buffer
= buf
;
153 info
->info_head
= info
->info_buffer
;
156 kcfg
->cfg_rc1
= info
->info_size
;
158 if (copy_to_user((struct splat_cfg_t __user
*)arg
, kcfg
, sizeof(*kcfg
)))
161 mutex_unlock(&info
->info_lock
);
167 static splat_subsystem_t
*
168 splat_subsystem_find(int id
) {
169 splat_subsystem_t
*sub
;
171 spin_lock(&splat_module_lock
);
172 list_for_each_entry(sub
, &splat_module_list
, subsystem_list
) {
173 if (id
== sub
->desc
.id
) {
174 spin_unlock(&splat_module_lock
);
178 spin_unlock(&splat_module_lock
);
184 splat_subsystem_count(splat_cfg_t
*kcfg
, unsigned long arg
)
186 splat_subsystem_t
*sub
;
189 spin_lock(&splat_module_lock
);
190 list_for_each_entry(sub
, &splat_module_list
, subsystem_list
)
193 spin_unlock(&splat_module_lock
);
196 if (copy_to_user((struct splat_cfg_t __user
*)arg
, kcfg
, sizeof(*kcfg
)))
203 splat_subsystem_list(splat_cfg_t
*kcfg
, unsigned long arg
)
205 splat_subsystem_t
*sub
;
209 /* Structure will be sized large enough for N subsystem entries
210 * which is passed in by the caller. On exit the number of
211 * entries filled in with valid subsystems will be stored in
212 * cfg_rc1. If the caller does not provide enough entries
213 * for all subsystems we will truncate the list to avoid overrun.
215 size
= sizeof(*tmp
) + kcfg
->cfg_data
.splat_subsystems
.size
*
216 sizeof(splat_user_t
);
217 tmp
= kmalloc(size
, GFP_KERNEL
);
221 /* Local 'tmp' is used as the structure copied back to user space */
222 memset(tmp
, 0, size
);
223 memcpy(tmp
, kcfg
, sizeof(*kcfg
));
225 spin_lock(&splat_module_lock
);
226 list_for_each_entry(sub
, &splat_module_list
, subsystem_list
) {
227 strncpy(tmp
->cfg_data
.splat_subsystems
.descs
[i
].name
,
228 sub
->desc
.name
, SPLAT_NAME_SIZE
);
229 strncpy(tmp
->cfg_data
.splat_subsystems
.descs
[i
].desc
,
230 sub
->desc
.desc
, SPLAT_DESC_SIZE
);
231 tmp
->cfg_data
.splat_subsystems
.descs
[i
].id
= sub
->desc
.id
;
233 /* Truncate list if we are about to overrun alloc'ed memory */
234 if ((i
++) == kcfg
->cfg_data
.splat_subsystems
.size
)
237 spin_unlock(&splat_module_lock
);
240 if (copy_to_user((struct splat_cfg_t __user
*)arg
, tmp
, size
)) {
250 splat_test_count(splat_cfg_t
*kcfg
, unsigned long arg
)
252 splat_subsystem_t
*sub
;
256 /* Subsystem ID passed as arg1 */
257 sub
= splat_subsystem_find(kcfg
->cfg_arg1
);
261 spin_lock(&(sub
->test_lock
));
262 list_for_each_entry(test
, &(sub
->test_list
), test_list
)
265 spin_unlock(&(sub
->test_lock
));
268 if (copy_to_user((struct splat_cfg_t __user
*)arg
, kcfg
, sizeof(*kcfg
)))
275 splat_test_list(splat_cfg_t
*kcfg
, unsigned long arg
)
277 splat_subsystem_t
*sub
;
282 /* Subsystem ID passed as arg1 */
283 sub
= splat_subsystem_find(kcfg
->cfg_arg1
);
287 /* Structure will be sized large enough for N test entries
288 * which is passed in by the caller. On exit the number of
289 * entries filled in with valid tests will be stored in
290 * cfg_rc1. If the caller does not provide enough entries
291 * for all tests we will truncate the list to avoid overrun.
293 size
= sizeof(*tmp
)+kcfg
->cfg_data
.splat_tests
.size
*sizeof(splat_user_t
);
294 tmp
= kmalloc(size
, GFP_KERNEL
);
298 /* Local 'tmp' is used as the structure copied back to user space */
299 memset(tmp
, 0, size
);
300 memcpy(tmp
, kcfg
, sizeof(*kcfg
));
302 spin_lock(&(sub
->test_lock
));
303 list_for_each_entry(test
, &(sub
->test_list
), test_list
) {
304 strncpy(tmp
->cfg_data
.splat_tests
.descs
[i
].name
,
305 test
->desc
.name
, SPLAT_NAME_SIZE
);
306 strncpy(tmp
->cfg_data
.splat_tests
.descs
[i
].desc
,
307 test
->desc
.desc
, SPLAT_DESC_SIZE
);
308 tmp
->cfg_data
.splat_tests
.descs
[i
].id
= test
->desc
.id
;
310 /* Truncate list if we are about to overrun alloc'ed memory */
311 if ((i
++) == kcfg
->cfg_data
.splat_tests
.size
)
314 spin_unlock(&(sub
->test_lock
));
317 if (copy_to_user((struct splat_cfg_t __user
*)arg
, tmp
, size
)) {
327 splat_validate(struct file
*file
, splat_subsystem_t
*sub
, int cmd
, void *arg
)
331 spin_lock(&(sub
->test_lock
));
332 list_for_each_entry(test
, &(sub
->test_list
), test_list
) {
333 if (test
->desc
.id
== cmd
) {
334 spin_unlock(&(sub
->test_lock
));
335 return test
->test(file
, arg
);
338 spin_unlock(&(sub
->test_lock
));
344 splat_ioctl_cfg(struct file
*file
, unsigned int cmd
, unsigned long arg
)
349 /* User and kernel space agree about arg size */
350 if (_IOC_SIZE(cmd
) != sizeof(kcfg
))
353 if (copy_from_user(&kcfg
, (splat_cfg_t
*)arg
, sizeof(kcfg
)))
356 if (kcfg
.cfg_magic
!= SPLAT_CFG_MAGIC
) {
357 splat_print(file
, "Bad config magic 0x%x != 0x%x\n",
358 kcfg
.cfg_magic
, SPLAT_CFG_MAGIC
);
362 switch (kcfg
.cfg_cmd
) {
363 case SPLAT_CFG_BUFFER_CLEAR
:
367 rc
= splat_buffer_clear(file
, &kcfg
, arg
);
369 case SPLAT_CFG_BUFFER_SIZE
:
370 /* cfg_arg1 - 0 - query size; >0 resize
371 * cfg_rc1 - Set to current buffer size
373 rc
= splat_buffer_size(file
, &kcfg
, arg
);
375 case SPLAT_CFG_SUBSYSTEM_COUNT
:
377 * cfg_rc1 - Set to number of subsystems
379 rc
= splat_subsystem_count(&kcfg
, arg
);
381 case SPLAT_CFG_SUBSYSTEM_LIST
:
383 * cfg_rc1 - Set to number of subsystems
384 * cfg_data.splat_subsystems - Set with subsystems
386 rc
= splat_subsystem_list(&kcfg
, arg
);
388 case SPLAT_CFG_TEST_COUNT
:
389 /* cfg_arg1 - Set to a target subsystem
390 * cfg_rc1 - Set to number of tests
392 rc
= splat_test_count(&kcfg
, arg
);
394 case SPLAT_CFG_TEST_LIST
:
395 /* cfg_arg1 - Set to a target subsystem
396 * cfg_rc1 - Set to number of tests
397 * cfg_data.splat_subsystems - Populated with tests
399 rc
= splat_test_list(&kcfg
, arg
);
402 splat_print(file
, "Bad config command %d\n",
412 splat_ioctl_cmd(struct file
*file
, unsigned int cmd
, unsigned long arg
)
414 splat_subsystem_t
*sub
;
419 /* User and kernel space agree about arg size */
420 if (_IOC_SIZE(cmd
) != sizeof(kcmd
))
423 if (copy_from_user(&kcmd
, (splat_cfg_t
*)arg
, sizeof(kcmd
)))
426 if (kcmd
.cmd_magic
!= SPLAT_CMD_MAGIC
) {
427 splat_print(file
, "Bad command magic 0x%x != 0x%x\n",
428 kcmd
.cmd_magic
, SPLAT_CFG_MAGIC
);
432 /* Allocate memory for any opaque data the caller needed to pass on */
433 if (kcmd
.cmd_data_size
> 0) {
434 data
= (void *)kmalloc(kcmd
.cmd_data_size
, GFP_KERNEL
);
438 if (copy_from_user(data
, (void *)(arg
+ offsetof(splat_cmd_t
,
439 cmd_data_str
)), kcmd
.cmd_data_size
)) {
445 sub
= splat_subsystem_find(kcmd
.cmd_subsystem
);
447 rc
= splat_validate(file
, sub
, kcmd
.cmd_test
, data
);
458 splat_unlocked_ioctl(struct file
*file
, unsigned int cmd
, unsigned long arg
)
460 unsigned int minor
= iminor(file
->f_dentry
->d_inode
);
463 /* Ignore tty ioctls */
464 if ((cmd
& 0xffffff00) == ((int)'T') << 8)
467 if (minor
>= SPLAT_MINORS
)
472 rc
= splat_ioctl_cfg(file
, cmd
, arg
);
475 rc
= splat_ioctl_cmd(file
, cmd
, arg
);
478 splat_print(file
, "Bad ioctl command %d\n", cmd
);
487 /* Compatibility handler for ioctls from 32-bit ELF binaries */
489 splat_compat_ioctl(struct file
*file
, unsigned int cmd
, unsigned long arg
)
491 return splat_unlocked_ioctl(file
, cmd
, arg
);
493 #endif /* CONFIG_COMPAT */
495 /* I'm not sure why you would want to write in to this buffer from
496 * user space since its principle use is to pass test status info
497 * back to the user space, but I don't see any reason to prevent it.
499 static ssize_t
splat_write(struct file
*file
, const char __user
*buf
,
500 size_t count
, loff_t
*ppos
)
502 unsigned int minor
= iminor(file
->f_dentry
->d_inode
);
503 splat_info_t
*info
= (splat_info_t
*)file
->private_data
;
506 if (minor
>= SPLAT_MINORS
)
510 ASSERT(info
->info_buffer
);
512 mutex_lock(&info
->info_lock
);
514 /* Write beyond EOF */
515 if (*ppos
>= info
->info_size
) {
520 /* Resize count if beyond EOF */
521 if (*ppos
+ count
> info
->info_size
)
522 count
= info
->info_size
- *ppos
;
524 if (copy_from_user(info
->info_buffer
, buf
, count
)) {
532 mutex_unlock(&info
->info_lock
);
536 static ssize_t
splat_read(struct file
*file
, char __user
*buf
,
537 size_t count
, loff_t
*ppos
)
539 unsigned int minor
= iminor(file
->f_dentry
->d_inode
);
540 splat_info_t
*info
= (splat_info_t
*)file
->private_data
;
543 if (minor
>= SPLAT_MINORS
)
547 ASSERT(info
->info_buffer
);
549 mutex_lock(&info
->info_lock
);
551 /* Read beyond EOF */
552 if (*ppos
>= info
->info_size
)
555 /* Resize count if beyond EOF */
556 if (*ppos
+ count
> info
->info_size
)
557 count
= info
->info_size
- *ppos
;
559 if (copy_to_user(buf
, info
->info_buffer
+ *ppos
, count
)) {
567 mutex_unlock(&info
->info_lock
);
571 static loff_t
splat_seek(struct file
*file
, loff_t offset
, int origin
)
573 unsigned int minor
= iminor(file
->f_dentry
->d_inode
);
574 splat_info_t
*info
= (splat_info_t
*)file
->private_data
;
577 if (minor
>= SPLAT_MINORS
)
581 ASSERT(info
->info_buffer
);
583 mutex_lock(&info
->info_lock
);
586 case 0: /* SEEK_SET - No-op just do it */
588 case 1: /* SEEK_CUR - Seek from current */
589 offset
= file
->f_pos
+ offset
;
591 case 2: /* SEEK_END - Seek from end */
592 offset
= info
->info_size
+ offset
;
597 file
->f_pos
= offset
;
602 mutex_unlock(&info
->info_lock
);
607 static struct cdev splat_cdev
;
608 static struct file_operations splat_fops
= {
609 .owner
= THIS_MODULE
,
611 .release
= splat_release
,
612 .unlocked_ioctl
= splat_unlocked_ioctl
,
614 .compat_ioctl
= splat_compat_ioctl
,
617 .write
= splat_write
,
618 .llseek
= splat_seek
,
627 spin_lock_init(&splat_module_lock
);
628 INIT_LIST_HEAD(&splat_module_list
);
630 SPLAT_SUBSYSTEM_INIT(kmem
);
631 SPLAT_SUBSYSTEM_INIT(taskq
);
632 SPLAT_SUBSYSTEM_INIT(krng
);
633 SPLAT_SUBSYSTEM_INIT(mutex
);
634 SPLAT_SUBSYSTEM_INIT(condvar
);
635 SPLAT_SUBSYSTEM_INIT(thread
);
636 SPLAT_SUBSYSTEM_INIT(rwlock
);
637 SPLAT_SUBSYSTEM_INIT(time
);
638 SPLAT_SUBSYSTEM_INIT(vnode
);
639 SPLAT_SUBSYSTEM_INIT(kobj
);
640 SPLAT_SUBSYSTEM_INIT(atomic
);
641 SPLAT_SUBSYSTEM_INIT(list
);
642 SPLAT_SUBSYSTEM_INIT(generic
);
643 SPLAT_SUBSYSTEM_INIT(cred
);
644 SPLAT_SUBSYSTEM_INIT(zlib
);
645 SPLAT_SUBSYSTEM_INIT(linux
);
647 dev
= MKDEV(SPLAT_MAJOR
, 0);
648 if ((rc
= register_chrdev_region(dev
, SPLAT_MINORS
, SPLAT_NAME
)))
651 /* Support for registering a character driver */
652 cdev_init(&splat_cdev
, &splat_fops
);
653 splat_cdev
.owner
= THIS_MODULE
;
654 kobject_set_name(&splat_cdev
.kobj
, SPLAT_NAME
);
655 if ((rc
= cdev_add(&splat_cdev
, dev
, SPLAT_MINORS
))) {
656 printk(KERN_ERR
"SPLAT: Error adding cdev, %d\n", rc
);
657 kobject_put(&splat_cdev
.kobj
);
658 unregister_chrdev_region(dev
, SPLAT_MINORS
);
662 /* Support for udev make driver info available in sysfs */
663 splat_class
= spl_class_create(THIS_MODULE
, "splat");
664 if (IS_ERR(splat_class
)) {
665 rc
= PTR_ERR(splat_class
);
666 printk(KERN_ERR
"SPLAT: Error creating splat class, %d\n", rc
);
667 cdev_del(&splat_cdev
);
668 unregister_chrdev_region(dev
, SPLAT_MINORS
);
672 splat_device
= spl_device_create(splat_class
, NULL
,
673 MKDEV(SPLAT_MAJOR
, 0),
676 printk(KERN_INFO
"SPLAT: Loaded module v%s-%s%s\n",
677 SPL_META_VERSION
, SPL_META_RELEASE
, SPL_DEBUG_STR
);
680 printk(KERN_ERR
"SPLAT: Error registering splat device, %d\n", rc
);
687 dev_t dev
= MKDEV(SPLAT_MAJOR
, 0);
689 spl_device_destroy(splat_class
, splat_device
, dev
);
690 spl_class_destroy(splat_class
);
691 cdev_del(&splat_cdev
);
692 unregister_chrdev_region(dev
, SPLAT_MINORS
);
694 SPLAT_SUBSYSTEM_FINI(linux
);
695 SPLAT_SUBSYSTEM_FINI(zlib
);
696 SPLAT_SUBSYSTEM_FINI(cred
);
697 SPLAT_SUBSYSTEM_FINI(generic
);
698 SPLAT_SUBSYSTEM_FINI(list
);
699 SPLAT_SUBSYSTEM_FINI(atomic
);
700 SPLAT_SUBSYSTEM_FINI(kobj
);
701 SPLAT_SUBSYSTEM_FINI(vnode
);
702 SPLAT_SUBSYSTEM_FINI(time
);
703 SPLAT_SUBSYSTEM_FINI(rwlock
);
704 SPLAT_SUBSYSTEM_FINI(thread
);
705 SPLAT_SUBSYSTEM_FINI(condvar
);
706 SPLAT_SUBSYSTEM_FINI(mutex
);
707 SPLAT_SUBSYSTEM_FINI(krng
);
708 SPLAT_SUBSYSTEM_FINI(taskq
);
709 SPLAT_SUBSYSTEM_FINI(kmem
);
711 ASSERT(list_empty(&splat_module_list
));
712 printk(KERN_INFO
"SPLAT: Unloaded module v%s-%s%s\n",
713 SPL_META_VERSION
, SPL_META_RELEASE
, SPL_DEBUG_STR
);
718 spl_module_init(splat_init
);
719 spl_module_exit(splat_fini
);
721 MODULE_AUTHOR("Lawrence Livermore National Labs");
722 MODULE_DESCRIPTION("Solaris Porting LAyer Tests");
723 MODULE_LICENSE("GPL");