aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Tucker <tom@opengridcomputing.com>2007-12-30 22:07:36 -0500
committerJ. Bruce Fields <bfields@citi.umich.edu>2008-02-01 16:42:08 -0500
commit38a417cc993f4535548e47207f9894e7c27e05e4 (patch)
treef8035bcf6bc9a4831b152f5556b14cb3b48a72b8
parentd7979ae4a050a45b78af51832475001b68263d2a (diff)
svc: Add xpo_accept transport function
Previously, the accept logic looked into the socket state to determine whether to call accept or recv when data-ready was indicated on an endpoint. Since some transports don't use sockets, this logic now uses a flag bit (SK_LISTENER) to identify listening endpoints. A transport function (xpo_accept) allows each transport to define its own accept processing. A transport's initialization logic is reponsible for setting the SK_LISTENER bit. I didn't see any way to do this in transport independent logic since the passive side of a UDP connection doesn't listen and always recv's. In the svc_recv function, if the SK_LISTENER bit is set, the transport xpo_accept function is called to handle accept processing. Note that all functions are defined even if they don't make sense for a given transport. For example, accept doesn't mean anything for UDP. The function is defined anyway and bug checks if called. The UDP transport should never set the SK_LISTENER bit. Signed-off-by: Tom Tucker <tom@opengridcomputing.com> Acked-by: Neil Brown <neilb@suse.de> Reviewed-by: Chuck Lever <chuck.lever@oracle.com> Reviewed-by: Greg Banks <gnb@sgi.com> Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu>
-rw-r--r--include/linux/sunrpc/svc_xprt.h1
-rw-r--r--include/linux/sunrpc/svcsock.h1
-rw-r--r--net/sunrpc/svcsock.c31
3 files changed, 21 insertions, 12 deletions
diff --git a/include/linux/sunrpc/svc_xprt.h b/include/linux/sunrpc/svc_xprt.h
index 85df97acc2d0..31a44f441fd1 100644
--- a/include/linux/sunrpc/svc_xprt.h
+++ b/include/linux/sunrpc/svc_xprt.h
@@ -10,6 +10,7 @@
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_accept)(struct svc_xprt *);
13 int (*xpo_has_wspace)(struct svc_xprt *); 14 int (*xpo_has_wspace)(struct svc_xprt *);
14 int (*xpo_recvfrom)(struct svc_rqst *); 15 int (*xpo_recvfrom)(struct svc_rqst *);
15 void (*xpo_prep_reply_hdr)(struct svc_rqst *); 16 void (*xpo_prep_reply_hdr)(struct svc_rqst *);
diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h
index 08e78d0a364f..9882ce0ee33c 100644
--- a/include/linux/sunrpc/svcsock.h
+++ b/include/linux/sunrpc/svcsock.h
@@ -36,6 +36,7 @@ struct svc_sock {
36#define SK_DEFERRED 8 /* request on sk_deferred */ 36#define SK_DEFERRED 8 /* request on sk_deferred */
37#define SK_OLD 9 /* used for temp socket aging mark+sweep */ 37#define SK_OLD 9 /* used for temp socket aging mark+sweep */
38#define SK_DETACHED 10 /* detached from tempsocks list */ 38#define SK_DETACHED 10 /* detached from tempsocks list */
39#define SK_LISTENER 11 /* listening endpoint */
39 40
40 atomic_t sk_reserved; /* space on outq that is reserved */ 41 atomic_t sk_reserved; /* space on outq that is reserved */
41 42
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 603db98b8fca..41d1f815fbbd 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -896,6 +896,12 @@ static int svc_udp_has_wspace(struct svc_xprt *xprt)
896 return 1; 896 return 1;
897} 897}
898 898
899static struct svc_xprt *svc_udp_accept(struct svc_xprt *xprt)
900{
901 BUG();
902 return NULL;
903}
904
899static struct svc_xprt_ops svc_udp_ops = { 905static struct svc_xprt_ops svc_udp_ops = {
900 .xpo_recvfrom = svc_udp_recvfrom, 906 .xpo_recvfrom = svc_udp_recvfrom,
901 .xpo_sendto = svc_udp_sendto, 907 .xpo_sendto = svc_udp_sendto,
@@ -904,6 +910,7 @@ static struct svc_xprt_ops svc_udp_ops = {
904 .xpo_free = svc_sock_free, 910 .xpo_free = svc_sock_free,
905 .xpo_prep_reply_hdr = svc_udp_prep_reply_hdr, 911 .xpo_prep_reply_hdr = svc_udp_prep_reply_hdr,
906 .xpo_has_wspace = svc_udp_has_wspace, 912 .xpo_has_wspace = svc_udp_has_wspace,
913 .xpo_accept = svc_udp_accept,
907}; 914};
908 915
909static struct svc_xprt_class svc_udp_class = { 916static struct svc_xprt_class svc_udp_class = {
@@ -1028,9 +1035,9 @@ static inline int svc_port_is_privileged(struct sockaddr *sin)
1028/* 1035/*
1029 * Accept a TCP connection 1036 * Accept a TCP connection
1030 */ 1037 */
1031static void 1038static struct svc_xprt *svc_tcp_accept(struct svc_xprt *xprt)
1032svc_tcp_accept(struct svc_sock *svsk)
1033{ 1039{
1040 struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt);
1034 struct sockaddr_storage addr; 1041 struct sockaddr_storage addr;
1035 struct sockaddr *sin = (struct sockaddr *) &addr; 1042 struct sockaddr *sin = (struct sockaddr *) &addr;
1036 struct svc_serv *serv = svsk->sk_server; 1043 struct svc_serv *serv = svsk->sk_server;
@@ -1042,7 +1049,7 @@ svc_tcp_accept(struct svc_sock *svsk)
1042 1049
1043 dprintk("svc: tcp_accept %p sock %p\n", svsk, sock); 1050 dprintk("svc: tcp_accept %p sock %p\n", svsk, sock);
1044 if (!sock) 1051 if (!sock)
1045 return; 1052 return NULL;
1046 1053
1047 clear_bit(SK_CONN, &svsk->sk_flags); 1054 clear_bit(SK_CONN, &svsk->sk_flags);
1048 err = kernel_accept(sock, &newsock, O_NONBLOCK); 1055 err = kernel_accept(sock, &newsock, O_NONBLOCK);
@@ -1053,7 +1060,7 @@ svc_tcp_accept(struct svc_sock *svsk)
1053 else if (err != -EAGAIN && net_ratelimit()) 1060 else if (err != -EAGAIN && net_ratelimit())
1054 printk(KERN_WARNING "%s: accept failed (err %d)!\n", 1061 printk(KERN_WARNING "%s: accept failed (err %d)!\n",
1055 serv->sv_name, -err); 1062 serv->sv_name, -err);
1056 return; 1063 return NULL;
1057 } 1064 }
1058 1065
1059 set_bit(SK_CONN, &svsk->sk_flags); 1066 set_bit(SK_CONN, &svsk->sk_flags);
@@ -1147,11 +1154,11 @@ svc_tcp_accept(struct svc_sock *svsk)
1147 if (serv->sv_stats) 1154 if (serv->sv_stats)
1148 serv->sv_stats->nettcpconn++; 1155 serv->sv_stats->nettcpconn++;
1149 1156
1150 return; 1157 return &newsvsk->sk_xprt;
1151 1158
1152failed: 1159failed:
1153 sock_release(newsock); 1160 sock_release(newsock);
1154 return; 1161 return NULL;
1155} 1162}
1156 1163
1157/* 1164/*
@@ -1176,12 +1183,6 @@ svc_tcp_recvfrom(struct svc_rqst *rqstp)
1176 return svc_deferred_recv(rqstp); 1183 return svc_deferred_recv(rqstp);
1177 } 1184 }
1178 1185
1179 if (svsk->sk_sk->sk_state == TCP_LISTEN) {
1180 svc_tcp_accept(svsk);
1181 svc_sock_received(svsk);
1182 return 0;
1183 }
1184
1185 if (test_and_clear_bit(SK_CHNGBUF, &svsk->sk_flags)) 1186 if (test_and_clear_bit(SK_CHNGBUF, &svsk->sk_flags))
1186 /* sndbuf needs to have room for one request 1187 /* sndbuf needs to have room for one request
1187 * per thread, otherwise we can stall even when the 1188 * per thread, otherwise we can stall even when the
@@ -1393,6 +1394,7 @@ static struct svc_xprt_ops svc_tcp_ops = {
1393 .xpo_free = svc_sock_free, 1394 .xpo_free = svc_sock_free,
1394 .xpo_prep_reply_hdr = svc_tcp_prep_reply_hdr, 1395 .xpo_prep_reply_hdr = svc_tcp_prep_reply_hdr,
1395 .xpo_has_wspace = svc_tcp_has_wspace, 1396 .xpo_has_wspace = svc_tcp_has_wspace,
1397 .xpo_accept = svc_tcp_accept,
1396}; 1398};
1397 1399
1398static struct svc_xprt_class svc_tcp_class = { 1400static struct svc_xprt_class svc_tcp_class = {
@@ -1423,6 +1425,7 @@ svc_tcp_init(struct svc_sock *svsk)
1423 1425
1424 if (sk->sk_state == TCP_LISTEN) { 1426 if (sk->sk_state == TCP_LISTEN) {
1425 dprintk("setting up TCP socket for listening\n"); 1427 dprintk("setting up TCP socket for listening\n");
1428 set_bit(SK_LISTENER, &svsk->sk_flags);
1426 sk->sk_data_ready = svc_tcp_listen_data_ready; 1429 sk->sk_data_ready = svc_tcp_listen_data_ready;
1427 set_bit(SK_CONN, &svsk->sk_flags); 1430 set_bit(SK_CONN, &svsk->sk_flags);
1428 } else { 1431 } else {
@@ -1569,6 +1572,10 @@ svc_recv(struct svc_rqst *rqstp, long timeout)
1569 if (test_bit(SK_CLOSE, &svsk->sk_flags)) { 1572 if (test_bit(SK_CLOSE, &svsk->sk_flags)) {
1570 dprintk("svc_recv: found SK_CLOSE\n"); 1573 dprintk("svc_recv: found SK_CLOSE\n");
1571 svc_delete_socket(svsk); 1574 svc_delete_socket(svsk);
1575 } else if (test_bit(SK_LISTENER, &svsk->sk_flags)) {
1576 struct svc_xprt *newxpt;
1577 newxpt = svsk->sk_xprt.xpt_ops->xpo_accept(&svsk->sk_xprt);
1578 svc_sock_received(svsk);
1572 } else { 1579 } else {
1573 dprintk("svc: server %p, pool %u, socket %p, inuse=%d\n", 1580 dprintk("svc: server %p, pool %u, socket %p, inuse=%d\n",
1574 rqstp, pool->sp_id, svsk, atomic_read(&svsk->sk_inuse)); 1581 rqstp, pool->sp_id, svsk, atomic_read(&svsk->sk_inuse));