diff options
author | Mike Christie <michaelc@cs.wisc.edu> | 2005-11-30 00:12:57 -0500 |
---|---|---|
committer | James Bottomley <jejb@mulgrave.(none)> | 2005-12-13 20:11:58 -0500 |
commit | f6cfba1d21e9e4afd80e2274aa4df3dc1bd0aab7 (patch) | |
tree | d5c91ea5b5ec80fff9da3a7e600839860b9d018d /drivers/scsi/iscsi_tcp.c | |
parent | 733bb6a70cb351786f3c2290ab22f71b612e6893 (diff) |
[SCSI] iscsi: data digest calculation fix
From Wang Zhenyu:
data digest fix (the bug caused data corruption w/Wasabi StorageBuilder target)
Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: Alex Aizman <itn780@yahoo.com>
Signed-off-by: Dmitry Yusupov <dmitry_yus@yahoo.com>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
Diffstat (limited to 'drivers/scsi/iscsi_tcp.c')
-rw-r--r-- | drivers/scsi/iscsi_tcp.c | 65 |
1 files changed, 40 insertions, 25 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index e6991515ad2e..83e2f8c8e496 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c | |||
@@ -903,11 +903,20 @@ partial_sg_digest_update(struct iscsi_conn *conn, struct scatterlist *sg, | |||
903 | crypto_digest_update(conn->data_rx_tfm, &temp, 1); | 903 | crypto_digest_update(conn->data_rx_tfm, &temp, 1); |
904 | } | 904 | } |
905 | 905 | ||
906 | static void | ||
907 | iscsi_recv_digest_update(struct iscsi_conn *conn, char* buf, int len) | ||
908 | { | ||
909 | struct scatterlist tmp; | ||
910 | |||
911 | sg_init_one(&tmp, buf, len); | ||
912 | crypto_digest_update(conn->data_rx_tfm, &tmp, 1); | ||
913 | } | ||
914 | |||
906 | static int iscsi_scsi_data_in(struct iscsi_conn *conn) | 915 | static int iscsi_scsi_data_in(struct iscsi_conn *conn) |
907 | { | 916 | { |
908 | struct iscsi_cmd_task *ctask = conn->in.ctask; | 917 | struct iscsi_cmd_task *ctask = conn->in.ctask; |
909 | struct scsi_cmnd *sc = ctask->sc; | 918 | struct scsi_cmnd *sc = ctask->sc; |
910 | struct scatterlist tmp, *sg; | 919 | struct scatterlist *sg; |
911 | int i, offset, rc = 0; | 920 | int i, offset, rc = 0; |
912 | 921 | ||
913 | BUG_ON((void*)ctask != sc->SCp.ptr); | 922 | BUG_ON((void*)ctask != sc->SCp.ptr); |
@@ -921,10 +930,8 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn) | |||
921 | sc->request_bufflen, ctask->data_offset); | 930 | sc->request_bufflen, ctask->data_offset); |
922 | if (rc == -EAGAIN) | 931 | if (rc == -EAGAIN) |
923 | return rc; | 932 | return rc; |
924 | if (conn->datadgst_en) { | 933 | if (conn->datadgst_en) |
925 | sg_init_one(&tmp, sc->request_buffer, i); | 934 | iscsi_recv_digest_update(conn, sc->request_buffer, i); |
926 | crypto_digest_update(conn->data_rx_tfm, &tmp, 1); | ||
927 | } | ||
928 | rc = 0; | 935 | rc = 0; |
929 | goto done; | 936 | goto done; |
930 | } | 937 | } |
@@ -1018,6 +1025,9 @@ iscsi_data_recv(struct iscsi_conn *conn) | |||
1018 | conn->in.hdr = &conn->hdr; | 1025 | conn->in.hdr = &conn->hdr; |
1019 | conn->senselen = (conn->data[0] << 8) | conn->data[1]; | 1026 | conn->senselen = (conn->data[0] << 8) | conn->data[1]; |
1020 | rc = iscsi_cmd_rsp(conn, conn->in.ctask); | 1027 | rc = iscsi_cmd_rsp(conn, conn->in.ctask); |
1028 | if (!rc && conn->datadgst_en) | ||
1029 | iscsi_recv_digest_update(conn, conn->data, | ||
1030 | conn->in.datalen); | ||
1021 | } | 1031 | } |
1022 | break; | 1032 | break; |
1023 | case ISCSI_OP_TEXT_RSP: | 1033 | case ISCSI_OP_TEXT_RSP: |
@@ -1042,6 +1052,11 @@ iscsi_data_recv(struct iscsi_conn *conn) | |||
1042 | rc = iscsi_recv_pdu(iscsi_handle(conn), conn->in.hdr, | 1052 | rc = iscsi_recv_pdu(iscsi_handle(conn), conn->in.hdr, |
1043 | conn->data, conn->in.datalen); | 1053 | conn->data, conn->in.datalen); |
1044 | 1054 | ||
1055 | if (!rc && conn->datadgst_en && | ||
1056 | conn->in.opcode != ISCSI_OP_LOGIN_RSP) | ||
1057 | iscsi_recv_digest_update(conn, conn->data, | ||
1058 | conn->in.datalen); | ||
1059 | |||
1045 | if (mtask && conn->login_mtask != mtask) { | 1060 | if (mtask && conn->login_mtask != mtask) { |
1046 | spin_lock(&session->lock); | 1061 | spin_lock(&session->lock); |
1047 | __kfifo_put(session->mgmtpool.queue, (void*)&mtask, | 1062 | __kfifo_put(session->mgmtpool.queue, (void*)&mtask, |
@@ -1050,6 +1065,8 @@ iscsi_data_recv(struct iscsi_conn *conn) | |||
1050 | } | 1065 | } |
1051 | } | 1066 | } |
1052 | break; | 1067 | break; |
1068 | case ISCSI_OP_ASYNC_EVENT: | ||
1069 | case ISCSI_OP_REJECT: | ||
1053 | default: | 1070 | default: |
1054 | BUG_ON(1); | 1071 | BUG_ON(1); |
1055 | } | 1072 | } |
@@ -1112,7 +1129,7 @@ more: | |||
1112 | rc = iscsi_hdr_recv(conn); | 1129 | rc = iscsi_hdr_recv(conn); |
1113 | if (!rc && conn->in.datalen) { | 1130 | if (!rc && conn->in.datalen) { |
1114 | if (conn->datadgst_en && | 1131 | if (conn->datadgst_en && |
1115 | conn->in.opcode == ISCSI_OP_SCSI_DATA_IN) { | 1132 | conn->in.opcode != ISCSI_OP_LOGIN_RSP) { |
1116 | BUG_ON(!conn->data_rx_tfm); | 1133 | BUG_ON(!conn->data_rx_tfm); |
1117 | crypto_digest_init(conn->data_rx_tfm); | 1134 | crypto_digest_init(conn->data_rx_tfm); |
1118 | } | 1135 | } |
@@ -1124,26 +1141,24 @@ more: | |||
1124 | } | 1141 | } |
1125 | 1142 | ||
1126 | if (conn->in_progress == IN_PROGRESS_DDIGEST_RECV) { | 1143 | if (conn->in_progress == IN_PROGRESS_DDIGEST_RECV) { |
1144 | uint32_t recv_digest; | ||
1127 | debug_tcp("extra data_recv offset %d copy %d\n", | 1145 | debug_tcp("extra data_recv offset %d copy %d\n", |
1128 | conn->in.offset, conn->in.copy); | 1146 | conn->in.offset, conn->in.copy); |
1129 | if (conn->in.opcode == ISCSI_OP_SCSI_DATA_IN) { | 1147 | skb_copy_bits(conn->in.skb, conn->in.offset, |
1130 | uint32_t recv_digest; | 1148 | &recv_digest, 4); |
1131 | skb_copy_bits(conn->in.skb, conn->in.offset, | 1149 | conn->in.offset += 4; |
1132 | &recv_digest, 4); | 1150 | conn->in.copy -= 4; |
1133 | conn->in.offset += 4; | 1151 | if (recv_digest != conn->in.datadgst) { |
1134 | conn->in.copy -= 4; | 1152 | debug_tcp("iscsi_tcp: data digest error!" |
1135 | if (recv_digest != conn->in.datadgst) { | 1153 | "0x%x != 0x%x\n", recv_digest, |
1136 | debug_tcp("iscsi_tcp: data digest error!" | 1154 | conn->in.datadgst); |
1137 | "0x%x != 0x%x\n", recv_digest, | 1155 | iscsi_conn_failure(conn, ISCSI_ERR_DATA_DGST); |
1138 | conn->in.datadgst); | 1156 | return 0; |
1139 | iscsi_conn_failure(conn, ISCSI_ERR_DATA_DGST); | 1157 | } else { |
1140 | return 0; | 1158 | debug_tcp("iscsi_tcp: data digest match!" |
1141 | } else { | 1159 | "0x%x == 0x%x\n", recv_digest, |
1142 | debug_tcp("iscsi_tcp: data digest match!" | 1160 | conn->in.datadgst); |
1143 | "0x%x == 0x%x\n", recv_digest, | 1161 | conn->in_progress = IN_PROGRESS_WAIT_HEADER; |
1144 | conn->in.datadgst); | ||
1145 | conn->in_progress = IN_PROGRESS_WAIT_HEADER; | ||
1146 | } | ||
1147 | } | 1162 | } |
1148 | } | 1163 | } |
1149 | 1164 | ||
@@ -1165,7 +1180,7 @@ more: | |||
1165 | conn->in.copy -= conn->in.padding; | 1180 | conn->in.copy -= conn->in.padding; |
1166 | conn->in.offset += conn->in.padding; | 1181 | conn->in.offset += conn->in.padding; |
1167 | if (conn->datadgst_en && | 1182 | if (conn->datadgst_en && |
1168 | conn->in.opcode == ISCSI_OP_SCSI_DATA_IN) { | 1183 | conn->in.opcode != ISCSI_OP_LOGIN_RSP) { |
1169 | if (conn->in.padding) { | 1184 | if (conn->in.padding) { |
1170 | debug_tcp("padding -> %d\n", conn->in.padding); | 1185 | debug_tcp("padding -> %d\n", conn->in.padding); |
1171 | memset(pad, 0, conn->in.padding); | 1186 | memset(pad, 0, conn->in.padding); |