diff options
Diffstat (limited to 'net/sunrpc/svcsock.c')
-rw-r--r-- | net/sunrpc/svcsock.c | 82 |
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 | */ | ||
210 | static inline unsigned long | ||
211 | svc_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 | ||
886 | static 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 | |||
900 | static struct svc_xprt_ops svc_udp_ops = { | 904 | static 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 | ||
909 | static struct svc_xprt_class svc_udp_class = { | 914 | static 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 | ||
1374 | static 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 | |||
1369 | static struct svc_xprt_ops svc_tcp_ops = { | 1398 | static 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 | ||
1378 | static struct svc_xprt_class svc_tcp_class = { | 1408 | static struct svc_xprt_class svc_tcp_class = { |