diff options
Diffstat (limited to 'net/sunrpc')
| -rw-r--r-- | net/sunrpc/clnt.c | 4 | ||||
| -rw-r--r-- | net/sunrpc/svcauth_unix.c | 21 | ||||
| -rw-r--r-- | net/sunrpc/svcsock.c | 20 | ||||
| -rw-r--r-- | net/sunrpc/xprt.c | 10 |
4 files changed, 34 insertions, 21 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c index 6d7221fe990a..396cdbe249d1 100644 --- a/net/sunrpc/clnt.c +++ b/net/sunrpc/clnt.c | |||
| @@ -1046,6 +1046,8 @@ call_status(struct rpc_task *task) | |||
| 1046 | rpc_delay(task, 3*HZ); | 1046 | rpc_delay(task, 3*HZ); |
| 1047 | case -ETIMEDOUT: | 1047 | case -ETIMEDOUT: |
| 1048 | task->tk_action = call_timeout; | 1048 | task->tk_action = call_timeout; |
| 1049 | if (task->tk_client->cl_discrtry) | ||
| 1050 | xprt_disconnect(task->tk_xprt); | ||
| 1049 | break; | 1051 | break; |
| 1050 | case -ECONNREFUSED: | 1052 | case -ECONNREFUSED: |
| 1051 | case -ENOTCONN: | 1053 | case -ENOTCONN: |
| @@ -1169,6 +1171,8 @@ call_decode(struct rpc_task *task) | |||
| 1169 | out_retry: | 1171 | out_retry: |
| 1170 | req->rq_received = req->rq_private_buf.len = 0; | 1172 | req->rq_received = req->rq_private_buf.len = 0; |
| 1171 | task->tk_status = 0; | 1173 | task->tk_status = 0; |
| 1174 | if (task->tk_client->cl_discrtry) | ||
| 1175 | xprt_disconnect(task->tk_xprt); | ||
| 1172 | } | 1176 | } |
| 1173 | 1177 | ||
| 1174 | /* | 1178 | /* |
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 9bae4090254c..2bd23ea2aa8b 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c | |||
| @@ -383,7 +383,10 @@ void svcauth_unix_purge(void) | |||
| 383 | static inline struct ip_map * | 383 | static inline struct ip_map * |
| 384 | ip_map_cached_get(struct svc_rqst *rqstp) | 384 | ip_map_cached_get(struct svc_rqst *rqstp) |
| 385 | { | 385 | { |
| 386 | struct ip_map *ipm = rqstp->rq_sock->sk_info_authunix; | 386 | struct ip_map *ipm; |
| 387 | struct svc_sock *svsk = rqstp->rq_sock; | ||
| 388 | spin_lock_bh(&svsk->sk_defer_lock); | ||
| 389 | ipm = svsk->sk_info_authunix; | ||
| 387 | if (ipm != NULL) { | 390 | if (ipm != NULL) { |
| 388 | if (!cache_valid(&ipm->h)) { | 391 | if (!cache_valid(&ipm->h)) { |
| 389 | /* | 392 | /* |
| @@ -391,12 +394,14 @@ ip_map_cached_get(struct svc_rqst *rqstp) | |||
| 391 | * remembered, e.g. by a second mount from the | 394 | * remembered, e.g. by a second mount from the |
| 392 | * same IP address. | 395 | * same IP address. |
| 393 | */ | 396 | */ |
| 394 | rqstp->rq_sock->sk_info_authunix = NULL; | 397 | svsk->sk_info_authunix = NULL; |
| 398 | spin_unlock_bh(&svsk->sk_defer_lock); | ||
| 395 | cache_put(&ipm->h, &ip_map_cache); | 399 | cache_put(&ipm->h, &ip_map_cache); |
| 396 | return NULL; | 400 | return NULL; |
| 397 | } | 401 | } |
| 398 | cache_get(&ipm->h); | 402 | cache_get(&ipm->h); |
| 399 | } | 403 | } |
| 404 | spin_unlock_bh(&svsk->sk_defer_lock); | ||
| 400 | return ipm; | 405 | return ipm; |
| 401 | } | 406 | } |
| 402 | 407 | ||
| @@ -405,9 +410,15 @@ ip_map_cached_put(struct svc_rqst *rqstp, struct ip_map *ipm) | |||
| 405 | { | 410 | { |
| 406 | struct svc_sock *svsk = rqstp->rq_sock; | 411 | struct svc_sock *svsk = rqstp->rq_sock; |
| 407 | 412 | ||
| 408 | if (svsk->sk_sock->type == SOCK_STREAM && svsk->sk_info_authunix == NULL) | 413 | spin_lock_bh(&svsk->sk_defer_lock); |
| 409 | svsk->sk_info_authunix = ipm; /* newly cached, keep the reference */ | 414 | if (svsk->sk_sock->type == SOCK_STREAM && |
| 410 | else | 415 | svsk->sk_info_authunix == NULL) { |
| 416 | /* newly cached, keep the reference */ | ||
| 417 | svsk->sk_info_authunix = ipm; | ||
| 418 | ipm = NULL; | ||
| 419 | } | ||
| 420 | spin_unlock_bh(&svsk->sk_defer_lock); | ||
| 421 | if (ipm) | ||
| 411 | cache_put(&ipm->h, &ip_map_cache); | 422 | cache_put(&ipm->h, &ip_map_cache); |
| 412 | } | 423 | } |
| 413 | 424 | ||
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index f6e1eb1ea720..2772fee93881 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c | |||
| @@ -452,6 +452,8 @@ union svc_pktinfo_u { | |||
| 452 | struct in_pktinfo pkti; | 452 | struct in_pktinfo pkti; |
| 453 | struct in6_pktinfo pkti6; | 453 | struct in6_pktinfo pkti6; |
| 454 | }; | 454 | }; |
| 455 | #define SVC_PKTINFO_SPACE \ | ||
| 456 | CMSG_SPACE(sizeof(union svc_pktinfo_u)) | ||
| 455 | 457 | ||
| 456 | static void svc_set_cmsg_data(struct svc_rqst *rqstp, struct cmsghdr *cmh) | 458 | static void svc_set_cmsg_data(struct svc_rqst *rqstp, struct cmsghdr *cmh) |
| 457 | { | 459 | { |
| @@ -491,8 +493,11 @@ svc_sendto(struct svc_rqst *rqstp, struct xdr_buf *xdr) | |||
| 491 | struct svc_sock *svsk = rqstp->rq_sock; | 493 | struct svc_sock *svsk = rqstp->rq_sock; |
| 492 | struct socket *sock = svsk->sk_sock; | 494 | struct socket *sock = svsk->sk_sock; |
| 493 | int slen; | 495 | int slen; |
| 494 | char buffer[CMSG_SPACE(sizeof(union svc_pktinfo_u))]; | 496 | union { |
| 495 | struct cmsghdr *cmh = (struct cmsghdr *)buffer; | 497 | struct cmsghdr hdr; |
| 498 | long all[SVC_PKTINFO_SPACE / sizeof(long)]; | ||
| 499 | } buffer; | ||
| 500 | struct cmsghdr *cmh = &buffer.hdr; | ||
| 496 | int len = 0; | 501 | int len = 0; |
| 497 | int result; | 502 | int result; |
| 498 | int size; | 503 | int size; |
| @@ -745,8 +750,11 @@ svc_udp_recvfrom(struct svc_rqst *rqstp) | |||
| 745 | struct svc_sock *svsk = rqstp->rq_sock; | 750 | struct svc_sock *svsk = rqstp->rq_sock; |
| 746 | struct svc_serv *serv = svsk->sk_server; | 751 | struct svc_serv *serv = svsk->sk_server; |
| 747 | struct sk_buff *skb; | 752 | struct sk_buff *skb; |
| 748 | char buffer[CMSG_SPACE(sizeof(union svc_pktinfo_u))]; | 753 | union { |
| 749 | struct cmsghdr *cmh = (struct cmsghdr *)buffer; | 754 | struct cmsghdr hdr; |
| 755 | long all[SVC_PKTINFO_SPACE / sizeof(long)]; | ||
| 756 | } buffer; | ||
| 757 | struct cmsghdr *cmh = &buffer.hdr; | ||
| 750 | int err, len; | 758 | int err, len; |
| 751 | struct msghdr msg = { | 759 | struct msghdr msg = { |
| 752 | .msg_name = svc_addr(rqstp), | 760 | .msg_name = svc_addr(rqstp), |
| @@ -779,8 +787,8 @@ svc_udp_recvfrom(struct svc_rqst *rqstp) | |||
| 779 | } | 787 | } |
| 780 | 788 | ||
| 781 | clear_bit(SK_DATA, &svsk->sk_flags); | 789 | clear_bit(SK_DATA, &svsk->sk_flags); |
| 782 | while ((err == kernel_recvmsg(svsk->sk_sock, &msg, NULL, | 790 | while ((err = kernel_recvmsg(svsk->sk_sock, &msg, NULL, |
| 783 | 0, 0, MSG_PEEK | MSG_DONTWAIT)) < 0 || | 791 | 0, 0, MSG_PEEK | MSG_DONTWAIT)) < 0 || |
| 784 | (skb = skb_recv_datagram(svsk->sk_sk, 0, 1, &err)) == NULL) { | 792 | (skb = skb_recv_datagram(svsk->sk_sk, 0, 1, &err)) == NULL) { |
| 785 | if (err == -EAGAIN) { | 793 | if (err == -EAGAIN) { |
| 786 | svc_sock_received(svsk); | 794 | svc_sock_received(svsk); |
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index ee6ffa01dfb1..456a14510308 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
| @@ -735,16 +735,6 @@ void xprt_transmit(struct rpc_task *task) | |||
| 735 | xprt_reset_majortimeo(req); | 735 | xprt_reset_majortimeo(req); |
| 736 | /* Turn off autodisconnect */ | 736 | /* Turn off autodisconnect */ |
| 737 | del_singleshot_timer_sync(&xprt->timer); | 737 | del_singleshot_timer_sync(&xprt->timer); |
| 738 | } else { | ||
| 739 | /* If all request bytes have been sent, | ||
| 740 | * then we must be retransmitting this one */ | ||
| 741 | if (!req->rq_bytes_sent) { | ||
| 742 | if (task->tk_client->cl_discrtry) { | ||
| 743 | xprt_disconnect(xprt); | ||
| 744 | task->tk_status = -ENOTCONN; | ||
| 745 | return; | ||
| 746 | } | ||
| 747 | } | ||
| 748 | } | 738 | } |
| 749 | } else if (!req->rq_bytes_sent) | 739 | } else if (!req->rq_bytes_sent) |
| 750 | return; | 740 | return; |
