diff options
author | Mike Christie <michaelc@cs.wisc.edu> | 2006-08-31 18:09:32 -0400 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.il.steeleye.com> | 2006-09-02 14:37:32 -0400 |
commit | ca5186842a6d85e982e3d572ecd407453d0c5116 (patch) | |
tree | 6eb680933750cf330308ab2c748a3d0e85c30c53 /drivers/scsi | |
parent | db98ccde0881b8247acb52dece6d94ed770a7aa5 (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>
Diffstat (limited to 'drivers/scsi')
-rw-r--r-- | drivers/scsi/iscsi_tcp.c | 21 |
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 | **/ |
650 | static inline int | 650 | static inline int |
651 | iscsi_tcp_copy(struct iscsi_conn *conn) | 651 | iscsi_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 | } |