Commit 912a8460 authored by NeilBrown's avatar NeilBrown Committed by Greg Kroah-Hartman

staging: lustre: replace libcfs_register_ioctl with a blocking notifier_chain

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.
Signed-off-by: default avatarNeilBrown <neilb@suse.com>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 6afe572b
...@@ -93,19 +93,14 @@ ...@@ -93,19 +93,14 @@
#define LNET_ACCEPTOR_MIN_RESERVED_PORT 512 #define LNET_ACCEPTOR_MIN_RESERVED_PORT 512
#define LNET_ACCEPTOR_MAX_RESERVED_PORT 1023 #define LNET_ACCEPTOR_MAX_RESERVED_PORT 1023
struct libcfs_ioctl_handler { extern struct blocking_notifier_head libcfs_ioctl_list;
struct list_head item; static inline int notifier_from_ioctl_errno(int err)
int (*handle_ioctl)(unsigned int cmd, struct libcfs_ioctl_hdr *hdr); {
}; if (err == -EINVAL)
return NOTIFY_OK;
#define DECLARE_IOCTL_HANDLER(ident, func) \ return notifier_from_errno(err) | NOTIFY_STOP_MASK;
struct libcfs_ioctl_handler ident = { \ }
.item = LIST_HEAD_INIT(ident.item), \
.handle_ioctl = func \
}
int libcfs_register_ioctl(struct libcfs_ioctl_handler *hand);
int libcfs_deregister_ioctl(struct libcfs_ioctl_handler *hand);
int libcfs_setup(void); int libcfs_setup(void);
#define _LIBCFS_H #define _LIBCFS_H
......
...@@ -62,38 +62,8 @@ ...@@ -62,38 +62,8 @@
static struct dentry *lnet_debugfs_root; static struct dentry *lnet_debugfs_root;
static DECLARE_RWSEM(ioctl_list_sem); BLOCKING_NOTIFIER_HEAD(libcfs_ioctl_list);
static LIST_HEAD(ioctl_list); EXPORT_SYMBOL(libcfs_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);
static inline size_t libcfs_ioctl_packlen(struct libcfs_ioctl_data *data) static inline size_t libcfs_ioctl_packlen(struct libcfs_ioctl_data *data)
{ {
...@@ -268,24 +238,18 @@ static int libcfs_ioctl(unsigned long cmd, void __user *uparam) ...@@ -268,24 +238,18 @@ static int libcfs_ioctl(unsigned long cmd, void __user *uparam)
libcfs_debug_mark_buffer(data->ioc_inlbuf1); libcfs_debug_mark_buffer(data->ioc_inlbuf1);
break; break;
default: { default:
struct libcfs_ioctl_handler *hand; err = blocking_notifier_call_chain(&libcfs_ioctl_list,
cmd, hdr);
err = -EINVAL; if (!(err & NOTIFY_STOP_MASK))
down_read(&ioctl_list_sem); /* No-one claimed the ioctl */
list_for_each_entry(hand, &ioctl_list, item) { err = -EINVAL;
err = hand->handle_ioctl(cmd, hdr); else
if (err == -EINVAL) err = notifier_to_errno(err);
continue; if (!err)
if (copy_to_user(uparam, hdr, hdr->ioc_len))
if (!err) { err = -EFAULT;
if (copy_to_user(uparam, hdr, hdr->ioc_len)) break;
err = -EFAULT;
}
break;
}
up_read(&ioctl_list_sem);
break; }
} }
out: out:
kvfree(hdr); kvfree(hdr);
......
...@@ -136,30 +136,37 @@ lnet_dyn_unconfigure(struct libcfs_ioctl_hdr *hdr) ...@@ -136,30 +136,37 @@ lnet_dyn_unconfigure(struct libcfs_ioctl_hdr *hdr)
} }
static int 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; int rc;
struct libcfs_ioctl_hdr *hdr = vdata;
switch (cmd) { switch (cmd) {
case IOC_LIBCFS_CONFIGURE: { case IOC_LIBCFS_CONFIGURE: {
struct libcfs_ioctl_data *data = struct libcfs_ioctl_data *data =
(struct libcfs_ioctl_data *)hdr; (struct libcfs_ioctl_data *)hdr;
if (data->ioc_hdr.ioc_len < sizeof(*data)) if (data->ioc_hdr.ioc_len < sizeof(*data)) {
return -EINVAL; rc = -EINVAL;
} else {
the_lnet.ln_nis_from_mod_params = data->ioc_flags; the_lnet.ln_nis_from_mod_params = data->ioc_flags;
return lnet_configure(NULL); rc = lnet_configure(NULL);
}
break;
} }
case IOC_LIBCFS_UNCONFIGURE: case IOC_LIBCFS_UNCONFIGURE:
return lnet_unconfigure(); rc = lnet_unconfigure();
break;
case IOC_LIBCFS_ADD_NET: case IOC_LIBCFS_ADD_NET:
return lnet_dyn_configure(hdr); rc = lnet_dyn_configure(hdr);
break;
case IOC_LIBCFS_DEL_NET: case IOC_LIBCFS_DEL_NET:
return lnet_dyn_unconfigure(hdr); rc = lnet_dyn_unconfigure(hdr);
break;
default: default:
/* /*
...@@ -172,11 +179,14 @@ lnet_ioctl(unsigned int cmd, struct libcfs_ioctl_hdr *hdr) ...@@ -172,11 +179,14 @@ lnet_ioctl(unsigned int cmd, struct libcfs_ioctl_hdr *hdr)
rc = LNetCtl(cmd, hdr); rc = LNetCtl(cmd, hdr);
LNetNIFini(); LNetNIFini();
} }
return rc; break;
} }
return notifier_from_ioctl_errno(rc);
} }
static 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) static int __init lnet_init(void)
{ {
...@@ -194,7 +204,8 @@ static int __init lnet_init(void) ...@@ -194,7 +204,8 @@ static int __init lnet_init(void)
return rc; return rc;
} }
rc = libcfs_register_ioctl(&lnet_ioctl_handler); rc = blocking_notifier_chain_register(&libcfs_ioctl_list,
&lnet_ioctl_handler);
LASSERT(!rc); LASSERT(!rc);
if (config_on_load) { if (config_on_load) {
...@@ -212,7 +223,8 @@ static void __exit lnet_exit(void) ...@@ -212,7 +223,8 @@ static void __exit lnet_exit(void)
{ {
int rc; int rc;
rc = libcfs_deregister_ioctl(&lnet_ioctl_handler); rc = blocking_notifier_chain_unregister(&libcfs_ioctl_list,
&lnet_ioctl_handler);
LASSERT(!rc); LASSERT(!rc);
lnet_lib_exit(); lnet_lib_exit();
......
...@@ -680,32 +680,34 @@ static int lst_test_add_ioctl(struct lstio_test_args *args) ...@@ -680,32 +680,34 @@ static int lst_test_add_ioctl(struct lstio_test_args *args)
} }
int 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;
char *buf = NULL;
struct libcfs_ioctl_data *data; struct libcfs_ioctl_data *data;
int opc; int opc;
int rc; int rc = -EINVAL;
if (cmd != IOC_LIBCFS_LNETST) if (cmd != IOC_LIBCFS_LNETST)
return -EINVAL; goto err;
data = container_of(hdr, struct libcfs_ioctl_data, ioc_hdr); data = container_of(hdr, struct libcfs_ioctl_data, ioc_hdr);
opc = data->ioc_u32[0]; opc = data->ioc_u32[0];
if (data->ioc_plen1 > PAGE_SIZE) if (data->ioc_plen1 > PAGE_SIZE)
return -EINVAL; goto err;
buf = kmalloc(data->ioc_plen1, GFP_KERNEL); buf = kmalloc(data->ioc_plen1, GFP_KERNEL);
rc = -ENOMEM;
if (!buf) if (!buf)
return -ENOMEM; goto err;
/* copy in parameter */ /* copy in parameter */
if (copy_from_user(buf, data->ioc_pbuf1, data->ioc_plen1)) { rc = -EFAULT;
kfree(buf); if (copy_from_user(buf, data->ioc_pbuf1, data->ioc_plen1))
return -EFAULT; goto err;
}
mutex_lock(&console_session.ses_mutex); mutex_lock(&console_session.ses_mutex);
...@@ -785,6 +787,7 @@ lstcon_ioctl_entry(unsigned int cmd, struct libcfs_ioctl_hdr *hdr) ...@@ -785,6 +787,7 @@ lstcon_ioctl_entry(unsigned int cmd, struct libcfs_ioctl_hdr *hdr)
break; break;
default: default:
rc = -EINVAL; rc = -EINVAL;
goto out;
} }
if (copy_to_user(data->ioc_pbuf2, &console_session.ses_trans_stat, if (copy_to_user(data->ioc_pbuf2, &console_session.ses_trans_stat,
...@@ -792,8 +795,8 @@ lstcon_ioctl_entry(unsigned int cmd, struct libcfs_ioctl_hdr *hdr) ...@@ -792,8 +795,8 @@ lstcon_ioctl_entry(unsigned int cmd, struct libcfs_ioctl_hdr *hdr)
rc = -EFAULT; rc = -EFAULT;
out: out:
mutex_unlock(&console_session.ses_mutex); mutex_unlock(&console_session.ses_mutex);
err:
kfree(buf); kfree(buf);
return rc; return notifier_from_ioctl_errno(rc);
} }
...@@ -1996,7 +1996,9 @@ static void lstcon_init_acceptor_service(void) ...@@ -1996,7 +1996,9 @@ static void lstcon_init_acceptor_service(void)
lstcon_acceptor_service.sv_wi_total = SFW_FRWK_WI_MAX; lstcon_acceptor_service.sv_wi_total = SFW_FRWK_WI_MAX;
} }
static DECLARE_IOCTL_HANDLER(lstcon_ioctl_handler, lstcon_ioctl_entry); static struct notifier_block lstcon_ioctl_handler = {
.notifier_call = lstcon_ioctl_entry,
};
/* initialize console */ /* initialize console */
int int
...@@ -2048,7 +2050,8 @@ lstcon_console_init(void) ...@@ -2048,7 +2050,8 @@ lstcon_console_init(void)
goto out; goto out;
} }
rc = libcfs_register_ioctl(&lstcon_ioctl_handler); rc = blocking_notifier_chain_register(&libcfs_ioctl_list,
&lstcon_ioctl_handler);
if (!rc) { if (!rc) {
lstcon_rpc_module_init(); lstcon_rpc_module_init();
...@@ -2071,7 +2074,8 @@ lstcon_console_fini(void) ...@@ -2071,7 +2074,8 @@ 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); mutex_lock(&console_session.ses_mutex);
......
...@@ -187,7 +187,8 @@ lstcon_id2hash(struct lnet_process_id id, struct list_head *hash) ...@@ -187,7 +187,8 @@ lstcon_id2hash(struct lnet_process_id id, struct list_head *hash)
return &hash[idx]; return &hash[idx];
} }
int lstcon_ioctl_entry(unsigned int cmd, struct libcfs_ioctl_hdr *hdr); int lstcon_ioctl_entry(struct notifier_block *nb,
unsigned long cmd, void *vdata);
int lstcon_console_init(void); int lstcon_console_init(void);
int lstcon_console_fini(void); int lstcon_console_fini(void);
int lstcon_session_match(struct lst_sid sid); int lstcon_session_match(struct lst_sid sid);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment