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>
Tue, 29 Dec 2020 12:44:57 +0000 (13:44 +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 a5da60b24d83ec79fb75bae8cd91ae52b6bcccc8..15bab51a3aef170497ae9fceaaebbb2e4b036ed5 100644 (file)
@@ -310,6 +310,7 @@ struct xprt_class {
        struct rpc_xprt *       (*setup)(struct xprt_create *);
        struct module           *owner;
        char                    name[32];
+       const char *            netid[];
 };
 
 /*
index 1a8df242d26a17c85037fc21a6ecf562303c9888..9491fc81d50ad5eb6e1090d5f4068cef0f3f5b96 100644 (file)
@@ -143,31 +143,64 @@ int xprt_unregister_transport(struct xprt_class *transport)
 }
 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 560712bd9fa2c66680bfbcdd04bf7eab50496a77..dd227de31a589b549856eb5ea7eaf355ca280db6 100644 (file)
@@ -19,6 +19,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 fa324fe7394669dded8565aa1368002f79abf8f8..3ea3bb64b6d5ce14d78350df8a7c94b48ee2bc85 100644 (file)
@@ -777,6 +777,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 f3f05148922a197167ff11d38a102aa31e13429f..bf20ea2606389b818a4594a11a332230507b4326 100644 (file)
@@ -3147,6 +3147,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 = {
@@ -3155,6 +3156,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 = {
@@ -3163,6 +3165,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 = {
@@ -3171,6 +3174,7 @@ static struct xprt_class  xs_bc_tcp_transport = {
        .owner          = THIS_MODULE,
        .ident          = XPRT_TRANSPORT_BC_TCP,
        .setup          = xs_setup_bc_tcp,
+       .netid          = { "" },
 };
 
 /**