From patchwork Mon Jul 24 22:26:43 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jason Gunthorpe X-Patchwork-Id: 9860759 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 744E360349 for ; Mon, 24 Jul 2017 22:27:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 672D628565 for ; Mon, 24 Jul 2017 22:27:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 5C0AC2859F; Mon, 24 Jul 2017 22:27:18 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C3D5B28565 for ; Mon, 24 Jul 2017 22:27:17 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756900AbdGXW1P (ORCPT ); Mon, 24 Jul 2017 18:27:15 -0400 Received: from quartz.orcorp.ca ([184.70.90.242]:49582 "EHLO quartz.orcorp.ca" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756903AbdGXW0z (ORCPT ); Mon, 24 Jul 2017 18:26:55 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=obsidianresearch.com; s=rsa1; h=References:In-Reply-To:Message-Id:Date:Subject:To:From; bh=41rYh5iFe3+EXTY11lFg46y9bBwtNxLu8gwZz1yq1cU=; b=XDZWiND2250+4OJAU1yrvPACVDMOS3Rqhj8W53WXxpcVjMFiZ5QwGu6kVaxvhffEkNK5i6iA9lBOFS5eBtEm8eIqNj//i+LJ7vxCIMQl9TEY1gbItLA8Pn5Hj/l51TCp1dbXRPNeqok+My1io/3BRmY7N03sp+IQQw0kMjdzkZk=; Received: from [10.0.0.156] (helo=jggl.edm.orcorp.ca) by quartz.orcorp.ca with esmtps (TLS1.2:ECDHE_RSA_AES_128_CBC_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1dZloR-00049s-QU; Mon, 24 Jul 2017 16:26:51 -0600 From: Jason Gunthorpe To: linux-rdma@vger.kernel.org, Leon Romanovsky , Doug Ledford Subject: [PATCH 2/3] rdma: Autoload netlink client modules Date: Mon, 24 Jul 2017 16:26:43 -0600 Message-Id: <1500935204-6505-3-git-send-email-jgunthorpe@obsidianresearch.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1500935204-6505-1-git-send-email-jgunthorpe@obsidianresearch.com> References: <1500935204-6505-1-git-send-email-jgunthorpe@obsidianresearch.com> X-Broken-Reverse-DNS: no host name found for IP address 10.0.0.156 Sender: linux-rdma-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-rdma@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP If a message comes in and we do not have the client in the table, then try to load the module supplying that client using MODULE_ALIAS to find it. This duplicates the scheme seen in other netlink muxes (eg nfnetlink). Factor out ibnl_find_client since this creates a 3rd copy of the pattern. Signed-off-by: Jason Gunthorpe --- drivers/infiniband/core/cma.c | 2 + drivers/infiniband/core/device.c | 2 + drivers/infiniband/core/iwcm.c | 2 + drivers/infiniband/core/netlink.c | 96 ++++++++++++++++++++++----------------- include/rdma/rdma_netlink.h | 12 +++++ 5 files changed, 73 insertions(+), 41 deletions(-) diff --git a/drivers/infiniband/core/cma.c b/drivers/infiniband/core/cma.c index 0eb393237ba2fc..f63a11e31ec988 100644 --- a/drivers/infiniband/core/cma.c +++ b/drivers/infiniband/core/cma.c @@ -4534,5 +4534,7 @@ static void __exit cma_cleanup(void) destroy_workqueue(cma_wq); } +MODULE_ALIAS_RDMA_NETLINK(RDMA_NL_RDMA_CM, 1); + module_init(cma_init); module_exit(cma_cleanup); diff --git a/drivers/infiniband/core/device.c b/drivers/infiniband/core/device.c index a5dfab6adf495b..6630b334ae7526 100644 --- a/drivers/infiniband/core/device.c +++ b/drivers/infiniband/core/device.c @@ -1204,5 +1204,7 @@ static void __exit ib_core_cleanup(void) destroy_workqueue(ib_wq); } +MODULE_ALIAS_RDMA_NETLINK(RDMA_NL_LS, 4); + module_init(ib_core_init); module_exit(ib_core_cleanup); diff --git a/drivers/infiniband/core/iwcm.c b/drivers/infiniband/core/iwcm.c index 31661b5c174364..51585a8e467a56 100644 --- a/drivers/infiniband/core/iwcm.c +++ b/drivers/infiniband/core/iwcm.c @@ -1204,5 +1204,7 @@ static void __exit iw_cm_cleanup(void) iwpm_exit(RDMA_NL_IWCM); } +MODULE_ALIAS_RDMA_NETLINK(RDMA_NL_IWCM, 2); + module_init(iw_cm_init); module_exit(iw_cm_cleanup); diff --git a/drivers/infiniband/core/netlink.c b/drivers/infiniband/core/netlink.c index 1165fe81d104a3..36141b9457f0e6 100644 --- a/drivers/infiniband/core/netlink.c +++ b/drivers/infiniband/core/netlink.c @@ -51,6 +51,18 @@ static DEFINE_MUTEX(ibnl_mutex); static struct sock *nls; static LIST_HEAD(client_list); +static struct ibnl_client *ibnl_find_client(int index) +{ + struct ibnl_client *client; + + list_for_each_entry_rcu(client, &client_list, list) { + if (client->index == index) + return client; + } + + return NULL; +} + int ibnl_chk_listeners(unsigned int group) { if (netlink_has_listeners(nls, group) == 0) @@ -61,7 +73,6 @@ int ibnl_chk_listeners(unsigned int group) int ibnl_add_client(int index, int nops, const struct ibnl_client_cbs cb_table[]) { - struct ibnl_client *cur; struct ibnl_client *nl_client; nl_client = kmalloc(sizeof *nl_client, GFP_KERNEL); @@ -73,14 +84,11 @@ int ibnl_add_client(int index, int nops, nl_client->cb_table = cb_table; mutex_lock(&ibnl_mutex); - - list_for_each_entry(cur, &client_list, list) { - if (cur->index == index) { - pr_warn("Client for %d already exists\n", index); - mutex_unlock(&ibnl_mutex); - kfree(nl_client); - return -EINVAL; - } + if (ibnl_find_client(index)) { + pr_warn("Client for %d already exists\n", index); + mutex_unlock(&ibnl_mutex); + kfree(nl_client); + return -EINVAL; } list_add_tail(&nl_client->list, &client_list); @@ -155,40 +163,46 @@ static int ibnl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, int index = RDMA_NL_GET_CLIENT(type); unsigned int op = RDMA_NL_GET_OP(type); - list_for_each_entry(client, &client_list, list) { - if (client->index == index) { - if (op >= client->nops || !client->cb_table[op].dump) - return -EINVAL; - - /* - * For response or local service set_timeout request, - * there is no need to use netlink_dump_start. - */ - if (!(nlh->nlmsg_flags & NLM_F_REQUEST) || - (index == RDMA_NL_LS && - op == RDMA_NL_LS_OP_SET_TIMEOUT)) { - struct netlink_callback cb = { - .skb = skb, - .nlh = nlh, - .dump = client->cb_table[op].dump, - .module = client->cb_table[op].module, - }; - - return cb.dump(skb, &cb); - } - - { - struct netlink_dump_control c = { - .dump = client->cb_table[op].dump, - .module = client->cb_table[op].module, - }; - return netlink_dump_start(nls, skb, nlh, &c); - } - } + client = ibnl_find_client(index); +#ifdef CONFIG_MODULES + if (!client) { + mutex_unlock(&ibnl_mutex); + request_module("rdma_netlink_subsys-%d", index); + mutex_lock(&ibnl_mutex); + client = ibnl_find_client(index); + } +#endif + if (!client) { + pr_info("Index %d wasn't found in client list\n", index); + return -EINVAL; } - pr_info("Index %d wasn't found in client list\n", index); - return -EINVAL; + if (op >= client->nops || !client->cb_table[op].dump) + return -EINVAL; + + /* + * For response or local service set_timeout request, + * there is no need to use netlink_dump_start. + */ + if (!(nlh->nlmsg_flags & NLM_F_REQUEST) || + (index == RDMA_NL_LS && op == RDMA_NL_LS_OP_SET_TIMEOUT)) { + struct netlink_callback cb = { + .skb = skb, + .nlh = nlh, + .dump = client->cb_table[op].dump, + .module = client->cb_table[op].module, + }; + + return cb.dump(skb, &cb); + } + + { + struct netlink_dump_control c = { + .dump = client->cb_table[op].dump, + .module = client->cb_table[op].module, + }; + return netlink_dump_start(nls, skb, nlh, &c); + } } static void ibnl_rcv_reply_skb(struct sk_buff *skb) diff --git a/include/rdma/rdma_netlink.h b/include/rdma/rdma_netlink.h index 348c102cb5f6af..5b2e813592199a 100644 --- a/include/rdma/rdma_netlink.h +++ b/include/rdma/rdma_netlink.h @@ -10,6 +10,18 @@ struct ibnl_client_cbs { struct module *module; }; +/* Define this module as providing netlinkg services for NETLINK_RDMA, client + * index _index. Since the client indexes were setup in a uapi header as an + * enum and we do no want to change that, the user must supply the expanded + * constant as well and the compiler checks they are the same. + */ +#define MODULE_ALIAS_RDMA_NETLINK(_index, _val) \ + static inline void __chk_##_index(void) \ + { \ + BUILD_BUG_ON(_index != _val); \ + } \ + MODULE_ALIAS("rdma_netlink_subsys-" __stringify(_val)) + /** * Add a a client to the list of IB netlink exporters. * @index: Index of the added client