diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2005-06-22 13:16:24 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2005-06-22 16:07:19 -0400 |
commit | 7e06b53d796a3740307b54aa2799077f8a0c84e7 (patch) | |
tree | 95c00126400914bfd68f84ed7669272e581e9386 /net/sunrpc/xprt.c | |
parent | e053d1ab62c8ef0eff3dd4c95448cad3c6d2fbf4 (diff) |
[PATCH] RPC: fix accounting bug in the case of a truncated RPC message
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'net/sunrpc/xprt.c')
-rw-r--r-- | net/sunrpc/xprt.c | 35 |
1 files changed, 27 insertions, 8 deletions
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c index a180ed4952d6..ef941e7de8bf 100644 --- a/net/sunrpc/xprt.c +++ b/net/sunrpc/xprt.c | |||
@@ -823,10 +823,15 @@ tcp_copy_data(skb_reader_t *desc, void *p, size_t len) | |||
823 | { | 823 | { |
824 | if (len > desc->count) | 824 | if (len > desc->count) |
825 | len = desc->count; | 825 | len = desc->count; |
826 | if (skb_copy_bits(desc->skb, desc->offset, p, len)) | 826 | if (skb_copy_bits(desc->skb, desc->offset, p, len)) { |
827 | dprintk("RPC: failed to copy %zu bytes from skb. %zu bytes remain\n", | ||
828 | len, desc->count); | ||
827 | return 0; | 829 | return 0; |
830 | } | ||
828 | desc->offset += len; | 831 | desc->offset += len; |
829 | desc->count -= len; | 832 | desc->count -= len; |
833 | dprintk("RPC: copied %zu bytes from skb. %zu bytes remain\n", | ||
834 | len, desc->count); | ||
830 | return len; | 835 | return len; |
831 | } | 836 | } |
832 | 837 | ||
@@ -865,6 +870,8 @@ tcp_read_fraghdr(struct rpc_xprt *xprt, skb_reader_t *desc) | |||
865 | static void | 870 | static void |
866 | tcp_check_recm(struct rpc_xprt *xprt) | 871 | tcp_check_recm(struct rpc_xprt *xprt) |
867 | { | 872 | { |
873 | dprintk("RPC: xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u, tcp_flags = %lx\n", | ||
874 | xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen, xprt->tcp_flags); | ||
868 | if (xprt->tcp_offset == xprt->tcp_reclen) { | 875 | if (xprt->tcp_offset == xprt->tcp_reclen) { |
869 | xprt->tcp_flags |= XPRT_COPY_RECM; | 876 | xprt->tcp_flags |= XPRT_COPY_RECM; |
870 | xprt->tcp_offset = 0; | 877 | xprt->tcp_offset = 0; |
@@ -909,7 +916,7 @@ tcp_read_request(struct rpc_xprt *xprt, skb_reader_t *desc) | |||
909 | struct rpc_rqst *req; | 916 | struct rpc_rqst *req; |
910 | struct xdr_buf *rcvbuf; | 917 | struct xdr_buf *rcvbuf; |
911 | size_t len; | 918 | size_t len; |
912 | int r; | 919 | ssize_t r; |
913 | 920 | ||
914 | /* Find and lock the request corresponding to this xid */ | 921 | /* Find and lock the request corresponding to this xid */ |
915 | spin_lock(&xprt->sock_lock); | 922 | spin_lock(&xprt->sock_lock); |
@@ -932,15 +939,17 @@ tcp_read_request(struct rpc_xprt *xprt, skb_reader_t *desc) | |||
932 | my_desc.count = len; | 939 | my_desc.count = len; |
933 | r = xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied, | 940 | r = xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied, |
934 | &my_desc, tcp_copy_data); | 941 | &my_desc, tcp_copy_data); |
935 | desc->count -= len; | 942 | desc->count -= r; |
936 | desc->offset += len; | 943 | desc->offset += r; |
937 | } else | 944 | } else |
938 | r = xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied, | 945 | r = xdr_partial_copy_from_skb(rcvbuf, xprt->tcp_copied, |
939 | desc, tcp_copy_data); | 946 | desc, tcp_copy_data); |
940 | xprt->tcp_copied += len; | ||
941 | xprt->tcp_offset += len; | ||
942 | 947 | ||
943 | if (r < 0) { | 948 | if (r > 0) { |
949 | xprt->tcp_copied += r; | ||
950 | xprt->tcp_offset += r; | ||
951 | } | ||
952 | if (r != len) { | ||
944 | /* Error when copying to the receive buffer, | 953 | /* Error when copying to the receive buffer, |
945 | * usually because we weren't able to allocate | 954 | * usually because we weren't able to allocate |
946 | * additional buffer pages. All we can do now | 955 | * additional buffer pages. All we can do now |
@@ -951,9 +960,18 @@ tcp_read_request(struct rpc_xprt *xprt, skb_reader_t *desc) | |||
951 | * be discarded. | 960 | * be discarded. |
952 | */ | 961 | */ |
953 | xprt->tcp_flags &= ~XPRT_COPY_DATA; | 962 | xprt->tcp_flags &= ~XPRT_COPY_DATA; |
963 | dprintk("RPC: XID %08x truncated request\n", | ||
964 | ntohl(xprt->tcp_xid)); | ||
965 | dprintk("RPC: xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u\n", | ||
966 | xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen); | ||
954 | goto out; | 967 | goto out; |
955 | } | 968 | } |
956 | 969 | ||
970 | dprintk("RPC: XID %08x read %u bytes\n", | ||
971 | ntohl(xprt->tcp_xid), r); | ||
972 | dprintk("RPC: xprt = %p, tcp_copied = %lu, tcp_offset = %u, tcp_reclen = %u\n", | ||
973 | xprt, xprt->tcp_copied, xprt->tcp_offset, xprt->tcp_reclen); | ||
974 | |||
957 | if (xprt->tcp_copied == req->rq_private_buf.buflen) | 975 | if (xprt->tcp_copied == req->rq_private_buf.buflen) |
958 | xprt->tcp_flags &= ~XPRT_COPY_DATA; | 976 | xprt->tcp_flags &= ~XPRT_COPY_DATA; |
959 | else if (xprt->tcp_offset == xprt->tcp_reclen) { | 977 | else if (xprt->tcp_offset == xprt->tcp_reclen) { |
@@ -961,12 +979,12 @@ tcp_read_request(struct rpc_xprt *xprt, skb_reader_t *desc) | |||
961 | xprt->tcp_flags &= ~XPRT_COPY_DATA; | 979 | xprt->tcp_flags &= ~XPRT_COPY_DATA; |
962 | } | 980 | } |
963 | 981 | ||
982 | out: | ||
964 | if (!(xprt->tcp_flags & XPRT_COPY_DATA)) { | 983 | if (!(xprt->tcp_flags & XPRT_COPY_DATA)) { |
965 | dprintk("RPC: %4d received reply complete\n", | 984 | dprintk("RPC: %4d received reply complete\n", |
966 | req->rq_task->tk_pid); | 985 | req->rq_task->tk_pid); |
967 | xprt_complete_rqst(xprt, req, xprt->tcp_copied); | 986 | xprt_complete_rqst(xprt, req, xprt->tcp_copied); |
968 | } | 987 | } |
969 | out: | ||
970 | spin_unlock(&xprt->sock_lock); | 988 | spin_unlock(&xprt->sock_lock); |
971 | tcp_check_recm(xprt); | 989 | tcp_check_recm(xprt); |
972 | } | 990 | } |
@@ -985,6 +1003,7 @@ tcp_read_discard(struct rpc_xprt *xprt, skb_reader_t *desc) | |||
985 | desc->count -= len; | 1003 | desc->count -= len; |
986 | desc->offset += len; | 1004 | desc->offset += len; |
987 | xprt->tcp_offset += len; | 1005 | xprt->tcp_offset += len; |
1006 | dprintk("RPC: discarded %u bytes\n", len); | ||
988 | tcp_check_recm(xprt); | 1007 | tcp_check_recm(xprt); |
989 | } | 1008 | } |
990 | 1009 | ||