aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Tucker <tom@opengridcomputing.com>2007-12-30 22:07:31 -0500
committerJ. Bruce Fields <bfields@citi.umich.edu>2008-02-01 16:42:08 -0500
commit323bee32e9bef14c6dd943ecc8e8cd373a9c94d9 (patch)
tree5779a724dfcbe3aee1f06d9eb989931d1dcfa163
parente831fe65b10199e1e301a7316c66d6ced133712d (diff)
svc: Add a transport function that checks for write space
In order to avoid blocking a service thread, the receive side checks to see if there is sufficient write space to reply to the request. Each transport has a different mechanism for determining if there is enough write space to reply. The code that checked for write space was coupled with code that checked for CLOSE and CONN. These checks have been broken out into separate statements to make the code easier to read. 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--net/sunrpc/svcsock.c82
2 files changed, 57 insertions, 26 deletions
diff --git a/include/linux/sunrpc/svc_xprt.h b/include/linux/sunrpc/svc_xprt.h
index 199cfcb9860b..85df97acc2d0 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 int (*xpo_has_wspace)(struct svc_xprt *);
13 int (*xpo_recvfrom)(struct svc_rqst *); 14 int (*xpo_recvfrom)(struct svc_rqst *);
14 void (*xpo_prep_reply_hdr)(struct svc_rqst *); 15 void (*xpo_prep_reply_hdr)(struct svc_rqst *);
15 int (*xpo_sendto)(struct svc_rqst *); 16 int (*xpo_sendto)(struct svc_rqst *);
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index 492a1dc544f3..2007881a5b26 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -205,22 +205,6 @@ static void svc_release_skb(struct svc_rqst *rqstp)
205} 205}
206 206
207/* 207/*
208 * Any space to write?
209 */
210static inline unsigned long
211svc_sock_wspace(struct svc_sock *svsk)
212{
213 int wspace;
214
215 if (svsk->sk_sock->type == SOCK_STREAM)
216 wspace = sk_stream_wspace(svsk->sk_sk);
217 else
218 wspace = sock_wspace(svsk->sk_sk);
219
220 return wspace;
221}
222
223/*
224 * Queue up a socket with data pending. If there are idle nfsd 208 * Queue up a socket with data pending. If there are idle nfsd
225 * processes, wake 'em up. 209 * processes, wake 'em up.
226 * 210 *
@@ -269,22 +253,24 @@ svc_sock_enqueue(struct svc_sock *svsk)
269 BUG_ON(svsk->sk_pool != NULL); 253 BUG_ON(svsk->sk_pool != NULL);
270 svsk->sk_pool = pool; 254 svsk->sk_pool = pool;
271 255
272 set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags); 256 /* Handle pending connection */
273 if (((atomic_read(&svsk->sk_reserved) + serv->sv_max_mesg)*2 257 if (test_bit(SK_CONN, &svsk->sk_flags))
274 > svc_sock_wspace(svsk)) 258 goto process;
275 && !test_bit(SK_CLOSE, &svsk->sk_flags) 259
276 && !test_bit(SK_CONN, &svsk->sk_flags)) { 260 /* Handle close in-progress */
261 if (test_bit(SK_CLOSE, &svsk->sk_flags))
262 goto process;
263
264 /* Check if we have space to reply to a request */
265 if (!svsk->sk_xprt.xpt_ops->xpo_has_wspace(&svsk->sk_xprt)) {
277 /* Don't enqueue while not enough space for reply */ 266 /* Don't enqueue while not enough space for reply */
278 dprintk("svc: socket %p no space, %d*2 > %ld, not enqueued\n", 267 dprintk("svc: no write space, socket %p not enqueued\n", svsk);
279 svsk->sk_sk, atomic_read(&svsk->sk_reserved)+serv->sv_max_mesg,
280 svc_sock_wspace(svsk));
281 svsk->sk_pool = NULL; 268 svsk->sk_pool = NULL;
282 clear_bit(SK_BUSY, &svsk->sk_flags); 269 clear_bit(SK_BUSY, &svsk->sk_flags);
283 goto out_unlock; 270 goto out_unlock;
284 } 271 }
285 clear_bit(SOCK_NOSPACE, &svsk->sk_sock->flags);
286
287 272
273 process:
288 if (!list_empty(&pool->sp_threads)) { 274 if (!list_empty(&pool->sp_threads)) {
289 rqstp = list_entry(pool->sp_threads.next, 275 rqstp = list_entry(pool->sp_threads.next,
290 struct svc_rqst, 276 struct svc_rqst,
@@ -897,6 +883,24 @@ static void svc_udp_prep_reply_hdr(struct svc_rqst *rqstp)
897{ 883{
898} 884}
899 885
886static int svc_udp_has_wspace(struct svc_xprt *xprt)
887{
888 struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt);
889 struct svc_serv *serv = svsk->sk_server;
890 unsigned long required;
891
892 /*
893 * Set the SOCK_NOSPACE flag before checking the available
894 * sock space.
895 */
896 set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags);
897 required = atomic_read(&svsk->sk_reserved) + serv->sv_max_mesg;
898 if (required*2 > sock_wspace(svsk->sk_sk))
899 return 0;
900 clear_bit(SOCK_NOSPACE, &svsk->sk_sock->flags);
901 return 1;
902}
903
900static struct svc_xprt_ops svc_udp_ops = { 904static struct svc_xprt_ops svc_udp_ops = {
901 .xpo_recvfrom = svc_udp_recvfrom, 905 .xpo_recvfrom = svc_udp_recvfrom,
902 .xpo_sendto = svc_udp_sendto, 906 .xpo_sendto = svc_udp_sendto,
@@ -904,6 +908,7 @@ static struct svc_xprt_ops svc_udp_ops = {
904 .xpo_detach = svc_sock_detach, 908 .xpo_detach = svc_sock_detach,
905 .xpo_free = svc_sock_free, 909 .xpo_free = svc_sock_free,
906 .xpo_prep_reply_hdr = svc_udp_prep_reply_hdr, 910 .xpo_prep_reply_hdr = svc_udp_prep_reply_hdr,
911 .xpo_has_wspace = svc_udp_has_wspace,
907}; 912};
908 913
909static struct svc_xprt_class svc_udp_class = { 914static struct svc_xprt_class svc_udp_class = {
@@ -1366,6 +1371,30 @@ static void svc_tcp_prep_reply_hdr(struct svc_rqst *rqstp)
1366 svc_putnl(resv, 0); 1371 svc_putnl(resv, 0);
1367} 1372}
1368 1373
1374static int svc_tcp_has_wspace(struct svc_xprt *xprt)
1375{
1376 struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt);
1377 struct svc_serv *serv = svsk->sk_server;
1378 int required;
1379 int wspace;
1380
1381 /*
1382 * Set the SOCK_NOSPACE flag before checking the available
1383 * sock space.
1384 */
1385 set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags);
1386 required = atomic_read(&svsk->sk_reserved) + serv->sv_max_mesg;
1387 wspace = sk_stream_wspace(svsk->sk_sk);
1388
1389 if (wspace < sk_stream_min_wspace(svsk->sk_sk))
1390 return 0;
1391 if (required * 2 > wspace)
1392 return 0;
1393
1394 clear_bit(SOCK_NOSPACE, &svsk->sk_sock->flags);
1395 return 1;
1396}
1397
1369static struct svc_xprt_ops svc_tcp_ops = { 1398static struct svc_xprt_ops svc_tcp_ops = {
1370 .xpo_recvfrom = svc_tcp_recvfrom, 1399 .xpo_recvfrom = svc_tcp_recvfrom,
1371 .xpo_sendto = svc_tcp_sendto, 1400 .xpo_sendto = svc_tcp_sendto,
@@ -1373,6 +1402,7 @@ static struct svc_xprt_ops svc_tcp_ops = {
1373 .xpo_detach = svc_sock_detach, 1402 .xpo_detach = svc_sock_detach,
1374 .xpo_free = svc_sock_free, 1403 .xpo_free = svc_sock_free,
1375 .xpo_prep_reply_hdr = svc_tcp_prep_reply_hdr, 1404 .xpo_prep_reply_hdr = svc_tcp_prep_reply_hdr,
1405 .xpo_has_wspace = svc_tcp_has_wspace,
1376}; 1406};
1377 1407
1378static struct svc_xprt_class svc_tcp_class = { 1408static struct svc_xprt_class svc_tcp_class = {