aboutsummaryrefslogtreecommitdiffstats
path: root/net/sunrpc
diff options
context:
space:
mode:
Diffstat (limited to 'net/sunrpc')
-rw-r--r--net/sunrpc/clnt.c32
-rw-r--r--net/sunrpc/socklib.c5
-rw-r--r--net/sunrpc/svcsock.c9
3 files changed, 37 insertions, 9 deletions
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 702ede309b06..61c3abeaccae 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -55,6 +55,7 @@ static void call_bind(struct rpc_task *task);
55static void call_bind_status(struct rpc_task *task); 55static void call_bind_status(struct rpc_task *task);
56static void call_transmit(struct rpc_task *task); 56static void call_transmit(struct rpc_task *task);
57static void call_status(struct rpc_task *task); 57static void call_status(struct rpc_task *task);
58static void call_transmit_status(struct rpc_task *task);
58static void call_refresh(struct rpc_task *task); 59static void call_refresh(struct rpc_task *task);
59static void call_refreshresult(struct rpc_task *task); 60static void call_refreshresult(struct rpc_task *task);
60static void call_timeout(struct rpc_task *task); 61static void call_timeout(struct rpc_task *task);
@@ -672,6 +673,18 @@ call_allocate(struct rpc_task *task)
672 rpc_exit(task, -ERESTARTSYS); 673 rpc_exit(task, -ERESTARTSYS);
673} 674}
674 675
676static inline int
677rpc_task_need_encode(struct rpc_task *task)
678{
679 return task->tk_rqstp->rq_snd_buf.len == 0;
680}
681
682static inline void
683rpc_task_force_reencode(struct rpc_task *task)
684{
685 task->tk_rqstp->rq_snd_buf.len = 0;
686}
687
675/* 688/*
676 * 3. Encode arguments of an RPC call 689 * 3. Encode arguments of an RPC call
677 */ 690 */
@@ -867,12 +880,14 @@ call_transmit(struct rpc_task *task)
867 if (task->tk_status != 0) 880 if (task->tk_status != 0)
868 return; 881 return;
869 /* Encode here so that rpcsec_gss can use correct sequence number. */ 882 /* Encode here so that rpcsec_gss can use correct sequence number. */
870 if (task->tk_rqstp->rq_bytes_sent == 0) { 883 if (rpc_task_need_encode(task)) {
884 task->tk_rqstp->rq_bytes_sent = 0;
871 call_encode(task); 885 call_encode(task);
872 /* Did the encode result in an error condition? */ 886 /* Did the encode result in an error condition? */
873 if (task->tk_status != 0) 887 if (task->tk_status != 0)
874 goto out_nosend; 888 goto out_nosend;
875 } 889 }
890 task->tk_action = call_transmit_status;
876 xprt_transmit(task); 891 xprt_transmit(task);
877 if (task->tk_status < 0) 892 if (task->tk_status < 0)
878 return; 893 return;
@@ -884,6 +899,7 @@ call_transmit(struct rpc_task *task)
884out_nosend: 899out_nosend:
885 /* release socket write lock before attempting to handle error */ 900 /* release socket write lock before attempting to handle error */
886 xprt_abort_transmit(task); 901 xprt_abort_transmit(task);
902 rpc_task_force_reencode(task);
887} 903}
888 904
889/* 905/*
@@ -915,7 +931,6 @@ call_status(struct rpc_task *task)
915 break; 931 break;
916 case -ECONNREFUSED: 932 case -ECONNREFUSED:
917 case -ENOTCONN: 933 case -ENOTCONN:
918 req->rq_bytes_sent = 0;
919 if (clnt->cl_autobind) 934 if (clnt->cl_autobind)
920 clnt->cl_port = 0; 935 clnt->cl_port = 0;
921 task->tk_action = call_bind; 936 task->tk_action = call_bind;
@@ -937,7 +952,18 @@ call_status(struct rpc_task *task)
937} 952}
938 953
939/* 954/*
940 * 6a. Handle RPC timeout 955 * 6a. Handle transmission errors.
956 */
957static void
958call_transmit_status(struct rpc_task *task)
959{
960 if (task->tk_status != -EAGAIN)
961 rpc_task_force_reencode(task);
962 call_status(task);
963}
964
965/*
966 * 6b. Handle RPC timeout
941 * We do not release the request slot, so we keep using the 967 * We do not release the request slot, so we keep using the
942 * same XID for all retransmits. 968 * same XID for all retransmits.
943 */ 969 */
diff --git a/net/sunrpc/socklib.c b/net/sunrpc/socklib.c
index 8f97e90f36c8..eb330d4f66d6 100644
--- a/net/sunrpc/socklib.c
+++ b/net/sunrpc/socklib.c
@@ -6,6 +6,9 @@
6 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de> 6 * Copyright (C) 1995, 1996 Olaf Kirch <okir@monad.swb.de>
7 */ 7 */
8 8
9#include <linux/compiler.h>
10#include <linux/netdevice.h>
11#include <linux/skbuff.h>
9#include <linux/types.h> 12#include <linux/types.h>
10#include <linux/pagemap.h> 13#include <linux/pagemap.h>
11#include <linux/udp.h> 14#include <linux/udp.h>
@@ -165,6 +168,8 @@ int csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb)
165 return -1; 168 return -1;
166 if ((unsigned short)csum_fold(desc.csum)) 169 if ((unsigned short)csum_fold(desc.csum))
167 return -1; 170 return -1;
171 if (unlikely(skb->ip_summed == CHECKSUM_HW))
172 netdev_rx_csum_fault(skb->dev);
168 return 0; 173 return 0;
169no_checksum: 174no_checksum:
170 if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_bits) < 0) 175 if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_bits) < 0)
diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c
index f16e7cdd6150..e50e7cf43737 100644
--- a/net/sunrpc/svcsock.c
+++ b/net/sunrpc/svcsock.c
@@ -623,12 +623,9 @@ svc_udp_recvfrom(struct svc_rqst *rqstp)
623 /* we can use it in-place */ 623 /* we can use it in-place */
624 rqstp->rq_arg.head[0].iov_base = skb->data + sizeof(struct udphdr); 624 rqstp->rq_arg.head[0].iov_base = skb->data + sizeof(struct udphdr);
625 rqstp->rq_arg.head[0].iov_len = len; 625 rqstp->rq_arg.head[0].iov_len = len;
626 if (skb->ip_summed != CHECKSUM_UNNECESSARY) { 626 if (skb_checksum_complete(skb)) {
627 if ((unsigned short)csum_fold(skb_checksum(skb, 0, skb->len, skb->csum))) { 627 skb_free_datagram(svsk->sk_sk, skb);
628 skb_free_datagram(svsk->sk_sk, skb); 628 return 0;
629 return 0;
630 }
631 skb->ip_summed = CHECKSUM_UNNECESSARY;
632 } 629 }
633 rqstp->rq_skbuff = skb; 630 rqstp->rq_skbuff = skb;
634 } 631 }