]> git.proxmox.com Git - mirror_spl-debian.git/blobdiff - module/splat/splat-ctl.c
New upstream version 0.7.2
[mirror_spl-debian.git] / module / splat / splat-ctl.c
index 53bf51dd629c57af9db66896a81436753d1ae833..8452f1363904e9a6b661ae922a7fe6e3a3e3dec0 100644 (file)
@@ -6,7 +6,7 @@
  *  UCRL-CODE-235197
  *
  *  This file is part of the SPL, Solaris Porting Layer.
- *  For details, see <http://github.com/behlendorf/spl/>.
+ *  For details, see <http://zfsonlinux.org/>.
  *
  *  The SPL is free software; you can redistribute it and/or modify it
  *  under the terms of the GNU General Public License as published by the
  *  the kmem interfaces have been implemented correctly.  When the splat
  *  module is loaded splat_*_init() will be called for each subsystems
  *  tests.  It is the responsibility of splat_*_init() to register all
- *  the tests for this subsystem using the SPLAT_TEST_INIT() macro.
+ *  the tests for this subsystem using the splat_test_init().
  *  Similarly splat_*_fini() is called when the splat module is removed
- *  and is responsible for unregistering its tests via the SPLAT_TEST_FINI
- *  macro.  Once a test is registered it can then be run with an ioctl()
+ *  and is responsible for unregistering its tests via the splat_test_fini.
+ *  Once a test is registered it can then be run with an ioctl()
  *  call which specifies the subsystem and test to be run.  The provided
  *  splat command line tool can be used to display all available
  *  subsystems and tests.  It can also be used to run the full suite
  *  of regression tests or particular tests.
 \*****************************************************************************/
 
-#include <linux/module.h>
-#include <linux/slab.h>
-#include <linux/vmalloc.h>
+#include <sys/debug.h>
+#include <sys/mutex.h>
+#include <sys/types.h>
 #include <linux/cdev.h>
 #include <linux/fs.h>
+#include <linux/miscdevice.h>
+#include <linux/module.h>
+#include <linux/slab.h>
 #include <linux/uaccess.h>
-#include <sys/types.h>
-#include <sys/debug.h>
+#include <linux/vmalloc.h>
 #include "splat-internal.h"
 
-static spl_class *splat_class;
-static spl_device *splat_device;
 static struct list_head splat_module_list;
 static spinlock_t splat_module_lock;
 
 static int
 splat_open(struct inode *inode, struct file *file)
 {
-       unsigned int minor = iminor(inode);
        splat_info_t *info;
 
-       if (minor >= SPLAT_MINORS)
-               return -ENXIO;
-
        info = (splat_info_t *)kmalloc(sizeof(*info), GFP_KERNEL);
        if (info == NULL)
                return -ENOMEM;
 
-       spin_lock_init(&info->info_lock);
+       mutex_init(&info->info_lock, SPLAT_NAME, MUTEX_DEFAULT, NULL);
        info->info_size = SPLAT_INFO_BUFFER_SIZE;
        info->info_buffer = (char *)vmalloc(SPLAT_INFO_BUFFER_SIZE);
        if (info->info_buffer == NULL) {
@@ -91,15 +87,12 @@ splat_open(struct inode *inode, struct file *file)
 static int
 splat_release(struct inode *inode, struct file *file)
 {
-       unsigned int minor = iminor(inode);
        splat_info_t *info = (splat_info_t *)file->private_data;
 
-       if (minor >= SPLAT_MINORS)
-               return -ENXIO;
-
        ASSERT(info);
        ASSERT(info->info_buffer);
 
+       mutex_destroy(&info->info_lock);
        vfree(info->info_buffer);
        kfree(info);
 
@@ -114,10 +107,10 @@ splat_buffer_clear(struct file *file, splat_cfg_t *kcfg, unsigned long arg)
        ASSERT(info);
        ASSERT(info->info_buffer);
 
-       spin_lock(&info->info_lock);
+       mutex_enter(&info->info_lock);
        memset(info->info_buffer, 0, info->info_size);
        info->info_head = info->info_buffer;
-       spin_unlock(&info->info_lock);
+       mutex_exit(&info->info_lock);
 
        return 0;
 }
@@ -132,7 +125,7 @@ splat_buffer_size(struct file *file, splat_cfg_t *kcfg, unsigned long arg)
        ASSERT(info);
        ASSERT(info->info_buffer);
 
-       spin_lock(&info->info_lock);
+       mutex_enter(&info->info_lock);
        if (kcfg->cfg_arg1 > 0) {
 
                size = kcfg->cfg_arg1;
@@ -157,7 +150,7 @@ splat_buffer_size(struct file *file, splat_cfg_t *kcfg, unsigned long arg)
        if (copy_to_user((struct splat_cfg_t __user *)arg, kcfg, sizeof(*kcfg)))
                rc = -EFAULT;
 out:
-       spin_unlock(&info->info_lock);
+       mutex_exit(&info->info_lock);
 
        return rc;
 }
@@ -456,16 +449,12 @@ splat_ioctl_cmd(struct file *file, unsigned int cmd, unsigned long arg)
 static long
 splat_unlocked_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
-        unsigned int minor = iminor(file->f_dentry->d_inode);
        int rc = 0;
 
        /* Ignore tty ioctls */
        if ((cmd & 0xffffff00) == ((int)'T') << 8)
                return -ENOTTY;
 
-       if (minor >= SPLAT_MINORS)
-               return -ENXIO;
-
        switch (cmd) {
                case SPLAT_CFG:
                        rc = splat_ioctl_cfg(file, cmd, arg);
@@ -498,17 +487,13 @@ splat_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 static ssize_t splat_write(struct file *file, const char __user *buf,
                          size_t count, loff_t *ppos)
 {
-        unsigned int minor = iminor(file->f_dentry->d_inode);
        splat_info_t *info = (splat_info_t *)file->private_data;
        int rc = 0;
 
-       if (minor >= SPLAT_MINORS)
-               return -ENXIO;
-
        ASSERT(info);
        ASSERT(info->info_buffer);
 
-       spin_lock(&info->info_lock);
+       mutex_enter(&info->info_lock);
 
        /* Write beyond EOF */
        if (*ppos >= info->info_size) {
@@ -528,24 +513,20 @@ static ssize_t splat_write(struct file *file, const char __user *buf,
        *ppos += count;
        rc = count;
 out:
-       spin_unlock(&info->info_lock);
+       mutex_exit(&info->info_lock);
        return rc;
 }
 
 static ssize_t splat_read(struct file *file, char __user *buf,
                        size_t count, loff_t *ppos)
 {
-        unsigned int minor = iminor(file->f_dentry->d_inode);
        splat_info_t *info = (splat_info_t *)file->private_data;
        int rc = 0;
 
-       if (minor >= SPLAT_MINORS)
-               return -ENXIO;
-
        ASSERT(info);
        ASSERT(info->info_buffer);
 
-       spin_lock(&info->info_lock);
+       mutex_enter(&info->info_lock);
 
        /* Read beyond EOF */
        if (*ppos >= info->info_size)
@@ -563,23 +544,19 @@ static ssize_t splat_read(struct file *file, char __user *buf,
        *ppos += count;
        rc = count;
 out:
-       spin_unlock(&info->info_lock);
+       mutex_exit(&info->info_lock);
        return rc;
 }
 
 static loff_t splat_seek(struct file *file, loff_t offset, int origin)
 {
-        unsigned int minor = iminor(file->f_dentry->d_inode);
        splat_info_t *info = (splat_info_t *)file->private_data;
        int rc = -EINVAL;
 
-       if (minor >= SPLAT_MINORS)
-               return -ENXIO;
-
        ASSERT(info);
        ASSERT(info->info_buffer);
 
-       spin_lock(&info->info_lock);
+       mutex_enter(&info->info_lock);
 
        switch (origin) {
        case 0: /* SEEK_SET - No-op just do it */
@@ -598,12 +575,11 @@ static loff_t splat_seek(struct file *file, loff_t offset, int origin)
                rc = offset;
        }
 
-       spin_unlock(&info->info_lock);
+       mutex_exit(&info->info_lock);
 
        return rc;
 }
 
-static struct cdev splat_cdev;
 static struct file_operations splat_fops = {
        .owner          = THIS_MODULE,
        .open           = splat_open,
@@ -617,11 +593,98 @@ static struct file_operations splat_fops = {
        .llseek         = splat_seek,
 };
 
-static int
+static struct miscdevice splat_misc = {
+       .minor          = MISC_DYNAMIC_MINOR,
+       .name           = SPLAT_NAME,
+       .fops           = &splat_fops,
+};
+
+static void splat_subsystem_init(const char *name,
+    splat_subsystem_t *(*init)(void))
+{
+       splat_subsystem_t *sub;
+       sub = init();
+       if (sub == NULL) {
+               printk(KERN_ERR "splat: Error initializing: %s\n", name);
+               return;
+       }
+       spin_lock(&splat_module_lock);
+       list_add_tail(&sub->subsystem_list, &splat_module_list);
+       spin_unlock(&splat_module_lock);
+}
+
+static void splat_subsystem_fini(const char *name,
+    int (*id_func)(void), void (*fini)(splat_subsystem_t *))
+{
+       splat_subsystem_t *sub, *tmp;
+       int id, flag = 0;
+
+       id = id_func();
+       spin_lock(&splat_module_lock);
+       list_for_each_entry_safe(sub, tmp, &splat_module_list, subsystem_list) {
+               if (sub->desc.id == id) {
+                       list_del_init(&sub->subsystem_list);
+                       flag = 1;
+                       break;
+               }
+       }
+       spin_unlock(&splat_module_lock);
+       if (flag == 0)
+               printk(KERN_ERR "splat: Error finalizing: %s\n", name);
+       else
+               fini(sub);
+}
+
+#define SPLAT_SUBSYSTEM_INIT(type) \
+       splat_subsystem_init(#type, splat_##type##_init)
+#define SPLAT_SUBSYSTEM_FINI(type) \
+       splat_subsystem_fini(#type, splat_##type##_id, splat_##type##_fini)
+
+void splat_test_init(splat_subsystem_t *sub, const char *name,
+    const char *desc, unsigned int tid, splat_test_func_t func)
+{
+       splat_test_t *test;
+       test = kmalloc(sizeof (splat_test_t), GFP_KERNEL);
+       if (test == NULL) {
+               printk(KERN_ERR "splat: Error initializing: %s/%u\n",
+                   name, tid);
+               return;
+       }
+       memset(test, 0, sizeof (splat_test_t));
+       strncpy(test->desc.name, name, SPLAT_NAME_SIZE-1);
+       strncpy(test->desc.desc, desc, SPLAT_DESC_SIZE-1);
+       test->desc.id = tid;
+       test->test = func;
+       INIT_LIST_HEAD(&test->test_list);
+       spin_lock(&sub->test_lock);
+       list_add_tail(&test->test_list, &sub->test_list);
+       spin_unlock(&sub->test_lock);
+}
+
+void splat_test_fini(splat_subsystem_t *sub, unsigned int tid)
+{
+       splat_test_t *test, *tmp;
+       int flag = 0;
+
+       spin_lock(&sub->test_lock);
+       list_for_each_entry_safe(test, tmp, &sub->test_list, test_list) {
+               if (test->desc.id == tid) {
+                       list_del_init(&test->test_list);
+                       kfree(test);
+                       flag = 1;
+                       break;
+               }
+       }
+       spin_unlock(&sub->test_lock);
+
+       if (flag == 0)
+               printk(KERN_ERR "splat: Error finalizing: %u\n", tid);
+}
+
+static int __init
 splat_init(void)
 {
-       dev_t dev;
-       int rc;
+       int error;
 
        spin_lock_init(&splat_module_lock);
        INIT_LIST_HEAD(&splat_module_list);
@@ -643,52 +706,21 @@ splat_init(void)
        SPLAT_SUBSYSTEM_INIT(zlib);
        SPLAT_SUBSYSTEM_INIT(linux);
 
-       dev = MKDEV(SPLAT_MAJOR, 0);
-        if ((rc = register_chrdev_region(dev, SPLAT_MINORS, SPLAT_NAME)))
-               goto error;
-
-       /* Support for registering a character driver */
-       cdev_init(&splat_cdev, &splat_fops);
-       splat_cdev.owner = THIS_MODULE;
-       kobject_set_name(&splat_cdev.kobj, SPLAT_NAME);
-       if ((rc = cdev_add(&splat_cdev, dev, SPLAT_MINORS))) {
-               printk(KERN_ERR "SPLAT: Error adding cdev, %d\n", rc);
-               kobject_put(&splat_cdev.kobj);
-               unregister_chrdev_region(dev, SPLAT_MINORS);
-               goto error;
+       error = misc_register(&splat_misc);
+       if (error) {
+               printk(KERN_INFO "SPLAT: misc_register() failed %d\n", error);
+       } else {
+               printk(KERN_INFO "SPLAT: Loaded module v%s-%s%s\n",
+                   SPL_META_VERSION, SPL_META_RELEASE, SPL_DEBUG_STR);
        }
 
-       /* Support for udev make driver info available in sysfs */
-        splat_class = spl_class_create(THIS_MODULE, "splat");
-       if (IS_ERR(splat_class)) {
-               rc = PTR_ERR(splat_class);
-               printk(KERN_ERR "SPLAT: Error creating splat class, %d\n", rc);
-               cdev_del(&splat_cdev);
-               unregister_chrdev_region(dev, SPLAT_MINORS);
-               goto error;
-       }
-
-       splat_device = spl_device_create(splat_class, NULL,
-                                        MKDEV(SPLAT_MAJOR, 0),
-                                        NULL, SPLAT_NAME);
-
-       printk(KERN_INFO "SPLAT: Loaded module v%s-%s%s\n",
-              SPL_META_VERSION, SPL_META_RELEASE, SPL_DEBUG_STR);
-       return 0;
-error:
-       printk(KERN_ERR "SPLAT: Error registering splat device, %d\n", rc);
-       return rc;
+       return (error);
 }
 
-static int
+static void __exit
 splat_fini(void)
 {
-       dev_t dev = MKDEV(SPLAT_MAJOR, 0);
-
-        spl_device_destroy(splat_class, splat_device, dev);
-        spl_class_destroy(splat_class);
-        cdev_del(&splat_cdev);
-        unregister_chrdev_region(dev, SPLAT_MINORS);
+       misc_deregister(&splat_misc);
 
        SPLAT_SUBSYSTEM_FINI(linux);
        SPLAT_SUBSYSTEM_FINI(zlib);
@@ -709,14 +741,13 @@ splat_fini(void)
 
        ASSERT(list_empty(&splat_module_list));
        printk(KERN_INFO "SPLAT: Unloaded module v%s-%s%s\n",
-              SPL_META_VERSION, SPL_META_RELEASE, SPL_DEBUG_STR);
-
-       return 0;
+           SPL_META_VERSION, SPL_META_RELEASE, SPL_DEBUG_STR);
 }
 
-spl_module_init(splat_init);
-spl_module_exit(splat_fini);
+module_init(splat_init);
+module_exit(splat_fini);
 
-MODULE_AUTHOR("Lawrence Livermore National Labs");
 MODULE_DESCRIPTION("Solaris Porting LAyer Tests");
-MODULE_LICENSE("GPL");
+MODULE_AUTHOR(SPL_META_AUTHOR);
+MODULE_LICENSE(SPL_META_LICENSE);
+MODULE_VERSION(SPL_META_VERSION "-" SPL_META_RELEASE);