Add transport function that makes the creation of a listening endpoint 
transport independent.

Signed-off-by: Tom Tucker <[EMAIL PROTECTED]>
---

 include/linux/sunrpc/svcsock.h |    5 +++
 net/sunrpc/svcsock.c           |   65 +++++++++++++++++++++++++++++++++++++---
 2 files changed, 65 insertions(+), 5 deletions(-)

diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h
index cc911ab..e2d0256 100644
--- a/include/linux/sunrpc/svcsock.h
+++ b/include/linux/sunrpc/svcsock.h
@@ -14,6 +14,10 @@ #include <linux/sunrpc/svc.h>
 struct svc_xprt {
        const char              *xpt_name;
        struct module           *xpt_owner;
+       /* Create an svc socket for this transport */
+       int                     (*xpt_create_svc)(struct svc_serv *,
+                                                 struct sockaddr *,
+                                                 int);
        int                     (*xpt_recvfrom)(struct svc_rqst *rqstp);
        int                     (*xpt_sendto)(struct svc_rqst *rqstp);
        /*
@@ -109,6 +113,7 @@ #define     SK_LISTENER     11                      /* 
listener (e.
 int            svc_register_transport(struct svc_xprt *xprt);
 int            svc_unregister_transport(struct svc_xprt *xprt);
 int            svc_makesock(struct svc_serv *, int, unsigned short, int flags);
+int            svc_create_svcsock(struct svc_serv *, char *, unsigned short, 
int);
 void           svc_force_close_socket(struct svc_sock *);
 int            svc_recv(struct svc_rqst *, long);
 int            svc_send(struct svc_rqst *);
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 276737e..44d6484 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -87,6 +87,8 @@ static void           svc_close_socket(struct svc
 static void            svc_sock_detach(struct svc_sock *);
 static void            svc_sock_free(struct svc_sock *);
 
+static int
+svc_create_socket(struct svc_serv *, int, struct sockaddr *, int, int);
 static struct svc_deferred_req *svc_deferred_dequeue(struct svc_sock *svsk);
 static int svc_deferred_recv(struct svc_rqst *rqstp);
 static struct cache_deferred_req *svc_defer(struct cache_req *req);
@@ -434,6 +436,7 @@ __svc_sock_put(struct svc_sock *svsk)
 
        if (svsk->sk_info_authunix != NULL)
                svcauth_unix_info_release(svsk->sk_info_authunix);
+       module_put(svsk->sk_xprt->xpt_owner);
        svsk->sk_xprt->xpt_free(svsk);
 }
 EXPORT_SYMBOL_GPL(__svc_sock_put);
@@ -961,9 +964,17 @@ svc_udp_has_wspace(struct svc_sock *svsk
        return svc_sock_has_write_space(svsk, sock_wspace(svsk->sk_sk));
 }
 
+static int
+svc_udp_create_svc(struct svc_serv *serv, struct sockaddr *sa, int flags)
+{
+       return svc_create_socket(serv, IPPROTO_UDP, sa,
+                                sizeof(struct sockaddr_in), flags);
+}
+
 static struct svc_xprt svc_udp_xprt = {
        .xpt_name = "udp",
        .xpt_owner = THIS_MODULE,
+       .xpt_create_svc = svc_udp_create_svc,
        .xpt_recvfrom = svc_udp_recvfrom,
        .xpt_sendto = svc_udp_sendto,
        .xpt_detach = svc_sock_detach,
@@ -1421,9 +1432,17 @@ svc_tcp_has_wspace(struct svc_sock *svsk
        return svc_sock_has_write_space(svsk, sk_stream_wspace(svsk->sk_sk));
 }
 
+static int
+svc_tcp_create_svc(struct svc_serv *serv, struct sockaddr *sa, int flags)
+{
+       return svc_create_socket(serv, IPPROTO_TCP, sa,
+                                sizeof(struct sockaddr_in), flags);
+}
+
 static struct svc_xprt svc_tcp_xprt = {
        .xpt_name = "tcp",
        .xpt_owner = THIS_MODULE,
+       .xpt_create_svc = svc_tcp_create_svc,
        .xpt_recvfrom = svc_tcp_recvfrom,
        .xpt_sendto = svc_tcp_sendto,
        .xpt_detach = svc_sock_detach,
@@ -1606,6 +1625,7 @@ svc_recv(struct svc_rqst *rqstp, long ti
                svc_delete_socket(svsk);
        } else if (test_bit(SK_LISTENER, &svsk->sk_flags)) {
                svsk->sk_xprt->xpt_accept(svsk);
+               __module_get(svsk->sk_xprt->xpt_owner);
                svc_sock_received(svsk);
        } else {
                dprintk("svc: server %p, pool %u, socket %p, inuse=%d\n",
@@ -1885,7 +1905,7 @@ EXPORT_SYMBOL_GPL(svc_addsock);
  * Create socket for RPC service.
  */
 static int svc_create_socket(struct svc_serv *serv, int protocol,
-                               struct sockaddr *sin, int len, int flags)
+                            struct sockaddr *sin, int len, int flags)
 {
        struct svc_sock *svsk;
        struct socket   *sock;
@@ -2037,18 +2057,53 @@ void svc_force_close_socket(struct svc_s
  *
  */
 int svc_makesock(struct svc_serv *serv, int protocol, unsigned short port,
-                       int flags)
+                int flags)
 {
+       dprintk("svc: creating socket proto = %d\n", protocol);
+       switch (protocol) {
+       case IPPROTO_TCP:
+               return svc_create_svcsock(serv, "tcp", port, flags);
+       case IPPROTO_UDP:
+               return svc_create_svcsock(serv, "udp", port, flags);
+       default:
+               return -EINVAL;
+       }
+}
+
+int svc_create_svcsock(struct svc_serv *serv, char *transport, unsigned short 
port,
+                      int flags)
+{
+       int ret = -ENOENT;
+       struct list_head *le;
        struct sockaddr_in sin = {
                .sin_family             = AF_INET,
                .sin_addr.s_addr        = INADDR_ANY,
                .sin_port               = htons(port),
        };
+       dprintk("svc: creating transport socket %s[%d]\n", transport, port);
+       spin_lock(&svc_transport_lock);
+       list_for_each(le, &svc_transport_list) {
+               struct svc_xprt *xprt =
+                       list_entry(le, struct svc_xprt, xpt_list);
 
-       dprintk("svc: creating socket proto = %d\n", protocol);
-       return svc_create_socket(serv, protocol, (struct sockaddr *) &sin,
-                                                       sizeof(sin), flags);
+               if (strcmp(transport, xprt->xpt_name)==0) {
+                       spin_unlock(&svc_transport_lock);
+                       if (try_module_get(xprt->xpt_owner)) {
+                               ret = xprt->xpt_create_svc(serv,
+                                                          (struct 
sockaddr*)&sin,
+                                                          flags);
+                               if (ret < 0)
+                                       module_put(xprt->xpt_owner);
+                               goto out;
+                       }
+               }
+       }
+       spin_unlock(&svc_transport_lock);
+       dprintk("svc: transport %s not found\n", transport);
+ out:
+       return ret;
 }
+EXPORT_SYMBOL_GPL(svc_create_svcsock);
 
 /*
  * Handle defer and revisit of requests
_______________________________________________
general mailing list
general@lists.openfabrics.org
http://lists.openfabrics.org/cgi-bin/mailman/listinfo/general

To unsubscribe, please visit http://openib.org/mailman/listinfo/openib-general

Reply via email to