#include <libcfs/libcfs.h>
#include <libcfs/libcfs_crypto.h>
-#include <libcfs/linux/linux-misc.h>
#include <lnet/lib-lnet.h>
#include "tracefile.h"
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)
{
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);
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;
}
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;
}
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);
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)
{
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;
}
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;
{
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();