diff options
author | Tom Tucker <tom@opengridcomputing.com> | 2007-12-30 22:07:36 -0500 |
---|---|---|
committer | J. Bruce Fields <bfields@citi.umich.edu> | 2008-02-01 16:42:08 -0500 |
commit | 38a417cc993f4535548e47207f9894e7c27e05e4 (patch) | |
tree | f8035bcf6bc9a4831b152f5556b14cb3b48a72b8 | |
parent | d7979ae4a050a45b78af51832475001b68263d2a (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.h | 1 | ||||
-rw-r--r-- | include/linux/sunrpc/svcsock.h | 1 | ||||
-rw-r--r-- | net/sunrpc/svcsock.c | 31 |
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 | ||
12 | struct svc_xprt_ops { | 12 | struct 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 | ||
899 | static struct svc_xprt *svc_udp_accept(struct svc_xprt *xprt) | ||
900 | { | ||
901 | BUG(); | ||
902 | return NULL; | ||
903 | } | ||
904 | |||
899 | static struct svc_xprt_ops svc_udp_ops = { | 905 | static 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 | ||
909 | static struct svc_xprt_class svc_udp_class = { | 916 | static 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 | */ |
1031 | static void | 1038 | static struct svc_xprt *svc_tcp_accept(struct svc_xprt *xprt) |
1032 | svc_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 | ||
1152 | failed: | 1159 | failed: |
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 | ||
1398 | static struct svc_xprt_class svc_tcp_class = { | 1400 | static 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)); |