aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMike Christie <michaelc@cs.wisc.edu>2005-11-30 00:12:57 -0500
committerJames Bottomley <jejb@mulgrave.(none)>2005-12-13 20:11:58 -0500
commitf6cfba1d21e9e4afd80e2274aa4df3dc1bd0aab7 (patch)
treed5c91ea5b5ec80fff9da3a7e600839860b9d018d
parent733bb6a70cb351786f3c2290ab22f71b612e6893 (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>
-rw-r--r--drivers/scsi/iscsi_tcp.c65
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
906static void
907iscsi_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
906static int iscsi_scsi_data_in(struct iscsi_conn *conn) 915static 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);