diff options
Diffstat (limited to 'net/sunrpc/svcsock.c')
-rw-r--r-- | net/sunrpc/svcsock.c | 50 |
1 files changed, 32 insertions, 18 deletions
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index b507cd327d9b..c24a8ff33f8f 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
@@ -446,15 +446,43 @@ static void svc_write_space(struct sock *sk) | |||
446 | } | 446 | } |
447 | } | 447 | } |
448 | 448 | ||
449 | static int svc_tcp_has_wspace(struct svc_xprt *xprt) | ||
450 | { | ||
451 | struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt); | ||
452 | struct svc_serv *serv = svsk->sk_xprt.xpt_server; | ||
453 | int required; | ||
454 | |||
455 | if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) | ||
456 | return 1; | ||
457 | required = atomic_read(&xprt->xpt_reserved) + serv->sv_max_mesg; | ||
458 | if (sk_stream_wspace(svsk->sk_sk) >= required || | ||
459 | (sk_stream_min_wspace(svsk->sk_sk) == 0 && | ||
460 | atomic_read(&xprt->xpt_reserved) == 0)) | ||
461 | return 1; | ||
462 | set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags); | ||
463 | return 0; | ||
464 | } | ||
465 | |||
449 | static void svc_tcp_write_space(struct sock *sk) | 466 | static void svc_tcp_write_space(struct sock *sk) |
450 | { | 467 | { |
468 | struct svc_sock *svsk = (struct svc_sock *)(sk->sk_user_data); | ||
451 | struct socket *sock = sk->sk_socket; | 469 | struct socket *sock = sk->sk_socket; |
452 | 470 | ||
453 | if (sk_stream_is_writeable(sk) && sock) | 471 | if (!sk_stream_is_writeable(sk) || !sock) |
472 | return; | ||
473 | if (!svsk || svc_tcp_has_wspace(&svsk->sk_xprt)) | ||
454 | clear_bit(SOCK_NOSPACE, &sock->flags); | 474 | clear_bit(SOCK_NOSPACE, &sock->flags); |
455 | svc_write_space(sk); | 475 | svc_write_space(sk); |
456 | } | 476 | } |
457 | 477 | ||
478 | static void svc_tcp_adjust_wspace(struct svc_xprt *xprt) | ||
479 | { | ||
480 | struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt); | ||
481 | |||
482 | if (svc_tcp_has_wspace(xprt)) | ||
483 | clear_bit(SOCK_NOSPACE, &svsk->sk_sock->flags); | ||
484 | } | ||
485 | |||
458 | /* | 486 | /* |
459 | * See net/ipv6/ip_sockglue.c : ip_cmsg_recv_pktinfo | 487 | * See net/ipv6/ip_sockglue.c : ip_cmsg_recv_pktinfo |
460 | */ | 488 | */ |
@@ -692,6 +720,7 @@ static struct svc_xprt_class svc_udp_class = { | |||
692 | .xcl_owner = THIS_MODULE, | 720 | .xcl_owner = THIS_MODULE, |
693 | .xcl_ops = &svc_udp_ops, | 721 | .xcl_ops = &svc_udp_ops, |
694 | .xcl_max_payload = RPCSVC_MAXPAYLOAD_UDP, | 722 | .xcl_max_payload = RPCSVC_MAXPAYLOAD_UDP, |
723 | .xcl_ident = XPRT_TRANSPORT_UDP, | ||
695 | }; | 724 | }; |
696 | 725 | ||
697 | static void svc_udp_init(struct svc_sock *svsk, struct svc_serv *serv) | 726 | static void svc_udp_init(struct svc_sock *svsk, struct svc_serv *serv) |
@@ -1197,23 +1226,6 @@ static void svc_tcp_prep_reply_hdr(struct svc_rqst *rqstp) | |||
1197 | svc_putnl(resv, 0); | 1226 | svc_putnl(resv, 0); |
1198 | } | 1227 | } |
1199 | 1228 | ||
1200 | static int svc_tcp_has_wspace(struct svc_xprt *xprt) | ||
1201 | { | ||
1202 | struct svc_sock *svsk = container_of(xprt, struct svc_sock, sk_xprt); | ||
1203 | struct svc_serv *serv = svsk->sk_xprt.xpt_server; | ||
1204 | int required; | ||
1205 | |||
1206 | if (test_bit(XPT_LISTENER, &xprt->xpt_flags)) | ||
1207 | return 1; | ||
1208 | required = atomic_read(&xprt->xpt_reserved) + serv->sv_max_mesg; | ||
1209 | if (sk_stream_wspace(svsk->sk_sk) >= required || | ||
1210 | (sk_stream_min_wspace(svsk->sk_sk) == 0 && | ||
1211 | atomic_read(&xprt->xpt_reserved) == 0)) | ||
1212 | return 1; | ||
1213 | set_bit(SOCK_NOSPACE, &svsk->sk_sock->flags); | ||
1214 | return 0; | ||
1215 | } | ||
1216 | |||
1217 | static struct svc_xprt *svc_tcp_create(struct svc_serv *serv, | 1229 | static struct svc_xprt *svc_tcp_create(struct svc_serv *serv, |
1218 | struct net *net, | 1230 | struct net *net, |
1219 | struct sockaddr *sa, int salen, | 1231 | struct sockaddr *sa, int salen, |
@@ -1285,6 +1297,7 @@ static struct svc_xprt_ops svc_tcp_ops = { | |||
1285 | .xpo_has_wspace = svc_tcp_has_wspace, | 1297 | .xpo_has_wspace = svc_tcp_has_wspace, |
1286 | .xpo_accept = svc_tcp_accept, | 1298 | .xpo_accept = svc_tcp_accept, |
1287 | .xpo_secure_port = svc_sock_secure_port, | 1299 | .xpo_secure_port = svc_sock_secure_port, |
1300 | .xpo_adjust_wspace = svc_tcp_adjust_wspace, | ||
1288 | }; | 1301 | }; |
1289 | 1302 | ||
1290 | static struct svc_xprt_class svc_tcp_class = { | 1303 | static struct svc_xprt_class svc_tcp_class = { |
@@ -1292,6 +1305,7 @@ static struct svc_xprt_class svc_tcp_class = { | |||
1292 | .xcl_owner = THIS_MODULE, | 1305 | .xcl_owner = THIS_MODULE, |
1293 | .xcl_ops = &svc_tcp_ops, | 1306 | .xcl_ops = &svc_tcp_ops, |
1294 | .xcl_max_payload = RPCSVC_MAXPAYLOAD_TCP, | 1307 | .xcl_max_payload = RPCSVC_MAXPAYLOAD_TCP, |
1308 | .xcl_ident = XPRT_TRANSPORT_TCP, | ||
1295 | }; | 1309 | }; |
1296 | 1310 | ||
1297 | void svc_init_xprt_sock(void) | 1311 | void svc_init_xprt_sock(void) |