Whamcloud - gitweb
LU-11986 lnet: properly cleanup lnet debugfs files
[fs/lustre-release.git] / libcfs / libcfs / module.c
index cdfd83e..de792a9 100644 (file)
@@ -23,7 +23,7 @@
  * Copyright (c) 2008, 2010, Oracle and/or its affiliates. All rights reserved.
  * Use is subject to license terms.
  *
- * Copyright (c) 2012, 2015, Intel Corporation.
+ * Copyright (c) 2012, 2017, Intel Corporation.
  */
 /*
  * This file is part of Lustre, http://www.lustre.org/
 
 static struct dentry *lnet_debugfs_root;
 
-static DECLARE_RWSEM(ioctl_list_sem);
-static LIST_HEAD(ioctl_list);
-
-int libcfs_register_ioctl(struct libcfs_ioctl_handler *hand)
-{
-       int rc = 0;
-
-       down_write(&ioctl_list_sem);
-       if (!list_empty(&hand->item))
-               rc = -EBUSY;
-       else
-               list_add_tail(&hand->item, &ioctl_list);
-       up_write(&ioctl_list_sem);
-
-       return rc;
-}
-EXPORT_SYMBOL(libcfs_register_ioctl);
-
-int libcfs_deregister_ioctl(struct libcfs_ioctl_handler *hand)
-{
-       int rc = 0;
-
-       down_write(&ioctl_list_sem);
-       if (list_empty(&hand->item))
-               rc = -ENOENT;
-       else
-               list_del_init(&hand->item);
-       up_write(&ioctl_list_sem);
-
-       return rc;
-}
-EXPORT_SYMBOL(libcfs_deregister_ioctl);
+BLOCKING_NOTIFIER_HEAD(libcfs_ioctl_list);
+EXPORT_SYMBOL(libcfs_ioctl_list);
 
 int libcfs_ioctl(unsigned long cmd, void __user *uparam)
 {
@@ -131,22 +101,18 @@ int libcfs_ioctl(unsigned long cmd, void __user *uparam)
                libcfs_debug_mark_buffer(data->ioc_inlbuf1);
                break;
 
-       default: {
-               struct libcfs_ioctl_handler *hand;
-
-               err = -EINVAL;
-               down_read(&ioctl_list_sem);
-               list_for_each_entry(hand, &ioctl_list, item) {
-                       err = hand->handle_ioctl(cmd, hdr);
-                       if (err == -EINVAL)
-                               continue;
-
+       default:
+               err = blocking_notifier_call_chain(&libcfs_ioctl_list,
+                                                  cmd, hdr);
+               if (!(err & NOTIFY_STOP_MASK))
+                       /* No-one claimed the ioctl */
+                       err = -EINVAL;
+               else
+                       err = notifier_to_errno(err);
+               if (!err)
                        if (copy_to_user(uparam, hdr, hdr->ioc_len))
                                err = -EFAULT;
-                       break;
-               }
-               up_read(&ioctl_list_sem);
-               break; }
+               break;
        }
 out:
        LIBCFS_FREE(hdr, hdr->ioc_len);
@@ -525,11 +491,13 @@ static ssize_t lnet_debugfs_read(struct file *filp, char __user *buf,
                                 size_t count, loff_t *ppos)
 {
        struct ctl_table *table = filp->private_data;
-       ssize_t rc;
+       ssize_t rc = -EINVAL;
 
-       rc = table->proc_handler(table, 0, buf, &count, ppos);
-       if (!rc)
-               rc = count;
+       if (table) {
+               rc = table->proc_handler(table, 0, buf, &count, ppos);
+               if (!rc)
+                       rc = count;
+       }
 
        return rc;
 }
@@ -538,11 +506,14 @@ static ssize_t lnet_debugfs_write(struct file *filp, const char __user *buf,
                                  size_t count, loff_t *ppos)
 {
        struct ctl_table *table = filp->private_data;
-       ssize_t rc;
+       ssize_t rc = -EINVAL;
 
-       rc = table->proc_handler(table, 1, (void __user *)buf, &count, ppos);
-       if (!rc)
-               rc = count;
+       if (table) {
+               rc = table->proc_handler(table, 1, (void __user *)buf, &count,
+                                        ppos);
+               if (!rc)
+                       rc = count;
+       }
 
        return rc;
 }
@@ -577,8 +548,7 @@ static const struct file_operations *lnet_debugfs_fops_select(umode_t mode)
        return &lnet_debugfs_file_operations_rw;
 }
 
-void lnet_insert_debugfs(struct ctl_table *table,
-                        const struct lnet_debugfs_symlink_def *symlinks)
+void lnet_insert_debugfs(struct ctl_table *table)
 {
        if (!lnet_debugfs_root)
                lnet_debugfs_root = debugfs_create_dir("lnet", NULL);
@@ -594,19 +564,29 @@ void lnet_insert_debugfs(struct ctl_table *table,
                debugfs_create_file(table->procname, table->mode,
                                    lnet_debugfs_root, table,
                                    lnet_debugfs_fops_select(table->mode));
+}
+EXPORT_SYMBOL_GPL(lnet_insert_debugfs);
 
+static void lnet_insert_debugfs_links(
+               const struct lnet_debugfs_symlink_def *symlinks)
+{
        for (; symlinks && symlinks->name; symlinks++)
                debugfs_create_symlink(symlinks->name, lnet_debugfs_root,
                                       symlinks->target);
 }
-EXPORT_SYMBOL_GPL(lnet_insert_debugfs);
 
-static void lnet_remove_debugfs(void)
+void lnet_remove_debugfs(struct ctl_table *table)
 {
-       debugfs_remove_recursive(lnet_debugfs_root);
+       for (; table && table->procname; table++) {
+               struct qstr dname = QSTR_INIT(table->procname,
+                                             strlen(table->procname));
+               struct dentry *dentry;
 
-       lnet_debugfs_root = NULL;
+               dentry = d_hash_and_lookup(lnet_debugfs_root, &dname);
+               debugfs_remove(dentry);
+       }
 }
+EXPORT_SYMBOL_GPL(lnet_remove_debugfs);
 
 static int __init libcfs_init(void)
 {
@@ -634,12 +614,11 @@ static int __init libcfs_init(void)
                goto cleanup_deregister;
        }
 
-       /* max to 4 threads, should be enough for rehash */
-       rc = min(cfs_cpt_weight(cfs_cpt_table, CFS_CPT_ANY), 4);
-       rc = cfs_wi_sched_create("cfs_rh", cfs_cpt_table, CFS_CPT_ANY,
-                                rc, &cfs_sched_rehash);
-       if (rc != 0) {
-               CERROR("Startup workitem scheduler: error: %d\n", rc);
+       cfs_rehash_wq = alloc_workqueue("cfs_rh", WQ_SYSFS, 4);
+       if (!cfs_rehash_wq) {
+               rc = -ENOMEM;
+               CERROR("libcfs: failed to start rehash workqueue: rc = %d\n",
+                      rc);
                goto cleanup_deregister;
        }
 
@@ -649,7 +628,9 @@ static int __init libcfs_init(void)
                goto cleanup_wi;
        }
 
-       lnet_insert_debugfs(lnet_table, lnet_debugfs_symlinks);
+       lnet_insert_debugfs(lnet_table);
+       if (!IS_ERR_OR_NULL(lnet_debugfs_root))
+               lnet_insert_debugfs_links(lnet_debugfs_symlinks);
 
        CDEBUG (D_OTHER, "portals setup OK\n");
        return 0;
@@ -668,14 +649,16 @@ static void __exit libcfs_exit(void)
 {
        int rc;
 
-       lnet_remove_debugfs();
+       /* Remove everthing */
+       debugfs_remove_recursive(lnet_debugfs_root);
+       lnet_debugfs_root = NULL;
 
        CDEBUG(D_MALLOC, "before Portals cleanup: kmem %d\n",
               atomic_read(&libcfs_kmemory));
 
-       if (cfs_sched_rehash != NULL) {
-               cfs_wi_sched_destroy(cfs_sched_rehash);
-               cfs_sched_rehash = NULL;
+       if (cfs_rehash_wq) {
+               destroy_workqueue(cfs_rehash_wq);
+               cfs_rehash_wq = NULL;
        }
 
        cfs_crypto_unregister();