diff options
Diffstat (limited to 'net/sunrpc/xprt.c')
-rw-r--r-- | net/sunrpc/xprt.c | 26 |
1 files changed, 22 insertions, 4 deletions
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index c74a6bb94074..a180ed4952d6 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -725,7 +725,8 @@ csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb) | |||
725 | goto no_checksum; | 725 | goto no_checksum; |
726 | 726 | ||
727 | desc.csum = csum_partial(skb->data, desc.offset, skb->csum); | 727 | desc.csum = csum_partial(skb->data, desc.offset, skb->csum); |
728 | xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_and_csum_bits); | 728 | if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_and_csum_bits) < 0) |
729 | return -1; | ||
729 | if (desc.offset != skb->len) { | 730 | if (desc.offset != skb->len) { |
730 | unsigned int csum2; | 731 | unsigned int csum2; |
731 | csum2 = skb_checksum(skb, desc.offset, skb->len - desc.offset, 0); | 732 | csum2 = skb_checksum(skb, desc.offset, skb->len - desc.offset, 0); |
@@ -737,7 +738,8 @@ csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb) | |||
737 | return -1; | 738 | return -1; |
738 | return 0; | 739 | return 0; |
739 | no_checksum: | 740 | no_checksum: |
740 | xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_bits); | 741 | if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_bits) < 0) |
742 | return -1; | ||
741 | if (desc.count) | 743 | if (desc.count) |
742 | return -1; | 744 | return -1; |
743 | return 0; | 745 | return 0; |
@@ -907,6 +909,7 @@ tcp_read_request(struct rpc_xprt *xprt, skb_reader_t *desc) | |||
907 | struct rpc_rqst *req; | 909 | struct rpc_rqst *req; |
908 | struct xdr_buf *rcvbuf; | 910 | struct xdr_buf *rcvbuf; |
909 | size_t len; | 911 | size_t len; |
912 | int r; | ||
910 | 913 | ||
911 | /* Find and lock the request corresponding to this xid */ | 914 | /* Find and lock the request corresponding to this xid */ |
912 | spin_lock(&xprt->sock_lock); | 915 | spin_lock(&xprt->sock_lock); |
@@ -927,16 +930,30 @@ tcp_read_request(struct rpc_xprt *xprt, skb_reader_t *desc) | |||
927 | len = xprt->tcp_reclen - xprt->tcp_offset; | 930 | len = xprt->tcp_reclen - xprt->tcp_offset; |
928 | memcpy(&my_desc, desc, sizeof(my_desc)); | 931 | memcpy(&my_desc, desc, sizeof(my_desc)); |
929 | my_desc.count = len; | 932 | my_desc.count = len; |
930 | xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied, | 933 | r = xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied, |
931 | &my_desc, tcp_copy_data); | 934 | &my_desc, tcp_copy_data); |
932 | desc->count -= len; | 935 | desc->count -= len; |
933 | desc->offset += len; | 936 | desc->offset += len; |
934 | } else | 937 | } else |
935 | xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied, | 938 | r = xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied, |
936 | desc, tcp_copy_data); | 939 | desc, tcp_copy_data); |
937 | xprt->tcp_copied += len; | 940 | xprt->tcp_copied += len; |
938 | xprt->tcp_offset += len; | 941 | xprt->tcp_offset += len; |
939 | 942 | ||
943 | if (r < 0) { | ||
944 | /* Error when copying to the receive buffer, | ||
945 | * usually because we weren't able to allocate | ||
946 | * additional buffer pages. All we can do now | ||
947 | * is turn off XPRT_COPY_DATA, so the request | ||
948 | * will not receive any additional updates, | ||
949 | * and time out. | ||
950 | * Any remaining data from this record will | ||
951 | * be discarded. | ||
952 | */ | ||
953 | xprt->tcp_flags &= ~XPRT_COPY_DATA; | ||
954 | goto out; | ||
955 | } | ||
956 | |||
940 | if (xprt->tcp_copied == req->rq_private_buf.buflen) | 957 | if (xprt->tcp_copied == req->rq_private_buf.buflen) |
941 | xprt->tcp_flags &= ~XPRT_COPY_DATA; | 958 | xprt->tcp_flags &= ~XPRT_COPY_DATA; |
942 | else if (xprt->tcp_offset == xprt->tcp_reclen) { | 959 | else if (xprt->tcp_offset == xprt->tcp_reclen) { |
@@ -949,6 +966,7 @@ tcp_read_request(struct rpc_xprt *xprt, skb_reader_t *desc) | |||
949 | req->rq_task->tk_pid); | 966 | req->rq_task->tk_pid); |
950 | xprt_complete_rqst(xprt, req, xprt->tcp_copied); | 967 | xprt_complete_rqst(xprt, req, xprt->tcp_copied); |
951 | } | 968 | } |
969 | out: | ||
952 | spin_unlock(&xprt->sock_lock); | 970 | spin_unlock(&xprt->sock_lock); |
953 | tcp_check_recm(xprt); | 971 | tcp_check_recm(xprt); |
954 | } | 972 | } |