aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2006-08-31 18:09:32 -0400
committerJames Bottomley <jejb@mulgrave.il.steeleye.com>2006-09-02 14:37:32 -0400
commitca5186842a6d85e982e3d572ecd407453d0c5116 (patch)
tree6eb680933750cf330308ab2c748a3d0e85c30c53
parentdb98ccde0881b8247acb52dece6d94ed770a7aa5 (diff)
[SCSI] iscsi_tcp: fix partial digest recv
When a digest is spread across two network buffers, we currently ignore this and try to check the digest with the partial buffer. Or course this fails. This patch has use iscsi_tcp_copy to copy the whole digest before testing it. Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
-rw-r--r--drivers/scsi/iscsi_tcp.c21
1 files changed, 13 insertions, 8 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 5d292d0b65ec..d91e8949c71e 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -648,10 +648,9 @@ iscsi_ctask_copy(struct iscsi_tcp_conn *tcp_conn, struct iscsi_cmd_task *ctask,
648 * byte counters. 648 * byte counters.
649 **/ 649 **/
650static inline int 650static inline int
651iscsi_tcp_copy(struct iscsi_conn *conn) 651iscsi_tcp_copy(struct iscsi_conn *conn, int buf_size)
652{ 652{
653 struct iscsi_tcp_conn *tcp_conn = conn->dd_data; 653 struct iscsi_tcp_conn *tcp_conn = conn->dd_data;
654 int buf_size = tcp_conn->in.datalen;
655 int buf_left = buf_size - tcp_conn->data_copied; 654 int buf_left = buf_size - tcp_conn->data_copied;
656 int size = min(tcp_conn->in.copy, buf_left); 655 int size = min(tcp_conn->in.copy, buf_left);
657 int rc; 656 int rc;
@@ -812,7 +811,7 @@ iscsi_data_recv(struct iscsi_conn *conn)
812 * Collect data segment to the connection's data 811 * Collect data segment to the connection's data
813 * placeholder 812 * placeholder
814 */ 813 */
815 if (iscsi_tcp_copy(conn)) { 814 if (iscsi_tcp_copy(conn, tcp_conn->in.datalen)) {
816 rc = -EAGAIN; 815 rc = -EAGAIN;
817 goto exit; 816 goto exit;
818 } 817 }
@@ -899,10 +898,15 @@ more:
899 898
900 debug_tcp("extra data_recv offset %d copy %d\n", 899 debug_tcp("extra data_recv offset %d copy %d\n",
901 tcp_conn->in.offset, tcp_conn->in.copy); 900 tcp_conn->in.offset, tcp_conn->in.copy);
902 skb_copy_bits(tcp_conn->in.skb, tcp_conn->in.offset, 901 rc = iscsi_tcp_copy(conn, sizeof(uint32_t));
903 &recv_digest, 4); 902 if (rc) {
904 tcp_conn->in.offset += 4; 903 if (rc == -EAGAIN)
905 tcp_conn->in.copy -= 4; 904 goto again;
905 iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
906 return 0;
907 }
908
909 memcpy(&recv_digest, conn->data, sizeof(uint32_t));
906 if (recv_digest != tcp_conn->in.datadgst) { 910 if (recv_digest != tcp_conn->in.datadgst) {
907 debug_tcp("iscsi_tcp: data digest error!" 911 debug_tcp("iscsi_tcp: data digest error!"
908 "0x%x != 0x%x\n", recv_digest, 912 "0x%x != 0x%x\n", recv_digest,
@@ -942,9 +946,10 @@ more:
942 &sg, 1); 946 &sg, 1);
943 } 947 }
944 crypto_digest_final(tcp_conn->rx_tfm, 948 crypto_digest_final(tcp_conn->rx_tfm,
945 (u8 *) & tcp_conn->in.datadgst); 949 (u8 *) &tcp_conn->in.datadgst);
946 debug_tcp("rx digest 0x%x\n", tcp_conn->in.datadgst); 950 debug_tcp("rx digest 0x%x\n", tcp_conn->in.datadgst);
947 tcp_conn->in_progress = IN_PROGRESS_DDIGEST_RECV; 951 tcp_conn->in_progress = IN_PROGRESS_DDIGEST_RECV;
952 tcp_conn->data_copied = 0;
948 } else 953 } else
949 tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER; 954 tcp_conn->in_progress = IN_PROGRESS_WAIT_HEADER;
950 } 955 }