aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/sunrpc/svc_xprt.h4
-rw-r--r--net/sunrpc/svc_xprt.c37
-rw-r--r--net/sunrpc/svcsock.c59
3 files changed, 85 insertions, 15 deletions
diff --git a/include/linux/sunrpc/svc_xprt.h b/include/linux/sunrpc/svc_xprt.h
index 31a44f441fd1..986a5a07044b 100644
--- a/include/linux/sunrpc/svc_xprt.h
+++ b/include/linux/sunrpc/svc_xprt.h
@@ -10,6 +10,9 @@
10#include <linux/sunrpc/svc.h> 10#include <linux/sunrpc/svc.h>
11 11
12struct svc_xprt_ops { 12struct svc_xprt_ops {
13 struct svc_xprt *(*xpo_create)(struct svc_serv *,
14 struct sockaddr *, int,
15 int);
13 struct svc_xprt *(*xpo_accept)(struct svc_xprt *); 16 struct svc_xprt *(*xpo_accept)(struct svc_xprt *);
14 int (*xpo_has_wspace)(struct svc_xprt *); 17 int (*xpo_has_wspace)(struct svc_xprt *);
15 int (*xpo_recvfrom)(struct svc_rqst *); 18 int (*xpo_recvfrom)(struct svc_rqst *);
@@ -36,5 +39,6 @@ struct svc_xprt {
36int svc_reg_xprt_class(struct svc_xprt_class *); 39int svc_reg_xprt_class(struct svc_xprt_class *);
37void svc_unreg_xprt_class(struct svc_xprt_class *); 40void svc_unreg_xprt_class(struct svc_xprt_class *);
38void svc_xprt_init(struct svc_xprt_class *, struct svc_xprt *); 41void svc_xprt_init(struct svc_xprt_class *, struct svc_xprt *);
42int svc_create_xprt(struct svc_serv *, char *, unsigned short, int);
39 43
40#endif /* SUNRPC_SVC_XPRT_H */ 44#endif /* SUNRPC_SVC_XPRT_H */
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index fe5270fae336..6ff5ca71602f 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -81,3 +81,40 @@ void svc_xprt_init(struct svc_xprt_class *xcl, struct svc_xprt *xprt)
81 xprt->xpt_ops = xcl->xcl_ops; 81 xprt->xpt_ops = xcl->xcl_ops;
82} 82}
83EXPORT_SYMBOL_GPL(svc_xprt_init); 83EXPORT_SYMBOL_GPL(svc_xprt_init);
84
85int svc_create_xprt(struct svc_serv *serv, char *xprt_name, unsigned short port,
86 int flags)
87{
88 struct svc_xprt_class *xcl;
89 int ret = -ENOENT;
90 struct sockaddr_in sin = {
91 .sin_family = AF_INET,
92 .sin_addr.s_addr = INADDR_ANY,
93 .sin_port = htons(port),
94 };
95 dprintk("svc: creating transport %s[%d]\n", xprt_name, port);
96 spin_lock(&svc_xprt_class_lock);
97 list_for_each_entry(xcl, &svc_xprt_class_list, xcl_list) {
98 if (strcmp(xprt_name, xcl->xcl_name) == 0) {
99 spin_unlock(&svc_xprt_class_lock);
100 if (try_module_get(xcl->xcl_owner)) {
101 struct svc_xprt *newxprt;
102 ret = 0;
103 newxprt = xcl->xcl_ops->xpo_create
104 (serv,
105 (struct sockaddr *)&sin, sizeof(sin),
106 flags);
107 if (IS_ERR(newxprt)) {
108 module_put(xcl->xcl_owner);
109 ret = PTR_ERR(newxprt);
110 }
111 }
112 goto out;
113 }
114 }
115 spin_unlock(&svc_xprt_class_lock);
116 dprintk("svc: transport %s not found\n", xprt_name);
117 out:
118 return ret;
119}
120EXPORT_SYMBOL_GPL(svc_create_xprt);
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 6e9dc8f96495..9f0f6d088969 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -91,6 +91,8 @@ static void svc_sock_free(struct svc_xprt *);
91static struct svc_deferred_req *svc_deferred_dequeue(struct svc_sock *svsk); 91static struct svc_deferred_req *svc_deferred_dequeue(struct svc_sock *svsk);
92static int svc_deferred_recv(struct svc_rqst *rqstp); 92static int svc_deferred_recv(struct svc_rqst *rqstp);
93static struct cache_deferred_req *svc_defer(struct cache_req *req); 93static struct cache_deferred_req *svc_defer(struct cache_req *req);
94static struct svc_xprt *svc_create_socket(struct svc_serv *, int,
95 struct sockaddr *, int, int);
94 96
95/* apparently the "standard" is that clients close 97/* apparently the "standard" is that clients close
96 * idle connections after 5 minutes, servers after 98 * idle connections after 5 minutes, servers after
@@ -365,6 +367,7 @@ svc_sock_put(struct svc_sock *svsk)
365{ 367{
366 if (atomic_dec_and_test(&svsk->sk_inuse)) { 368 if (atomic_dec_and_test(&svsk->sk_inuse)) {
367 BUG_ON(!test_bit(SK_DEAD, &svsk->sk_flags)); 369 BUG_ON(!test_bit(SK_DEAD, &svsk->sk_flags));
370 module_put(svsk->sk_xprt.xpt_class->xcl_owner);
368 svsk->sk_xprt.xpt_ops->xpo_free(&svsk->sk_xprt); 371 svsk->sk_xprt.xpt_ops->xpo_free(&svsk->sk_xprt);
369 } 372 }
370} 373}
@@ -902,7 +905,15 @@ static struct svc_xprt *svc_udp_accept(struct svc_xprt *xprt)
902 return NULL; 905 return NULL;
903} 906}
904 907
908static struct svc_xprt *svc_udp_create(struct svc_serv *serv,
909 struct sockaddr *sa, int salen,
910 int flags)
911{
912 return svc_create_socket(serv, IPPROTO_UDP, sa, salen, flags);
913}
914
905static struct svc_xprt_ops svc_udp_ops = { 915static struct svc_xprt_ops svc_udp_ops = {
916 .xpo_create = svc_udp_create,
906 .xpo_recvfrom = svc_udp_recvfrom, 917 .xpo_recvfrom = svc_udp_recvfrom,
907 .xpo_sendto = svc_udp_sendto, 918 .xpo_sendto = svc_udp_sendto,
908 .xpo_release_rqst = svc_release_skb, 919 .xpo_release_rqst = svc_release_skb,
@@ -915,6 +926,7 @@ static struct svc_xprt_ops svc_udp_ops = {
915 926
916static struct svc_xprt_class svc_udp_class = { 927static struct svc_xprt_class svc_udp_class = {
917 .xcl_name = "udp", 928 .xcl_name = "udp",
929 .xcl_owner = THIS_MODULE,
918 .xcl_ops = &svc_udp_ops, 930 .xcl_ops = &svc_udp_ops,
919 .xcl_max_payload = RPCSVC_MAXPAYLOAD_UDP, 931 .xcl_max_payload = RPCSVC_MAXPAYLOAD_UDP,
920}; 932};
@@ -1384,7 +1396,15 @@ static int svc_tcp_has_wspace(struct svc_xprt *xprt)
1384 return 1; 1396 return 1;
1385} 1397}
1386 1398
1399static struct svc_xprt *svc_tcp_create(struct svc_serv *serv,
1400 struct sockaddr *sa, int salen,
1401 int flags)
1402{
1403 return svc_create_socket(serv, IPPROTO_TCP, sa, salen, flags);
1404}
1405
1387static struct svc_xprt_ops svc_tcp_ops = { 1406static struct svc_xprt_ops svc_tcp_ops = {
1407 .xpo_create = svc_tcp_create,
1388 .xpo_recvfrom = svc_tcp_recvfrom, 1408 .xpo_recvfrom = svc_tcp_recvfrom,
1389 .xpo_sendto = svc_tcp_sendto, 1409 .xpo_sendto = svc_tcp_sendto,
1390 .xpo_release_rqst = svc_release_skb, 1410 .xpo_release_rqst = svc_release_skb,
@@ -1397,6 +1417,7 @@ static struct svc_xprt_ops svc_tcp_ops = {
1397 1417
1398static struct svc_xprt_class svc_tcp_class = { 1418static struct svc_xprt_class svc_tcp_class = {
1399 .xcl_name = "tcp", 1419 .xcl_name = "tcp",
1420 .xcl_owner = THIS_MODULE,
1400 .xcl_ops = &svc_tcp_ops, 1421 .xcl_ops = &svc_tcp_ops,
1401 .xcl_max_payload = RPCSVC_MAXPAYLOAD_TCP, 1422 .xcl_max_payload = RPCSVC_MAXPAYLOAD_TCP,
1402}; 1423};
@@ -1573,8 +1594,14 @@ svc_recv(struct svc_rqst *rqstp, long timeout)
1573 } else if (test_bit(SK_LISTENER, &svsk->sk_flags)) { 1594 } else if (test_bit(SK_LISTENER, &svsk->sk_flags)) {
1574 struct svc_xprt *newxpt; 1595 struct svc_xprt *newxpt;
1575 newxpt = svsk->sk_xprt.xpt_ops->xpo_accept(&svsk->sk_xprt); 1596 newxpt = svsk->sk_xprt.xpt_ops->xpo_accept(&svsk->sk_xprt);
1576 if (newxpt) 1597 if (newxpt) {
1598 /*
1599 * We know this module_get will succeed because the
1600 * listener holds a reference too
1601 */
1602 __module_get(newxpt->xpt_class->xcl_owner);
1577 svc_check_conn_limits(svsk->sk_server); 1603 svc_check_conn_limits(svsk->sk_server);
1604 }
1578 svc_sock_received(svsk); 1605 svc_sock_received(svsk);
1579 } else { 1606 } else {
1580 dprintk("svc: server %p, pool %u, socket %p, inuse=%d\n", 1607 dprintk("svc: server %p, pool %u, socket %p, inuse=%d\n",
@@ -1814,8 +1841,10 @@ EXPORT_SYMBOL_GPL(svc_addsock);
1814/* 1841/*
1815 * Create socket for RPC service. 1842 * Create socket for RPC service.
1816 */ 1843 */
1817static int svc_create_socket(struct svc_serv *serv, int protocol, 1844static struct svc_xprt *svc_create_socket(struct svc_serv *serv,
1818 struct sockaddr *sin, int len, int flags) 1845 int protocol,
1846 struct sockaddr *sin, int len,
1847 int flags)
1819{ 1848{
1820 struct svc_sock *svsk; 1849 struct svc_sock *svsk;
1821 struct socket *sock; 1850 struct socket *sock;
@@ -1830,13 +1859,13 @@ static int svc_create_socket(struct svc_serv *serv, int protocol,
1830 if (protocol != IPPROTO_UDP && protocol != IPPROTO_TCP) { 1859 if (protocol != IPPROTO_UDP && protocol != IPPROTO_TCP) {
1831 printk(KERN_WARNING "svc: only UDP and TCP " 1860 printk(KERN_WARNING "svc: only UDP and TCP "
1832 "sockets supported\n"); 1861 "sockets supported\n");
1833 return -EINVAL; 1862 return ERR_PTR(-EINVAL);
1834 } 1863 }
1835 type = (protocol == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM; 1864 type = (protocol == IPPROTO_UDP)? SOCK_DGRAM : SOCK_STREAM;
1836 1865
1837 error = sock_create_kern(sin->sa_family, type, protocol, &sock); 1866 error = sock_create_kern(sin->sa_family, type, protocol, &sock);
1838 if (error < 0) 1867 if (error < 0)
1839 return error; 1868 return ERR_PTR(error);
1840 1869
1841 svc_reclassify_socket(sock); 1870 svc_reclassify_socket(sock);
1842 1871
@@ -1853,13 +1882,13 @@ static int svc_create_socket(struct svc_serv *serv, int protocol,
1853 1882
1854 if ((svsk = svc_setup_socket(serv, sock, &error, flags)) != NULL) { 1883 if ((svsk = svc_setup_socket(serv, sock, &error, flags)) != NULL) {
1855 svc_sock_received(svsk); 1884 svc_sock_received(svsk);
1856 return ntohs(inet_sk(svsk->sk_sk)->sport); 1885 return (struct svc_xprt *)svsk;
1857 } 1886 }
1858 1887
1859bummer: 1888bummer:
1860 dprintk("svc: svc_create_socket error = %d\n", -error); 1889 dprintk("svc: svc_create_socket error = %d\n", -error);
1861 sock_release(sock); 1890 sock_release(sock);
1862 return error; 1891 return ERR_PTR(error);
1863} 1892}
1864 1893
1865/* 1894/*
@@ -1970,15 +1999,15 @@ void svc_force_close_socket(struct svc_sock *svsk)
1970int svc_makesock(struct svc_serv *serv, int protocol, unsigned short port, 1999int svc_makesock(struct svc_serv *serv, int protocol, unsigned short port,
1971 int flags) 2000 int flags)
1972{ 2001{
1973 struct sockaddr_in sin = {
1974 .sin_family = AF_INET,
1975 .sin_addr.s_addr = INADDR_ANY,
1976 .sin_port = htons(port),
1977 };
1978
1979 dprintk("svc: creating socket proto = %d\n", protocol); 2002 dprintk("svc: creating socket proto = %d\n", protocol);
1980 return svc_create_socket(serv, protocol, (struct sockaddr *) &sin, 2003 switch (protocol) {
1981 sizeof(sin), flags); 2004 case IPPROTO_TCP:
2005 return svc_create_xprt(serv, "tcp", port, flags);
2006 case IPPROTO_UDP:
2007 return svc_create_xprt(serv, "udp", port, flags);
2008 default:
2009 return -EINVAL;
2010 }
1982} 2011}
1983 2012
1984/* 2013/*