aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/iscsi_tcp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/iscsi_tcp.c')
-rw-r--r--drivers/scsi/iscsi_tcp.c121
1 files changed, 72 insertions, 49 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c
index 3d8009f55342..10bcf42cb65c 100644
--- a/drivers/scsi/iscsi_tcp.c
+++ b/drivers/scsi/iscsi_tcp.c
@@ -49,7 +49,7 @@ MODULE_AUTHOR("Dmitry Yusupov <dmitry_yus@yahoo.com>, "
49 "Alex Aizman <itn780@yahoo.com>"); 49 "Alex Aizman <itn780@yahoo.com>");
50MODULE_DESCRIPTION("iSCSI/TCP data-path"); 50MODULE_DESCRIPTION("iSCSI/TCP data-path");
51MODULE_LICENSE("GPL"); 51MODULE_LICENSE("GPL");
52MODULE_VERSION("0:4.409"); 52MODULE_VERSION("0:4.445");
53/* #define DEBUG_TCP */ 53/* #define DEBUG_TCP */
54/* #define DEBUG_SCSI */ 54/* #define DEBUG_SCSI */
55#define DEBUG_ASSERT 55#define DEBUG_ASSERT
@@ -581,10 +581,16 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
581 crypto_digest_digest(conn->rx_tfm, &sg, 1, (u8 *)&cdgst); 581 crypto_digest_digest(conn->rx_tfm, &sg, 1, (u8 *)&cdgst);
582 rdgst = *(uint32_t*)((char*)hdr + sizeof(struct iscsi_hdr) + 582 rdgst = *(uint32_t*)((char*)hdr + sizeof(struct iscsi_hdr) +
583 conn->in.ahslen); 583 conn->in.ahslen);
584 if (cdgst != rdgst) {
585 printk(KERN_ERR "iscsi_tcp: itt %x: hdrdgst error "
586 "recv 0x%x calc 0x%x\n", conn->in.itt, rdgst,
587 cdgst);
588 return ISCSI_ERR_HDR_DGST;
589 }
584 } 590 }
585 591
586 /* save opcode for later */ 592 /* save opcode for later */
587 conn->in.opcode = hdr->opcode; 593 conn->in.opcode = hdr->opcode & ISCSI_OPCODE_MASK;
588 594
589 /* verify itt (itt encoding: age+cid+itt) */ 595 /* verify itt (itt encoding: age+cid+itt) */
590 if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) { 596 if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) {
@@ -610,13 +616,6 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
610 conn->in.ahslen, conn->in.datalen); 616 conn->in.ahslen, conn->in.datalen);
611 617
612 if (conn->in.itt < session->cmds_max) { 618 if (conn->in.itt < session->cmds_max) {
613 if (conn->hdrdgst_en && cdgst != rdgst) {
614 printk(KERN_ERR "iscsi_tcp: itt %x: hdrdgst error "
615 "recv 0x%x calc 0x%x\n", conn->in.itt, rdgst,
616 cdgst);
617 return ISCSI_ERR_HDR_DGST;
618 }
619
620 ctask = (struct iscsi_cmd_task *)session->cmds[conn->in.itt]; 619 ctask = (struct iscsi_cmd_task *)session->cmds[conn->in.itt];
621 620
622 if (!ctask->sc) { 621 if (!ctask->sc) {
@@ -642,9 +641,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
642 switch(conn->in.opcode) { 641 switch(conn->in.opcode) {
643 case ISCSI_OP_SCSI_CMD_RSP: 642 case ISCSI_OP_SCSI_CMD_RSP:
644 BUG_ON((void*)ctask != ctask->sc->SCp.ptr); 643 BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
645 if (ctask->hdr.flags & ISCSI_FLAG_CMD_WRITE) 644 if (!conn->in.datalen)
646 rc = iscsi_cmd_rsp(conn, ctask);
647 else if (!conn->in.datalen)
648 rc = iscsi_cmd_rsp(conn, ctask); 645 rc = iscsi_cmd_rsp(conn, ctask);
649 else 646 else
650 /* 647 /*
@@ -666,8 +663,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn)
666 break; 663 break;
667 case ISCSI_OP_R2T: 664 case ISCSI_OP_R2T:
668 BUG_ON((void*)ctask != ctask->sc->SCp.ptr); 665 BUG_ON((void*)ctask != ctask->sc->SCp.ptr);
669 if (ctask->hdr.flags & ISCSI_FLAG_CMD_WRITE && 666 if (ctask->sc->sc_data_direction == DMA_TO_DEVICE)
670 ctask->sc->sc_data_direction == DMA_TO_DEVICE)
671 rc = iscsi_r2t_rsp(conn, ctask); 667 rc = iscsi_r2t_rsp(conn, ctask);
672 else 668 else
673 rc = ISCSI_ERR_PROTO; 669 rc = ISCSI_ERR_PROTO;
@@ -906,11 +902,20 @@ partial_sg_digest_update(struct iscsi_conn *conn, struct scatterlist *sg,
906 crypto_digest_update(conn->data_rx_tfm, &temp, 1); 902 crypto_digest_update(conn->data_rx_tfm, &temp, 1);
907} 903}
908 904
905static void
906iscsi_recv_digest_update(struct iscsi_conn *conn, char* buf, int len)
907{
908 struct scatterlist tmp;
909
910 sg_init_one(&tmp, buf, len);
911 crypto_digest_update(conn->data_rx_tfm, &tmp, 1);
912}
913
909static int iscsi_scsi_data_in(struct iscsi_conn *conn) 914static int iscsi_scsi_data_in(struct iscsi_conn *conn)
910{ 915{
911 struct iscsi_cmd_task *ctask = conn->in.ctask; 916 struct iscsi_cmd_task *ctask = conn->in.ctask;
912 struct scsi_cmnd *sc = ctask->sc; 917 struct scsi_cmnd *sc = ctask->sc;
913 struct scatterlist tmp, *sg; 918 struct scatterlist *sg;
914 int i, offset, rc = 0; 919 int i, offset, rc = 0;
915 920
916 BUG_ON((void*)ctask != sc->SCp.ptr); 921 BUG_ON((void*)ctask != sc->SCp.ptr);
@@ -924,10 +929,8 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn)
924 sc->request_bufflen, ctask->data_offset); 929 sc->request_bufflen, ctask->data_offset);
925 if (rc == -EAGAIN) 930 if (rc == -EAGAIN)
926 return rc; 931 return rc;
927 if (conn->datadgst_en) { 932 if (conn->datadgst_en)
928 sg_init_one(&tmp, sc->request_buffer, i); 933 iscsi_recv_digest_update(conn, sc->request_buffer, i);
929 crypto_digest_update(conn->data_rx_tfm, &tmp, 1);
930 }
931 rc = 0; 934 rc = 0;
932 goto done; 935 goto done;
933 } 936 }
@@ -1021,6 +1024,9 @@ iscsi_data_recv(struct iscsi_conn *conn)
1021 conn->in.hdr = &conn->hdr; 1024 conn->in.hdr = &conn->hdr;
1022 conn->senselen = (conn->data[0] << 8) | conn->data[1]; 1025 conn->senselen = (conn->data[0] << 8) | conn->data[1];
1023 rc = iscsi_cmd_rsp(conn, conn->in.ctask); 1026 rc = iscsi_cmd_rsp(conn, conn->in.ctask);
1027 if (!rc && conn->datadgst_en)
1028 iscsi_recv_digest_update(conn, conn->data,
1029 conn->in.datalen);
1024 } 1030 }
1025 break; 1031 break;
1026 case ISCSI_OP_TEXT_RSP: 1032 case ISCSI_OP_TEXT_RSP:
@@ -1045,6 +1051,11 @@ iscsi_data_recv(struct iscsi_conn *conn)
1045 rc = iscsi_recv_pdu(iscsi_handle(conn), conn->in.hdr, 1051 rc = iscsi_recv_pdu(iscsi_handle(conn), conn->in.hdr,
1046 conn->data, conn->in.datalen); 1052 conn->data, conn->in.datalen);
1047 1053
1054 if (!rc && conn->datadgst_en &&
1055 conn->in.opcode != ISCSI_OP_LOGIN_RSP)
1056 iscsi_recv_digest_update(conn, conn->data,
1057 conn->in.datalen);
1058
1048 if (mtask && conn->login_mtask != mtask) { 1059 if (mtask && conn->login_mtask != mtask) {
1049 spin_lock(&session->lock); 1060 spin_lock(&session->lock);
1050 __kfifo_put(session->mgmtpool.queue, (void*)&mtask, 1061 __kfifo_put(session->mgmtpool.queue, (void*)&mtask,
@@ -1053,6 +1064,8 @@ iscsi_data_recv(struct iscsi_conn *conn)
1053 } 1064 }
1054 } 1065 }
1055 break; 1066 break;
1067 case ISCSI_OP_ASYNC_EVENT:
1068 case ISCSI_OP_REJECT:
1056 default: 1069 default:
1057 BUG_ON(1); 1070 BUG_ON(1);
1058 } 1071 }
@@ -1114,8 +1127,7 @@ more:
1114 */ 1127 */
1115 rc = iscsi_hdr_recv(conn); 1128 rc = iscsi_hdr_recv(conn);
1116 if (!rc && conn->in.datalen) { 1129 if (!rc && conn->in.datalen) {
1117 if (conn->datadgst_en && 1130 if (conn->datadgst_en) {
1118 conn->in.opcode == ISCSI_OP_SCSI_DATA_IN) {
1119 BUG_ON(!conn->data_rx_tfm); 1131 BUG_ON(!conn->data_rx_tfm);
1120 crypto_digest_init(conn->data_rx_tfm); 1132 crypto_digest_init(conn->data_rx_tfm);
1121 } 1133 }
@@ -1127,26 +1139,24 @@ more:
1127 } 1139 }
1128 1140
1129 if (conn->in_progress == IN_PROGRESS_DDIGEST_RECV) { 1141 if (conn->in_progress == IN_PROGRESS_DDIGEST_RECV) {
1142 uint32_t recv_digest;
1130 debug_tcp("extra data_recv offset %d copy %d\n", 1143 debug_tcp("extra data_recv offset %d copy %d\n",
1131 conn->in.offset, conn->in.copy); 1144 conn->in.offset, conn->in.copy);
1132 if (conn->in.opcode == ISCSI_OP_SCSI_DATA_IN) { 1145 skb_copy_bits(conn->in.skb, conn->in.offset,
1133 uint32_t recv_digest; 1146 &recv_digest, 4);
1134 skb_copy_bits(conn->in.skb, conn->in.offset, 1147 conn->in.offset += 4;
1135 &recv_digest, 4); 1148 conn->in.copy -= 4;
1136 conn->in.offset += 4; 1149 if (recv_digest != conn->in.datadgst) {
1137 conn->in.copy -= 4; 1150 debug_tcp("iscsi_tcp: data digest error!"
1138 if (recv_digest != conn->in.datadgst) { 1151 "0x%x != 0x%x\n", recv_digest,
1139 debug_tcp("iscsi_tcp: data digest error!" 1152 conn->in.datadgst);
1140 "0x%x != 0x%x\n", recv_digest, 1153 iscsi_conn_failure(conn, ISCSI_ERR_DATA_DGST);
1141 conn->in.datadgst); 1154 return 0;
1142 iscsi_conn_failure(conn, ISCSI_ERR_DATA_DGST); 1155 } else {
1143 return 0; 1156 debug_tcp("iscsi_tcp: data digest match!"
1144 } else { 1157 "0x%x == 0x%x\n", recv_digest,
1145 debug_tcp("iscsi_tcp: data digest match!" 1158 conn->in.datadgst);
1146 "0x%x == 0x%x\n", recv_digest, 1159 conn->in_progress = IN_PROGRESS_WAIT_HEADER;
1147 conn->in.datadgst);
1148 conn->in_progress = IN_PROGRESS_WAIT_HEADER;
1149 }
1150 } 1160 }
1151 } 1161 }
1152 1162
@@ -1167,8 +1177,7 @@ more:
1167 } 1177 }
1168 conn->in.copy -= conn->in.padding; 1178 conn->in.copy -= conn->in.padding;
1169 conn->in.offset += conn->in.padding; 1179 conn->in.offset += conn->in.padding;
1170 if (conn->datadgst_en && 1180 if (conn->datadgst_en) {
1171 conn->in.opcode == ISCSI_OP_SCSI_DATA_IN) {
1172 if (conn->in.padding) { 1181 if (conn->in.padding) {
1173 debug_tcp("padding -> %d\n", conn->in.padding); 1182 debug_tcp("padding -> %d\n", conn->in.padding);
1174 memset(pad, 0, conn->in.padding); 1183 memset(pad, 0, conn->in.padding);
@@ -1237,8 +1246,9 @@ iscsi_tcp_state_change(struct sock *sk)
1237 conn = (struct iscsi_conn*)sk->sk_user_data; 1246 conn = (struct iscsi_conn*)sk->sk_user_data;
1238 session = conn->session; 1247 session = conn->session;
1239 1248
1240 if (sk->sk_state == TCP_CLOSE_WAIT || 1249 if ((sk->sk_state == TCP_CLOSE_WAIT ||
1241 sk->sk_state == TCP_CLOSE) { 1250 sk->sk_state == TCP_CLOSE) &&
1251 !atomic_read(&sk->sk_rmem_alloc)) {
1242 debug_tcp("iscsi_tcp_state_change: TCP_CLOSE|TCP_CLOSE_WAIT\n"); 1252 debug_tcp("iscsi_tcp_state_change: TCP_CLOSE|TCP_CLOSE_WAIT\n");
1243 iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); 1253 iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED);
1244 } 1254 }
@@ -2389,6 +2399,15 @@ fault:
2389} 2399}
2390 2400
2391static int 2401static int
2402iscsi_change_queue_depth(struct scsi_device *sdev, int depth)
2403{
2404 if (depth > ISCSI_MAX_CMD_PER_LUN)
2405 depth = ISCSI_MAX_CMD_PER_LUN;
2406 scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth);
2407 return sdev->queue_depth;
2408}
2409
2410static int
2392iscsi_pool_init(struct iscsi_queue *q, int max, void ***items, int item_size) 2411iscsi_pool_init(struct iscsi_queue *q, int max, void ***items, int item_size)
2393{ 2412{
2394 int i; 2413 int i;
@@ -2853,8 +2872,11 @@ iscsi_conn_stop(iscsi_connh_t connh, int flag)
2853 * in hdr_extract() and will be re-negotiated at 2872 * in hdr_extract() and will be re-negotiated at
2854 * set_param() time. 2873 * set_param() time.
2855 */ 2874 */
2856 if (flag == STOP_CONN_RECOVER) 2875 if (flag == STOP_CONN_RECOVER) {
2857 conn->hdr_size = sizeof(struct iscsi_hdr); 2876 conn->hdr_size = sizeof(struct iscsi_hdr);
2877 conn->hdrdgst_en = 0;
2878 conn->datadgst_en = 0;
2879 }
2858 } 2880 }
2859 up(&conn->xmitsema); 2881 up(&conn->xmitsema);
2860} 2882}
@@ -3247,13 +3269,14 @@ iscsi_r2tpool_free(struct iscsi_session *session)
3247static struct scsi_host_template iscsi_sht = { 3269static struct scsi_host_template iscsi_sht = {
3248 .name = "iSCSI Initiator over TCP/IP, v." 3270 .name = "iSCSI Initiator over TCP/IP, v."
3249 ISCSI_VERSION_STR, 3271 ISCSI_VERSION_STR,
3250 .queuecommand = iscsi_queuecommand, 3272 .queuecommand = iscsi_queuecommand,
3273 .change_queue_depth = iscsi_change_queue_depth,
3251 .can_queue = ISCSI_XMIT_CMDS_MAX - 1, 3274 .can_queue = ISCSI_XMIT_CMDS_MAX - 1,
3252 .sg_tablesize = ISCSI_SG_TABLESIZE, 3275 .sg_tablesize = ISCSI_SG_TABLESIZE,
3253 .cmd_per_lun = ISCSI_CMD_PER_LUN, 3276 .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN,
3254 .eh_abort_handler = iscsi_eh_abort, 3277 .eh_abort_handler = iscsi_eh_abort,
3255 .eh_host_reset_handler = iscsi_eh_host_reset, 3278 .eh_host_reset_handler = iscsi_eh_host_reset,
3256 .use_clustering = DISABLE_CLUSTERING, 3279 .use_clustering = DISABLE_CLUSTERING,
3257 .proc_name = "iscsi_tcp", 3280 .proc_name = "iscsi_tcp",
3258 .this_id = -1, 3281 .this_id = -1,
3259}; 3282};