diff options
Diffstat (limited to 'drivers/scsi/iscsi_tcp.c')
-rw-r--r-- | drivers/scsi/iscsi_tcp.c | 121 |
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>"); |
50 | MODULE_DESCRIPTION("iSCSI/TCP data-path"); | 50 | MODULE_DESCRIPTION("iSCSI/TCP data-path"); |
51 | MODULE_LICENSE("GPL"); | 51 | MODULE_LICENSE("GPL"); |
52 | MODULE_VERSION("0:4.409"); | 52 | MODULE_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 | ||
905 | static void | ||
906 | iscsi_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 | |||
909 | static int iscsi_scsi_data_in(struct iscsi_conn *conn) | 914 | static 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 | ||
2391 | static int | 2401 | static int |
2402 | iscsi_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 | |||
2410 | static int | ||
2392 | iscsi_pool_init(struct iscsi_queue *q, int max, void ***items, int item_size) | 2411 | iscsi_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) | |||
3247 | static struct scsi_host_template iscsi_sht = { | 3269 | static 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 | }; |