SUNRPC: introduce svc_xprt_create_from_sa utility routine
authorLorenzo Bianconi <lorenzo@kernel.org>
Tue, 23 Apr 2024 13:25:42 +0000 (15:25 +0200)
committerChuck Lever <chuck.lever@oracle.com>
Mon, 6 May 2024 13:07:22 +0000 (09:07 -0400)
Add svc_xprt_create_from_sa utility routine and refactor
svc_xprt_create() codebase in order to introduce the capability to
create a svc port from socket address.

Reviewed-by: Jeff Layton <jlayton@kernel.org>
Tested-by: Jeff Layton <jlayton@kernel.org>
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
include/linux/sunrpc/svc_xprt.h
net/sunrpc/svc_xprt.c

index 8e20cd60e2e712afd9be8b30b82eae200795aef3..0d9b10dbe07d19a636af443c714407b609cbac34 100644 (file)
@@ -135,6 +135,9 @@ int svc_reg_xprt_class(struct svc_xprt_class *);
 void   svc_unreg_xprt_class(struct svc_xprt_class *);
 void   svc_xprt_init(struct net *, struct svc_xprt_class *, struct svc_xprt *,
                      struct svc_serv *);
+int    svc_xprt_create_from_sa(struct svc_serv *serv, const char *xprt_name,
+                               struct net *net, struct sockaddr *sap,
+                               int flags, const struct cred *cred);
 int    svc_xprt_create(struct svc_serv *serv, const char *xprt_name,
                        struct net *net, const int family,
                        const unsigned short port, int flags,
index b4a85a227bd7d0cb0b4d363e999f9331eca304f0..463fe544ae285e208ea0696c8f88419073ab18f3 100644 (file)
@@ -211,51 +211,6 @@ void svc_xprt_init(struct net *net, struct svc_xprt_class *xcl,
 }
 EXPORT_SYMBOL_GPL(svc_xprt_init);
 
-static struct svc_xprt *__svc_xpo_create(struct svc_xprt_class *xcl,
-                                        struct svc_serv *serv,
-                                        struct net *net,
-                                        const int family,
-                                        const unsigned short port,
-                                        int flags)
-{
-       struct sockaddr_in sin = {
-               .sin_family             = AF_INET,
-               .sin_addr.s_addr        = htonl(INADDR_ANY),
-               .sin_port               = htons(port),
-       };
-#if IS_ENABLED(CONFIG_IPV6)
-       struct sockaddr_in6 sin6 = {
-               .sin6_family            = AF_INET6,
-               .sin6_addr              = IN6ADDR_ANY_INIT,
-               .sin6_port              = htons(port),
-       };
-#endif
-       struct svc_xprt *xprt;
-       struct sockaddr *sap;
-       size_t len;
-
-       switch (family) {
-       case PF_INET:
-               sap = (struct sockaddr *)&sin;
-               len = sizeof(sin);
-               break;
-#if IS_ENABLED(CONFIG_IPV6)
-       case PF_INET6:
-               sap = (struct sockaddr *)&sin6;
-               len = sizeof(sin6);
-               break;
-#endif
-       default:
-               return ERR_PTR(-EAFNOSUPPORT);
-       }
-
-       xprt = xcl->xcl_ops->xpo_create(serv, net, sap, len, flags);
-       if (IS_ERR(xprt))
-               trace_svc_xprt_create_err(serv->sv_program->pg_name,
-                                         xcl->xcl_name, sap, len, xprt);
-       return xprt;
-}
-
 /**
  * svc_xprt_received - start next receiver thread
  * @xprt: controlling transport
@@ -294,9 +249,8 @@ void svc_add_new_perm_xprt(struct svc_serv *serv, struct svc_xprt *new)
 }
 
 static int _svc_xprt_create(struct svc_serv *serv, const char *xprt_name,
-                           struct net *net, const int family,
-                           const unsigned short port, int flags,
-                           const struct cred *cred)
+                           struct net *net, struct sockaddr *sap,
+                           size_t len, int flags, const struct cred *cred)
 {
        struct svc_xprt_class *xcl;
 
@@ -312,8 +266,11 @@ static int _svc_xprt_create(struct svc_serv *serv, const char *xprt_name,
                        goto err;
 
                spin_unlock(&svc_xprt_class_lock);
-               newxprt = __svc_xpo_create(xcl, serv, net, family, port, flags);
+               newxprt = xcl->xcl_ops->xpo_create(serv, net, sap, len, flags);
                if (IS_ERR(newxprt)) {
+                       trace_svc_xprt_create_err(serv->sv_program->pg_name,
+                                                 xcl->xcl_name, sap, len,
+                                                 newxprt);
                        module_put(xcl->xcl_owner);
                        return PTR_ERR(newxprt);
                }
@@ -329,6 +286,48 @@ static int _svc_xprt_create(struct svc_serv *serv, const char *xprt_name,
        return -EPROTONOSUPPORT;
 }
 
+/**
+ * svc_xprt_create_from_sa - Add a new listener to @serv from socket address
+ * @serv: target RPC service
+ * @xprt_name: transport class name
+ * @net: network namespace
+ * @sap: socket address pointer
+ * @flags: SVC_SOCK flags
+ * @cred: credential to bind to this transport
+ *
+ * Return local xprt port on success or %-EPROTONOSUPPORT on failure
+ */
+int svc_xprt_create_from_sa(struct svc_serv *serv, const char *xprt_name,
+                           struct net *net, struct sockaddr *sap,
+                           int flags, const struct cred *cred)
+{
+       size_t len;
+       int err;
+
+       switch (sap->sa_family) {
+       case AF_INET:
+               len = sizeof(struct sockaddr_in);
+               break;
+#if IS_ENABLED(CONFIG_IPV6)
+       case AF_INET6:
+               len = sizeof(struct sockaddr_in6);
+               break;
+#endif
+       default:
+               return -EAFNOSUPPORT;
+       }
+
+       err = _svc_xprt_create(serv, xprt_name, net, sap, len, flags, cred);
+       if (err == -EPROTONOSUPPORT) {
+               request_module("svc%s", xprt_name);
+               err = _svc_xprt_create(serv, xprt_name, net, sap, len, flags,
+                                      cred);
+       }
+
+       return err;
+}
+EXPORT_SYMBOL_GPL(svc_xprt_create_from_sa);
+
 /**
  * svc_xprt_create - Add a new listener to @serv
  * @serv: target RPC service
@@ -339,23 +338,41 @@ static int _svc_xprt_create(struct svc_serv *serv, const char *xprt_name,
  * @flags: SVC_SOCK flags
  * @cred: credential to bind to this transport
  *
- * Return values:
- *   %0: New listener added successfully
- *   %-EPROTONOSUPPORT: Requested transport type not supported
+ * Return local xprt port on success or %-EPROTONOSUPPORT on failure
  */
 int svc_xprt_create(struct svc_serv *serv, const char *xprt_name,
                    struct net *net, const int family,
                    const unsigned short port, int flags,
                    const struct cred *cred)
 {
-       int err;
+       struct sockaddr_in sin = {
+               .sin_family             = AF_INET,
+               .sin_addr.s_addr        = htonl(INADDR_ANY),
+               .sin_port               = htons(port),
+       };
+#if IS_ENABLED(CONFIG_IPV6)
+       struct sockaddr_in6 sin6 = {
+               .sin6_family            = AF_INET6,
+               .sin6_addr              = IN6ADDR_ANY_INIT,
+               .sin6_port              = htons(port),
+       };
+#endif
+       struct sockaddr *sap;
 
-       err = _svc_xprt_create(serv, xprt_name, net, family, port, flags, cred);
-       if (err == -EPROTONOSUPPORT) {
-               request_module("svc%s", xprt_name);
-               err = _svc_xprt_create(serv, xprt_name, net, family, port, flags, cred);
+       switch (family) {
+       case PF_INET:
+               sap = (struct sockaddr *)&sin;
+               break;
+#if IS_ENABLED(CONFIG_IPV6)
+       case PF_INET6:
+               sap = (struct sockaddr *)&sin6;
+               break;
+#endif
+       default:
+               return -EAFNOSUPPORT;
        }
-       return err;
+
+       return svc_xprt_create_from_sa(serv, xprt_name, net, sap, flags, cred);
 }
 EXPORT_SYMBOL_GPL(svc_xprt_create);