diff options
Diffstat (limited to 'net/sunrpc/xprt.c')
-rw-r--r-- | net/sunrpc/xprt.c | 71 |
1 files changed, 57 insertions, 14 deletions
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index c74a6bb94074..eca92405948f 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -569,8 +569,11 @@ void xprt_connect(struct rpc_task *task) | |||
569 | if (xprt->sock != NULL) | 569 | if (xprt->sock != NULL) |
570 | schedule_delayed_work(&xprt->sock_connect, | 570 | schedule_delayed_work(&xprt->sock_connect, |
571 | RPC_REESTABLISH_TIMEOUT); | 571 | RPC_REESTABLISH_TIMEOUT); |
572 | else | 572 | else { |
573 | schedule_work(&xprt->sock_connect); | 573 | schedule_work(&xprt->sock_connect); |
574 | if (!RPC_IS_ASYNC(task)) | ||
575 | flush_scheduled_work(); | ||
576 | } | ||
574 | } | 577 | } |
575 | return; | 578 | return; |
576 | out_write: | 579 | out_write: |
@@ -725,7 +728,8 @@ csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb) | |||
725 | goto no_checksum; | 728 | goto no_checksum; |
726 | 729 | ||
727 | desc.csum = csum_partial(skb->data, desc.offset, skb->csum); | 730 | desc.csum = csum_partial(skb->data, desc.offset, skb->csum); |
728 | xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_and_csum_bits); | 731 | if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_and_csum_bits) < 0) |
732 | return -1; | ||
729 | if (desc.offset != skb->len) { | 733 | if (desc.offset != skb->len) { |
730 | unsigned int csum2; | 734 | unsigned int csum2; |
731 | csum2 = skb_checksum(skb, desc.offset, skb->len - desc.offset, 0); | 735 | csum2 = skb_checksum(skb, desc.offset, skb->len - desc.offset, 0); |
@@ -737,7 +741,8 @@ csum_partial_copy_to_xdr(struct xdr_buf *xdr, struct sk_buff *skb) | |||
737 | return -1; | 741 | return -1; |
738 | return 0; | 742 | return 0; |
739 | no_checksum: | 743 | no_checksum: |
740 | xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_bits); | 744 | if (xdr_partial_copy_from_skb(xdr, 0, &desc, skb_read_bits) < 0) |
745 | return -1; | ||
741 | if (desc.count) | 746 | if (desc.count) |
742 | return -1; | 747 | return -1; |
743 | return 0; | 748 | return 0; |
@@ -821,10 +826,15 @@ tcp_copy_data(skb_reader_t *desc, void *p, size_t len) | |||
821 | { | 826 | { |
822 | if (len > desc->count) | 827 | if (len > desc->count) |
823 | len = desc->count; | 828 | len = desc->count; |
824 | if (skb_copy_bits(desc->skb, desc->offset, p, len)) | 829 | if (skb_copy_bits(desc->skb, desc->offset, p, len)) { |
830 | dprintk("RPC: failed to copy %zu bytes from skb. %zu bytes remain\n", | ||
831 | len, desc->count); | ||
825 | return 0; | 832 | return 0; |
833 | } | ||
826 | desc->offset += len; | 834 | desc->offset += len; |
827 | desc->count -= len; | 835 | desc->count -= len; |
836 | dprintk("RPC: copied %zu bytes from skb. %zu bytes remain\n", | ||
837 | len, desc->count); | ||
828 | return len; | 838 | return len; |
829 | } | 839 | } |
830 | 840 | ||
@@ -863,6 +873,8 @@ tcp_read_fraghdr(struct rpc_xprt *xprt, skb_reader_t *desc) | |||
863 | static void | 873 | static void |
864 | tcp_check_recm(struct rpc_xprt *xprt) | 874 | tcp_check_recm(struct rpc_xprt *xprt) |
865 | { | 875 | { |
876 | dprintk("RPC: xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u, tcp_flags = %lx\n", | ||
877 | xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen, xprt->tcp_flags); | ||
866 | if (xprt->tcp_offset == xprt->tcp_reclen) { | 878 | if (xprt->tcp_offset == xprt->tcp_reclen) { |
867 | xprt->tcp_flags |= XPRT_COPY_RECM; | 879 | xprt->tcp_flags |= XPRT_COPY_RECM; |
868 | xprt->tcp_offset = 0; | 880 | xprt->tcp_offset = 0; |
@@ -907,6 +919,7 @@ tcp_read_request(struct rpc_xprt *xprt, skb_reader_t *desc) | |||
907 | struct rpc_rqst *req; | 919 | struct rpc_rqst *req; |
908 | struct xdr_buf *rcvbuf; | 920 | struct xdr_buf *rcvbuf; |
909 | size_t len; | 921 | size_t len; |
922 | ssize_t r; | ||
910 | 923 | ||
911 | /* Find and lock the request corresponding to this xid */ | 924 | /* Find and lock the request corresponding to this xid */ |
912 | spin_lock(&xprt->sock_lock); | 925 | spin_lock(&xprt->sock_lock); |
@@ -927,15 +940,40 @@ tcp_read_request(struct rpc_xprt *xprt, skb_reader_t *desc) | |||
927 | len = xprt->tcp_reclen - xprt->tcp_offset; | 940 | len = xprt->tcp_reclen - xprt->tcp_offset; |
928 | memcpy(&my_desc, desc, sizeof(my_desc)); | 941 | memcpy(&my_desc, desc, sizeof(my_desc)); |
929 | my_desc.count = len; | 942 | my_desc.count = len; |
930 | xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied, | 943 | r = xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied, |
931 | &my_desc, tcp_copy_data); | 944 | &my_desc, tcp_copy_data); |
932 | desc->count -= len; | 945 | desc->count -= r; |
933 | desc->offset += len; | 946 | desc->offset += r; |
934 | } else | 947 | } else |
935 | xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied, | 948 | r = xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied, |
936 | desc, tcp_copy_data); | 949 | desc, tcp_copy_data); |
937 | xprt->tcp_copied += len; | 950 | |
938 | xprt->tcp_offset += len; | 951 | if (r > 0) { |
952 | xprt->tcp_copied += r; | ||
953 | xprt->tcp_offset += r; | ||
954 | } | ||
955 | if (r != len) { | ||
956 | /* Error when copying to the receive buffer, | ||
957 | * usually because we weren't able to allocate | ||
958 | * additional buffer pages. All we can do now | ||
959 | * is turn off XPRT_COPY_DATA, so the request | ||
960 | * will not receive any additional updates, | ||
961 | * and time out. | ||
962 | * Any remaining data from this record will | ||
963 | * be discarded. | ||
964 | */ | ||
965 | xprt->tcp_flags &= ~XPRT_COPY_DATA; | ||
966 | dprintk("RPC: XID %08x truncated request\n", | ||
967 | ntohl(xprt->tcp_xid)); | ||
968 | dprintk("RPC: xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u\n", | ||
969 | xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen); | ||
970 | goto out; | ||
971 | } | ||
972 | |||
973 | dprintk("RPC: XID %08x read %u bytes\n", | ||
974 | ntohl(xprt->tcp_xid), r); | ||
975 | dprintk("RPC: xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u\n", | ||
976 | xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen); | ||
939 | 977 | ||
940 | if (xprt->tcp_copied == req->rq_private_buf.buflen) | 978 | if (xprt->tcp_copied == req->rq_private_buf.buflen) |
941 | xprt->tcp_flags &= ~XPRT_COPY_DATA; | 979 | xprt->tcp_flags &= ~XPRT_COPY_DATA; |
@@ -944,6 +982,7 @@ tcp_read_request(struct rpc_xprt *xprt, skb_reader_t *desc) | |||
944 | xprt->tcp_flags &= ~XPRT_COPY_DATA; | 982 | xprt->tcp_flags &= ~XPRT_COPY_DATA; |
945 | } | 983 | } |
946 | 984 | ||
985 | out: | ||
947 | if (!(xprt->tcp_flags & XPRT_COPY_DATA)) { | 986 | if (!(xprt->tcp_flags & XPRT_COPY_DATA)) { |
948 | dprintk("RPC: %4d received reply complete\n", | 987 | dprintk("RPC: %4d received reply complete\n", |
949 | req->rq_task->tk_pid); | 988 | req->rq_task->tk_pid); |
@@ -967,6 +1006,7 @@ tcp_read_discard(struct rpc_xprt *xprt, skb_reader_t *desc) | |||
967 | desc->count -= len; | 1006 | desc->count -= len; |
968 | desc->offset += len; | 1007 | desc->offset += len; |
969 | xprt->tcp_offset += len; | 1008 | xprt->tcp_offset += len; |
1009 | dprintk("RPC: discarded %u bytes\n", len); | ||
970 | tcp_check_recm(xprt); | 1010 | tcp_check_recm(xprt); |
971 | } | 1011 | } |
972 | 1012 | ||
@@ -1064,8 +1104,7 @@ tcp_state_change(struct sock *sk) | |||
1064 | case TCP_SYN_RECV: | 1104 | case TCP_SYN_RECV: |
1065 | break; | 1105 | break; |
1066 | default: | 1106 | default: |
1067 | if (xprt_test_and_clear_connected(xprt)) | 1107 | xprt_disconnect(xprt); |
1068 | rpc_wake_up_status(&xprt->pending, -ENOTCONN); | ||
1069 | break; | 1108 | break; |
1070 | } | 1109 | } |
1071 | out: | 1110 | out: |
@@ -1203,6 +1242,8 @@ xprt_transmit(struct rpc_task *task) | |||
1203 | list_add_tail(&req->rq_list, &xprt->recv); | 1242 | list_add_tail(&req->rq_list, &xprt->recv); |
1204 | spin_unlock_bh(&xprt->sock_lock); | 1243 | spin_unlock_bh(&xprt->sock_lock); |
1205 | xprt_reset_majortimeo(req); | 1244 | xprt_reset_majortimeo(req); |
1245 | /* Turn off autodisconnect */ | ||
1246 | del_singleshot_timer_sync(&xprt->timer); | ||
1206 | } | 1247 | } |
1207 | } else if (!req->rq_bytes_sent) | 1248 | } else if (!req->rq_bytes_sent) |
1208 | return; | 1249 | return; |
@@ -1333,8 +1374,6 @@ xprt_reserve(struct rpc_task *task) | |||
1333 | spin_lock(&xprt->xprt_lock); | 1374 | spin_lock(&xprt->xprt_lock); |
1334 | do_xprt_reserve(task); | 1375 | do_xprt_reserve(task); |
1335 | spin_unlock(&xprt->xprt_lock); | 1376 | spin_unlock(&xprt->xprt_lock); |
1336 | if (task->tk_rqstp) | ||
1337 | del_timer_sync(&xprt->timer); | ||
1338 | } | 1377 | } |
1339 | } | 1378 | } |
1340 | 1379 | ||
@@ -1649,6 +1688,10 @@ xprt_shutdown(struct rpc_xprt *xprt) | |||
1649 | rpc_wake_up(&xprt->backlog); | 1688 | rpc_wake_up(&xprt->backlog); |
1650 | wake_up(&xprt->cong_wait); | 1689 | wake_up(&xprt->cong_wait); |
1651 | del_timer_sync(&xprt->timer); | 1690 | del_timer_sync(&xprt->timer); |
1691 | |||
1692 | /* synchronously wait for connect worker to finish */ | ||
1693 | cancel_delayed_work(&xprt->sock_connect); | ||
1694 | flush_scheduled_work(); | ||
1652 | } | 1695 | } |
1653 | 1696 | ||
1654 | /* | 1697 | /* |