Whamcloud - gitweb
LU-6202 libcfs: replace libcfs_register_ioctl with a blocking notifier_chain 84/33284/4
authorNeilBrown <neilb@suse.com>
Fri, 5 Oct 2018 13:02:41 +0000 (09:02 -0400)
committerOleg Drokin <green@whamcloud.com>
Wed, 10 Oct 2018 01:50:49 +0000 (01:50 +0000)
libcfs allows other modules to register handlers for ioctls.
The implementation it uses for this is nearly identical to a
blocking notifier chain, so change to use that.

The biggest difference is that the return value from notifier has a
defined format, where libcfs_register_ioctl uses -EINVAL to mean
"continue".  This requires a little bit of conversion.

Linux-commit: 912a846027c203370f4837a2b2db7ba2ebe1b47c

Change-Id: I84657fc1befd004eb09de37b5549af8bff034738
Signed-off-by: NeilBrown <neilb@suse.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: James Simmons <uja.ornl@yahoo.com>
Reviewed-on: https://review.whamcloud.com/33284
Reviewed-by: Andreas Dilger <adilger@whamcloud.com>
Reviewed-by: Ben Evans <bevans@cray.com>
Tested-by: Jenkins
Tested-by: Maloo <hpdd-maloo@intel.com>
Reviewed-by: Oleg Drokin <green@whamcloud.com>
libcfs/include/libcfs/libcfs.h
libcfs/libcfs/module.c
lnet/include/lnet/lib-lnet.h
lnet/lnet/module.c
lnet/selftest/conctl.c
lnet/selftest/console.c
lnet/selftest/console.h

index 9b4395e..7d687dc 100644 (file)
@@ -91,6 +91,14 @@ void lc_watchdog_delete(struct lc_watchdog *lcw);
 #define LNET_ACCEPTOR_MIN_RESERVED_PORT    512
 #define LNET_ACCEPTOR_MAX_RESERVED_PORT    1023
 
+extern struct blocking_notifier_head libcfs_ioctl_list;
+static inline int notifier_from_ioctl_errno(int err)
+{
+       if (err == -EINVAL)
+               return NOTIFY_OK;
+       return notifier_from_errno(err) | NOTIFY_STOP_MASK;
+}
+
 /*
  * Defined by platform
  */
index e6e6d0c..370c905 100644 (file)
 
 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);
index aeb0e4b..2b52cb7 100644 (file)
@@ -575,19 +575,6 @@ struct lnet_ni *lnet_get_next_ni_locked(struct lnet_net *mynet,
                                        struct lnet_ni *prev);
 struct lnet_ni *lnet_get_ni_idx_locked(int idx);
 
-struct libcfs_ioctl_handler {
-       struct list_head item;
-       int (*handle_ioctl)(unsigned int cmd, struct libcfs_ioctl_hdr *hdr);
-};
-
-#define DECLARE_IOCTL_HANDLER(ident, func)                     \
-       static struct libcfs_ioctl_handler ident = {            \
-               .item         = LIST_HEAD_INIT(ident.item),     \
-               .handle_ioctl = func                            \
-       }
-
-extern int libcfs_register_ioctl(struct libcfs_ioctl_handler *hand);
-extern int libcfs_deregister_ioctl(struct libcfs_ioctl_handler *hand);
 extern int libcfs_ioctl_getdata(struct libcfs_ioctl_hdr **hdr_pp,
                                struct libcfs_ioctl_hdr __user *uparam);
 extern int lnet_get_peer_list(__u32 *countp, __u32 *sizep,
index c30669a..676f734 100644 (file)
@@ -172,36 +172,45 @@ lnet_dyn_unconfigure_ni(struct libcfs_ioctl_hdr *hdr)
 }
 
 static int
-lnet_ioctl(unsigned int cmd, struct libcfs_ioctl_hdr *hdr)
+lnet_ioctl(struct notifier_block *nb,
+          unsigned long cmd, void *vdata)
 {
-       int   rc;
+       struct libcfs_ioctl_hdr *hdr = vdata;
+       int rc;
 
        switch (cmd) {
        case IOC_LIBCFS_CONFIGURE: {
                struct libcfs_ioctl_data *data =
                  (struct libcfs_ioctl_data *)hdr;
 
-               if (data->ioc_hdr.ioc_len < sizeof(*data))
-                       return -EINVAL;
-
-               the_lnet.ln_nis_from_mod_params = data->ioc_flags;
-               return lnet_configure(NULL);
+               if (data->ioc_hdr.ioc_len < sizeof(*data)) {
+                       rc = -EINVAL;
+               } else {
+                       the_lnet.ln_nis_from_mod_params = data->ioc_flags;
+                       rc = lnet_configure(NULL);
+               }
+               break;
        }
 
        case IOC_LIBCFS_UNCONFIGURE:
-               return lnet_unconfigure();
+               rc = lnet_unconfigure();
+               break;
 
        case IOC_LIBCFS_ADD_NET:
-               return lnet_dyn_configure_net(hdr);
+               rc = lnet_dyn_configure_net(hdr);
+               break;
 
        case IOC_LIBCFS_DEL_NET:
-               return lnet_dyn_unconfigure_net(hdr);
+               rc = lnet_dyn_unconfigure_net(hdr);
+               break;
 
        case IOC_LIBCFS_ADD_LOCAL_NI:
-               return lnet_dyn_configure_ni(hdr);
+               rc = lnet_dyn_configure_ni(hdr);
+               break;
 
        case IOC_LIBCFS_DEL_LOCAL_NI:
-               return lnet_dyn_unconfigure_ni(hdr);
+               rc = lnet_dyn_unconfigure_ni(hdr);
+               break;
 
        default:
                /* Passing LNET_PID_ANY only gives me a ref if the net is up
@@ -212,11 +221,14 @@ lnet_ioctl(unsigned int cmd, struct libcfs_ioctl_hdr *hdr)
                        rc = LNetCtl(cmd, hdr);
                        LNetNIFini();
                }
-               return rc;
+               break;
        }
+       return notifier_from_ioctl_errno(rc);
 }
 
-DECLARE_IOCTL_HANDLER(lnet_ioctl_handler, lnet_ioctl);
+static struct notifier_block lnet_ioctl_handler = {
+       .notifier_call = lnet_ioctl,
+};
 
 static int __init lnet_init(void)
 {
@@ -231,7 +243,8 @@ static int __init lnet_init(void)
                RETURN(rc);
        }
 
-       rc = libcfs_register_ioctl(&lnet_ioctl_handler);
+       rc = blocking_notifier_chain_register(&libcfs_ioctl_list,
+                                             &lnet_ioctl_handler);
        LASSERT(rc == 0);
 
        if (config_on_load) {
@@ -247,7 +260,8 @@ static void __exit lnet_exit(void)
 {
        int rc;
 
-       rc = libcfs_deregister_ioctl(&lnet_ioctl_handler);
+       rc = blocking_notifier_chain_unregister(&libcfs_ioctl_list,
+                                               &lnet_ioctl_handler);
        LASSERT(rc == 0);
 
        lnet_lib_exit();
index ef878b6..4767ab8 100644 (file)
@@ -805,31 +805,35 @@ out:
 }
 
 int
-lstcon_ioctl_entry(unsigned int cmd, struct libcfs_ioctl_hdr *hdr)
+lstcon_ioctl_entry(struct notifier_block *nb,
+                  unsigned long cmd, void *vdata)
 {
-       char   *buf;
+       struct libcfs_ioctl_hdr *hdr = vdata;
        struct libcfs_ioctl_data *data;
-       int     opc;
-       int     rc;
+       char *buf = NULL;
+       int rc = -EINVAL;
+       int opc;
 
        if (cmd != IOC_LIBCFS_LNETST)
-               return -EINVAL;
+               goto err;
 
        data = container_of(hdr, struct libcfs_ioctl_data, ioc_hdr);
 
        opc = data->ioc_u32[0];
 
        if (data->ioc_plen1 > PAGE_SIZE)
-               return -EINVAL;
+               goto err;
 
        LIBCFS_ALLOC(buf, data->ioc_plen1);
-       if (buf == NULL)
-               return -ENOMEM;
+       if (buf == NULL) {
+               rc = -ENOMEM;
+               goto err;
+       }
 
        /* copy in parameter */
        if (copy_from_user(buf, data->ioc_pbuf1, data->ioc_plen1)) {
-               LIBCFS_FREE(buf, data->ioc_plen1);
-               return -EFAULT;
+               rc = -EFAULT;
+               goto out_free_buf;
        }
 
        mutex_lock(&console_session.ses_mutex);
@@ -910,6 +914,7 @@ lstcon_ioctl_entry(unsigned int cmd, struct libcfs_ioctl_hdr *hdr)
                break;
        default:
                rc = -EINVAL;
+               goto out;
        }
 
        if (copy_to_user(data->ioc_pbuf2, &console_session.ses_trans_stat,
@@ -917,8 +922,8 @@ lstcon_ioctl_entry(unsigned int cmd, struct libcfs_ioctl_hdr *hdr)
                rc = -EFAULT;
 out:
        mutex_unlock(&console_session.ses_mutex);
-
+out_free_buf:
        LIBCFS_FREE(buf, data->ioc_plen1);
-
-       return rc;
+err:
+       return notifier_from_ioctl_errno(rc);
 }
index ee41bf3..a595476 100644 (file)
@@ -2004,9 +2004,9 @@ static void lstcon_init_acceptor_service(void)
        lstcon_acceptor_service.sv_wi_total = SFW_FRWK_WI_MAX;
 }
 
-int lstcon_ioctl_entry(unsigned int cmd, struct libcfs_ioctl_hdr *hdr);
-
-DECLARE_IOCTL_HANDLER(lstcon_ioctl_handler, lstcon_ioctl_entry);
+static struct notifier_block lstcon_ioctl_handler = {
+       .notifier_call = lstcon_ioctl_entry,
+};
 
 /* initialize console */
 int
@@ -2058,12 +2058,12 @@ lstcon_console_init(void)
                 goto out;
         }
 
-        rc = libcfs_register_ioctl(&lstcon_ioctl_handler);
-
-        if (rc == 0) {
-                lstcon_rpc_module_init();
-                return 0;
-        }
+       rc = blocking_notifier_chain_register(&libcfs_ioctl_list,
+                                             &lstcon_ioctl_handler);
+       if (rc == 0) {
+               lstcon_rpc_module_init();
+               return 0;
+       }
 
 out:
        srpc_shutdown_service(&lstcon_acceptor_service);
@@ -2080,9 +2080,10 @@ out:
 int
 lstcon_console_fini(void)
 {
-        int     i;
+       int i;
 
-        libcfs_deregister_ioctl(&lstcon_ioctl_handler);
+       blocking_notifier_chain_unregister(&libcfs_ioctl_list,
+                                          &lstcon_ioctl_handler);
 
        mutex_lock(&console_session.ses_mutex);
 
index d1d9635..09cd0e8 100644 (file)
@@ -256,6 +256,8 @@ extern int lstcon_test_add(char *batch_name, int type, int loop,
                           void *param, int paramlen, int *retp,
                           struct list_head __user *result_up);
 
+int lstcon_ioctl_entry(struct notifier_block *nb,
+                      unsigned long cmd, void *vdata);
 int lstcon_console_init(void);
 int lstcon_console_fini(void);