aboutsummaryrefslogtreecommitdiffstats
path: root/net
diff options
context:
space:
mode:
Diffstat (limited to 'net')
-rw-r--r--net/sunrpc/svcsock.c82
1 files changed, 56 insertions, 26 deletions
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 = {