SUNRPC: xprt_load_transport() needs to support the netid "rdma6"
authorTrond Myklebust <trond.myklebust@hammerspace.com>
Fri, 6 Nov 2020 21:33:38 +0000 (16:33 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 30 Dec 2020 10:53:30 +0000 (11:53 +0100)
[ Upstream commit d5aa6b22e2258f05317313ecc02efbb988ed6d38 ]

According to RFC5666, the correct netid for an IPv6 addressed RDMA
transport is "rdma6", which we've supported as a mount option since
Linux-4.7. The problem is when we try to load the module "xprtrdma6",
that will fail, since there is no modulealias of that name.

Fixes: 181342c5ebe8 ("xprtrdma: Add rdma6 option to support NFS/RDMA IPv6")
Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
include/linux/sunrpc/xprt.h
net/sunrpc/xprt.c
net/sunrpc/xprtrdma/module.c
net/sunrpc/xprtrdma/transport.c
net/sunrpc/xprtsock.c

index a603d48d2b2cd55095e2467fca40da52ab26a6b6..3ac5037d1c3da2e86de6a07fb1c498bd50c68187 100644 (file)
@@ -330,6 +330,7 @@ struct xprt_class {
        struct rpc_xprt *       (*setup)(struct xprt_create *);
        struct module           *owner;
        char                    name[32];
+       const char *            netid[];
 };
 
 /*
index f6c17e75f20ede63927201b5363841b8c0012254..57f09ea3ef2af761e726579c6e7a1a70693f9b48 100644 (file)
@@ -151,31 +151,64 @@ out:
 }
 EXPORT_SYMBOL_GPL(xprt_unregister_transport);
 
+static void
+xprt_class_release(const struct xprt_class *t)
+{
+       module_put(t->owner);
+}
+
+static const struct xprt_class *
+xprt_class_find_by_netid_locked(const char *netid)
+{
+       const struct xprt_class *t;
+       unsigned int i;
+
+       list_for_each_entry(t, &xprt_list, list) {
+               for (i = 0; t->netid[i][0] != '\0'; i++) {
+                       if (strcmp(t->netid[i], netid) != 0)
+                               continue;
+                       if (!try_module_get(t->owner))
+                               continue;
+                       return t;
+               }
+       }
+       return NULL;
+}
+
+static const struct xprt_class *
+xprt_class_find_by_netid(const char *netid)
+{
+       const struct xprt_class *t;
+
+       spin_lock(&xprt_list_lock);
+       t = xprt_class_find_by_netid_locked(netid);
+       if (!t) {
+               spin_unlock(&xprt_list_lock);
+               request_module("rpc%s", netid);
+               spin_lock(&xprt_list_lock);
+               t = xprt_class_find_by_netid_locked(netid);
+       }
+       spin_unlock(&xprt_list_lock);
+       return t;
+}
+
 /**
  * xprt_load_transport - load a transport implementation
- * @transport_name: transport to load
+ * @netid: transport to load
  *
  * Returns:
  * 0:          transport successfully loaded
  * -ENOENT:    transport module not available
  */
-int xprt_load_transport(const char *transport_name)
+int xprt_load_transport(const char *netid)
 {
-       struct xprt_class *t;
-       int result;
+       const struct xprt_class *t;
 
-       result = 0;
-       spin_lock(&xprt_list_lock);
-       list_for_each_entry(t, &xprt_list, list) {
-               if (strcmp(t->name, transport_name) == 0) {
-                       spin_unlock(&xprt_list_lock);
-                       goto out;
-               }
-       }
-       spin_unlock(&xprt_list_lock);
-       result = request_module("xprt%s", transport_name);
-out:
-       return result;
+       t = xprt_class_find_by_netid(netid);
+       if (!t)
+               return -ENOENT;
+       xprt_class_release(t);
+       return 0;
 }
 EXPORT_SYMBOL_GPL(xprt_load_transport);
 
index 620327c01302ce8702062bd48f7545f9882cea24..45c5b41ac8dc90e0043d4f795c23a42afe4ac6ad 100644 (file)
@@ -24,6 +24,7 @@ MODULE_DESCRIPTION("RPC/RDMA Transport");
 MODULE_LICENSE("Dual BSD/GPL");
 MODULE_ALIAS("svcrdma");
 MODULE_ALIAS("xprtrdma");
+MODULE_ALIAS("rpcrdma6");
 
 static void __exit rpc_rdma_cleanup(void)
 {
index 8915e42240d38b057ed4c6477bd78b7f1f0dc897..035060c05fd5aac9f5d3d0dd0fbaf2d8ad4fffb2 100644 (file)
@@ -768,6 +768,7 @@ static struct xprt_class xprt_rdma = {
        .owner                  = THIS_MODULE,
        .ident                  = XPRT_TRANSPORT_RDMA,
        .setup                  = xprt_setup_rdma,
+       .netid                  = { "rdma", "rdma6", "" },
 };
 
 void xprt_rdma_cleanup(void)
index 7090bbee0ec59d6d8dee6704cd4856e6be8593ac..c93ff70da3f983e8a61a4f4fda7ae3997bc3e2e9 100644 (file)
@@ -3059,6 +3059,7 @@ static struct xprt_class  xs_local_transport = {
        .owner          = THIS_MODULE,
        .ident          = XPRT_TRANSPORT_LOCAL,
        .setup          = xs_setup_local,
+       .netid          = { "" },
 };
 
 static struct xprt_class       xs_udp_transport = {
@@ -3067,6 +3068,7 @@ static struct xprt_class  xs_udp_transport = {
        .owner          = THIS_MODULE,
        .ident          = XPRT_TRANSPORT_UDP,
        .setup          = xs_setup_udp,
+       .netid          = { "udp", "udp6", "" },
 };
 
 static struct xprt_class       xs_tcp_transport = {
@@ -3075,6 +3077,7 @@ static struct xprt_class  xs_tcp_transport = {
        .owner          = THIS_MODULE,
        .ident          = XPRT_TRANSPORT_TCP,
        .setup          = xs_setup_tcp,
+       .netid          = { "tcp", "tcp6", "" },
 };
 
 static struct xprt_class       xs_bc_tcp_transport = {
@@ -3083,6 +3086,7 @@ static struct xprt_class  xs_bc_tcp_transport = {
        .owner          = THIS_MODULE,
        .ident          = XPRT_TRANSPORT_BC_TCP,
        .setup          = xs_setup_bc_tcp,
+       .netid          = { "" },
 };
 
 /**