diff options
Diffstat (limited to 'drivers/scsi/iscsi_tcp.c')
-rw-r--r-- | drivers/scsi/iscsi_tcp.c | 420 |
1 files changed, 217 insertions, 203 deletions
diff --git a/drivers/scsi/iscsi_tcp.c b/drivers/scsi/iscsi_tcp.c index 3d8009f55342..780bfcc67096 100644 --- a/drivers/scsi/iscsi_tcp.c +++ b/drivers/scsi/iscsi_tcp.c | |||
@@ -33,6 +33,7 @@ | |||
33 | #include <linux/delay.h> | 33 | #include <linux/delay.h> |
34 | #include <linux/kfifo.h> | 34 | #include <linux/kfifo.h> |
35 | #include <linux/scatterlist.h> | 35 | #include <linux/scatterlist.h> |
36 | #include <linux/mutex.h> | ||
36 | #include <net/tcp.h> | 37 | #include <net/tcp.h> |
37 | #include <scsi/scsi_cmnd.h> | 38 | #include <scsi/scsi_cmnd.h> |
38 | #include <scsi/scsi_device.h> | 39 | #include <scsi/scsi_device.h> |
@@ -49,7 +50,7 @@ MODULE_AUTHOR("Dmitry Yusupov <dmitry_yus@yahoo.com>, " | |||
49 | "Alex Aizman <itn780@yahoo.com>"); | 50 | "Alex Aizman <itn780@yahoo.com>"); |
50 | MODULE_DESCRIPTION("iSCSI/TCP data-path"); | 51 | MODULE_DESCRIPTION("iSCSI/TCP data-path"); |
51 | MODULE_LICENSE("GPL"); | 52 | MODULE_LICENSE("GPL"); |
52 | MODULE_VERSION("0:4.409"); | 53 | MODULE_VERSION("0:4.445"); |
53 | /* #define DEBUG_TCP */ | 54 | /* #define DEBUG_TCP */ |
54 | /* #define DEBUG_SCSI */ | 55 | /* #define DEBUG_SCSI */ |
55 | #define DEBUG_ASSERT | 56 | #define DEBUG_ASSERT |
@@ -86,35 +87,32 @@ iscsi_buf_init_virt(struct iscsi_buf *ibuf, char *vbuf, int size) | |||
86 | { | 87 | { |
87 | sg_init_one(&ibuf->sg, (u8 *)vbuf, size); | 88 | sg_init_one(&ibuf->sg, (u8 *)vbuf, size); |
88 | ibuf->sent = 0; | 89 | ibuf->sent = 0; |
90 | ibuf->use_sendmsg = 0; | ||
89 | } | 91 | } |
90 | 92 | ||
91 | static inline void | 93 | static inline void |
92 | iscsi_buf_init_iov(struct iscsi_buf *ibuf, char *vbuf, int size) | 94 | iscsi_buf_init_iov(struct iscsi_buf *ibuf, char *vbuf, int size) |
93 | { | 95 | { |
94 | ibuf->sg.page = (void*)vbuf; | 96 | ibuf->sg.page = virt_to_page(vbuf); |
95 | ibuf->sg.offset = (unsigned int)-1; | 97 | ibuf->sg.offset = offset_in_page(vbuf); |
96 | ibuf->sg.length = size; | 98 | ibuf->sg.length = size; |
97 | ibuf->sent = 0; | 99 | ibuf->sent = 0; |
98 | } | 100 | ibuf->use_sendmsg = 1; |
99 | |||
100 | static inline void* | ||
101 | iscsi_buf_iov_base(struct iscsi_buf *ibuf) | ||
102 | { | ||
103 | return (char*)ibuf->sg.page + ibuf->sent; | ||
104 | } | 101 | } |
105 | 102 | ||
106 | static inline void | 103 | static inline void |
107 | iscsi_buf_init_sg(struct iscsi_buf *ibuf, struct scatterlist *sg) | 104 | iscsi_buf_init_sg(struct iscsi_buf *ibuf, struct scatterlist *sg) |
108 | { | 105 | { |
106 | ibuf->sg.page = sg->page; | ||
107 | ibuf->sg.offset = sg->offset; | ||
108 | ibuf->sg.length = sg->length; | ||
109 | /* | 109 | /* |
110 | * Fastpath: sg element fits into single page | 110 | * Fastpath: sg element fits into single page |
111 | */ | 111 | */ |
112 | if (sg->length + sg->offset <= PAGE_SIZE && page_count(sg->page) >= 2) { | 112 | if (sg->length + sg->offset <= PAGE_SIZE && !PageSlab(sg->page)) |
113 | ibuf->sg.page = sg->page; | 113 | ibuf->use_sendmsg = 0; |
114 | ibuf->sg.offset = sg->offset; | 114 | else |
115 | ibuf->sg.length = sg->length; | 115 | ibuf->use_sendmsg = 1; |
116 | } else | ||
117 | iscsi_buf_init_iov(ibuf, page_address(sg->page), sg->length); | ||
118 | ibuf->sent = 0; | 116 | ibuf->sent = 0; |
119 | } | 117 | } |
120 | 118 | ||
@@ -356,7 +354,7 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
356 | struct scsi_cmnd *sc = ctask->sc; | 354 | struct scsi_cmnd *sc = ctask->sc; |
357 | 355 | ||
358 | conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1; | 356 | conn->exp_statsn = be32_to_cpu(rhdr->statsn) + 1; |
359 | if (rhdr->flags & ISCSI_FLAG_CMD_UNDERFLOW) { | 357 | if (rhdr->flags & ISCSI_FLAG_DATA_UNDERFLOW) { |
360 | int res_count = be32_to_cpu(rhdr->residual_count); | 358 | int res_count = be32_to_cpu(rhdr->residual_count); |
361 | 359 | ||
362 | if (res_count > 0 && | 360 | if (res_count > 0 && |
@@ -366,9 +364,7 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
366 | } else | 364 | } else |
367 | sc->result = (DID_BAD_TARGET << 16) | | 365 | sc->result = (DID_BAD_TARGET << 16) | |
368 | rhdr->cmd_status; | 366 | rhdr->cmd_status; |
369 | } else if (rhdr->flags & ISCSI_FLAG_CMD_BIDI_UNDERFLOW) | 367 | } else if (rhdr->flags & ISCSI_FLAG_DATA_OVERFLOW) { |
370 | sc->result = (DID_BAD_TARGET << 16) | rhdr->cmd_status; | ||
371 | else if (rhdr->flags & ISCSI_FLAG_CMD_OVERFLOW) { | ||
372 | sc->resid = be32_to_cpu(rhdr->residual_count); | 368 | sc->resid = be32_to_cpu(rhdr->residual_count); |
373 | sc->result = (DID_OK << 16) | rhdr->cmd_status; | 369 | sc->result = (DID_OK << 16) | rhdr->cmd_status; |
374 | } else | 370 | } else |
@@ -529,7 +525,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
529 | __kfifo_put(ctask->r2tqueue, (void*)&r2t, sizeof(void*)); | 525 | __kfifo_put(ctask->r2tqueue, (void*)&r2t, sizeof(void*)); |
530 | __kfifo_put(conn->writequeue, (void*)&ctask, sizeof(void*)); | 526 | __kfifo_put(conn->writequeue, (void*)&ctask, sizeof(void*)); |
531 | 527 | ||
532 | schedule_work(&conn->xmitwork); | 528 | scsi_queue_work(session->host, &conn->xmitwork); |
533 | conn->r2t_pdus_cnt++; | 529 | conn->r2t_pdus_cnt++; |
534 | spin_unlock(&session->lock); | 530 | spin_unlock(&session->lock); |
535 | 531 | ||
@@ -581,10 +577,16 @@ iscsi_hdr_recv(struct iscsi_conn *conn) | |||
581 | crypto_digest_digest(conn->rx_tfm, &sg, 1, (u8 *)&cdgst); | 577 | crypto_digest_digest(conn->rx_tfm, &sg, 1, (u8 *)&cdgst); |
582 | rdgst = *(uint32_t*)((char*)hdr + sizeof(struct iscsi_hdr) + | 578 | rdgst = *(uint32_t*)((char*)hdr + sizeof(struct iscsi_hdr) + |
583 | conn->in.ahslen); | 579 | conn->in.ahslen); |
580 | if (cdgst != rdgst) { | ||
581 | printk(KERN_ERR "iscsi_tcp: itt %x: hdrdgst error " | ||
582 | "recv 0x%x calc 0x%x\n", conn->in.itt, rdgst, | ||
583 | cdgst); | ||
584 | return ISCSI_ERR_HDR_DGST; | ||
585 | } | ||
584 | } | 586 | } |
585 | 587 | ||
586 | /* save opcode for later */ | 588 | /* save opcode for later */ |
587 | conn->in.opcode = hdr->opcode; | 589 | conn->in.opcode = hdr->opcode & ISCSI_OPCODE_MASK; |
588 | 590 | ||
589 | /* verify itt (itt encoding: age+cid+itt) */ | 591 | /* verify itt (itt encoding: age+cid+itt) */ |
590 | if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) { | 592 | if (hdr->itt != cpu_to_be32(ISCSI_RESERVED_TAG)) { |
@@ -610,13 +612,6 @@ iscsi_hdr_recv(struct iscsi_conn *conn) | |||
610 | conn->in.ahslen, conn->in.datalen); | 612 | conn->in.ahslen, conn->in.datalen); |
611 | 613 | ||
612 | if (conn->in.itt < session->cmds_max) { | 614 | 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]; | 615 | ctask = (struct iscsi_cmd_task *)session->cmds[conn->in.itt]; |
621 | 616 | ||
622 | if (!ctask->sc) { | 617 | if (!ctask->sc) { |
@@ -642,9 +637,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn) | |||
642 | switch(conn->in.opcode) { | 637 | switch(conn->in.opcode) { |
643 | case ISCSI_OP_SCSI_CMD_RSP: | 638 | case ISCSI_OP_SCSI_CMD_RSP: |
644 | BUG_ON((void*)ctask != ctask->sc->SCp.ptr); | 639 | BUG_ON((void*)ctask != ctask->sc->SCp.ptr); |
645 | if (ctask->hdr.flags & ISCSI_FLAG_CMD_WRITE) | 640 | if (!conn->in.datalen) |
646 | rc = iscsi_cmd_rsp(conn, ctask); | ||
647 | else if (!conn->in.datalen) | ||
648 | rc = iscsi_cmd_rsp(conn, ctask); | 641 | rc = iscsi_cmd_rsp(conn, ctask); |
649 | else | 642 | else |
650 | /* | 643 | /* |
@@ -666,8 +659,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn) | |||
666 | break; | 659 | break; |
667 | case ISCSI_OP_R2T: | 660 | case ISCSI_OP_R2T: |
668 | BUG_ON((void*)ctask != ctask->sc->SCp.ptr); | 661 | BUG_ON((void*)ctask != ctask->sc->SCp.ptr); |
669 | if (ctask->hdr.flags & ISCSI_FLAG_CMD_WRITE && | 662 | 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); | 663 | rc = iscsi_r2t_rsp(conn, ctask); |
672 | else | 664 | else |
673 | rc = ISCSI_ERR_PROTO; | 665 | rc = ISCSI_ERR_PROTO; |
@@ -690,7 +682,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn) | |||
690 | switch(conn->in.opcode) { | 682 | switch(conn->in.opcode) { |
691 | case ISCSI_OP_LOGIN_RSP: | 683 | case ISCSI_OP_LOGIN_RSP: |
692 | case ISCSI_OP_TEXT_RSP: | 684 | case ISCSI_OP_TEXT_RSP: |
693 | case ISCSI_OP_LOGOUT_RSP: | 685 | case ISCSI_OP_LOGOUT_RSP: |
694 | rc = iscsi_check_assign_cmdsn(session, | 686 | rc = iscsi_check_assign_cmdsn(session, |
695 | (struct iscsi_nopin*)hdr); | 687 | (struct iscsi_nopin*)hdr); |
696 | if (rc) | 688 | if (rc) |
@@ -731,12 +723,12 @@ iscsi_hdr_recv(struct iscsi_conn *conn) | |||
731 | } | 723 | } |
732 | spin_unlock(&session->lock); | 724 | spin_unlock(&session->lock); |
733 | break; | 725 | break; |
734 | case ISCSI_OP_NOOP_IN: | 726 | case ISCSI_OP_NOOP_IN: |
735 | if (hdr->ttt != ISCSI_RESERVED_TAG) { | 727 | if (hdr->ttt != ISCSI_RESERVED_TAG) { |
736 | rc = ISCSI_ERR_PROTO; | 728 | rc = ISCSI_ERR_PROTO; |
737 | break; | 729 | break; |
738 | } | 730 | } |
739 | rc = iscsi_check_assign_cmdsn(session, | 731 | rc = iscsi_check_assign_cmdsn(session, |
740 | (struct iscsi_nopin*)hdr); | 732 | (struct iscsi_nopin*)hdr); |
741 | if (rc) | 733 | if (rc) |
742 | break; | 734 | break; |
@@ -771,7 +763,7 @@ iscsi_hdr_recv(struct iscsi_conn *conn) | |||
771 | if (!rc && hdr->ttt != ISCSI_RESERVED_TAG) | 763 | if (!rc && hdr->ttt != ISCSI_RESERVED_TAG) |
772 | rc = iscsi_recv_pdu(iscsi_handle(conn), | 764 | rc = iscsi_recv_pdu(iscsi_handle(conn), |
773 | hdr, NULL, 0); | 765 | hdr, NULL, 0); |
774 | } else | 766 | } else |
775 | rc = ISCSI_ERR_PROTO; | 767 | rc = ISCSI_ERR_PROTO; |
776 | break; | 768 | break; |
777 | case ISCSI_OP_REJECT: | 769 | case ISCSI_OP_REJECT: |
@@ -906,11 +898,20 @@ partial_sg_digest_update(struct iscsi_conn *conn, struct scatterlist *sg, | |||
906 | crypto_digest_update(conn->data_rx_tfm, &temp, 1); | 898 | crypto_digest_update(conn->data_rx_tfm, &temp, 1); |
907 | } | 899 | } |
908 | 900 | ||
901 | static void | ||
902 | iscsi_recv_digest_update(struct iscsi_conn *conn, char* buf, int len) | ||
903 | { | ||
904 | struct scatterlist tmp; | ||
905 | |||
906 | sg_init_one(&tmp, buf, len); | ||
907 | crypto_digest_update(conn->data_rx_tfm, &tmp, 1); | ||
908 | } | ||
909 | |||
909 | static int iscsi_scsi_data_in(struct iscsi_conn *conn) | 910 | static int iscsi_scsi_data_in(struct iscsi_conn *conn) |
910 | { | 911 | { |
911 | struct iscsi_cmd_task *ctask = conn->in.ctask; | 912 | struct iscsi_cmd_task *ctask = conn->in.ctask; |
912 | struct scsi_cmnd *sc = ctask->sc; | 913 | struct scsi_cmnd *sc = ctask->sc; |
913 | struct scatterlist tmp, *sg; | 914 | struct scatterlist *sg; |
914 | int i, offset, rc = 0; | 915 | int i, offset, rc = 0; |
915 | 916 | ||
916 | BUG_ON((void*)ctask != sc->SCp.ptr); | 917 | BUG_ON((void*)ctask != sc->SCp.ptr); |
@@ -924,10 +925,8 @@ static int iscsi_scsi_data_in(struct iscsi_conn *conn) | |||
924 | sc->request_bufflen, ctask->data_offset); | 925 | sc->request_bufflen, ctask->data_offset); |
925 | if (rc == -EAGAIN) | 926 | if (rc == -EAGAIN) |
926 | return rc; | 927 | return rc; |
927 | if (conn->datadgst_en) { | 928 | if (conn->datadgst_en) |
928 | sg_init_one(&tmp, sc->request_buffer, i); | 929 | iscsi_recv_digest_update(conn, sc->request_buffer, i); |
929 | crypto_digest_update(conn->data_rx_tfm, &tmp, 1); | ||
930 | } | ||
931 | rc = 0; | 930 | rc = 0; |
932 | goto done; | 931 | goto done; |
933 | } | 932 | } |
@@ -1021,6 +1020,9 @@ iscsi_data_recv(struct iscsi_conn *conn) | |||
1021 | conn->in.hdr = &conn->hdr; | 1020 | conn->in.hdr = &conn->hdr; |
1022 | conn->senselen = (conn->data[0] << 8) | conn->data[1]; | 1021 | conn->senselen = (conn->data[0] << 8) | conn->data[1]; |
1023 | rc = iscsi_cmd_rsp(conn, conn->in.ctask); | 1022 | rc = iscsi_cmd_rsp(conn, conn->in.ctask); |
1023 | if (!rc && conn->datadgst_en) | ||
1024 | iscsi_recv_digest_update(conn, conn->data, | ||
1025 | conn->in.datalen); | ||
1024 | } | 1026 | } |
1025 | break; | 1027 | break; |
1026 | case ISCSI_OP_TEXT_RSP: | 1028 | case ISCSI_OP_TEXT_RSP: |
@@ -1045,6 +1047,11 @@ iscsi_data_recv(struct iscsi_conn *conn) | |||
1045 | rc = iscsi_recv_pdu(iscsi_handle(conn), conn->in.hdr, | 1047 | rc = iscsi_recv_pdu(iscsi_handle(conn), conn->in.hdr, |
1046 | conn->data, conn->in.datalen); | 1048 | conn->data, conn->in.datalen); |
1047 | 1049 | ||
1050 | if (!rc && conn->datadgst_en && | ||
1051 | conn->in.opcode != ISCSI_OP_LOGIN_RSP) | ||
1052 | iscsi_recv_digest_update(conn, conn->data, | ||
1053 | conn->in.datalen); | ||
1054 | |||
1048 | if (mtask && conn->login_mtask != mtask) { | 1055 | if (mtask && conn->login_mtask != mtask) { |
1049 | spin_lock(&session->lock); | 1056 | spin_lock(&session->lock); |
1050 | __kfifo_put(session->mgmtpool.queue, (void*)&mtask, | 1057 | __kfifo_put(session->mgmtpool.queue, (void*)&mtask, |
@@ -1053,6 +1060,8 @@ iscsi_data_recv(struct iscsi_conn *conn) | |||
1053 | } | 1060 | } |
1054 | } | 1061 | } |
1055 | break; | 1062 | break; |
1063 | case ISCSI_OP_ASYNC_EVENT: | ||
1064 | case ISCSI_OP_REJECT: | ||
1056 | default: | 1065 | default: |
1057 | BUG_ON(1); | 1066 | BUG_ON(1); |
1058 | } | 1067 | } |
@@ -1114,8 +1123,7 @@ more: | |||
1114 | */ | 1123 | */ |
1115 | rc = iscsi_hdr_recv(conn); | 1124 | rc = iscsi_hdr_recv(conn); |
1116 | if (!rc && conn->in.datalen) { | 1125 | if (!rc && conn->in.datalen) { |
1117 | if (conn->datadgst_en && | 1126 | if (conn->datadgst_en) { |
1118 | conn->in.opcode == ISCSI_OP_SCSI_DATA_IN) { | ||
1119 | BUG_ON(!conn->data_rx_tfm); | 1127 | BUG_ON(!conn->data_rx_tfm); |
1120 | crypto_digest_init(conn->data_rx_tfm); | 1128 | crypto_digest_init(conn->data_rx_tfm); |
1121 | } | 1129 | } |
@@ -1127,26 +1135,24 @@ more: | |||
1127 | } | 1135 | } |
1128 | 1136 | ||
1129 | if (conn->in_progress == IN_PROGRESS_DDIGEST_RECV) { | 1137 | if (conn->in_progress == IN_PROGRESS_DDIGEST_RECV) { |
1138 | uint32_t recv_digest; | ||
1130 | debug_tcp("extra data_recv offset %d copy %d\n", | 1139 | debug_tcp("extra data_recv offset %d copy %d\n", |
1131 | conn->in.offset, conn->in.copy); | 1140 | conn->in.offset, conn->in.copy); |
1132 | if (conn->in.opcode == ISCSI_OP_SCSI_DATA_IN) { | 1141 | skb_copy_bits(conn->in.skb, conn->in.offset, |
1133 | uint32_t recv_digest; | 1142 | &recv_digest, 4); |
1134 | skb_copy_bits(conn->in.skb, conn->in.offset, | 1143 | conn->in.offset += 4; |
1135 | &recv_digest, 4); | 1144 | conn->in.copy -= 4; |
1136 | conn->in.offset += 4; | 1145 | if (recv_digest != conn->in.datadgst) { |
1137 | conn->in.copy -= 4; | 1146 | debug_tcp("iscsi_tcp: data digest error!" |
1138 | if (recv_digest != conn->in.datadgst) { | 1147 | "0x%x != 0x%x\n", recv_digest, |
1139 | debug_tcp("iscsi_tcp: data digest error!" | 1148 | conn->in.datadgst); |
1140 | "0x%x != 0x%x\n", recv_digest, | 1149 | iscsi_conn_failure(conn, ISCSI_ERR_DATA_DGST); |
1141 | conn->in.datadgst); | 1150 | return 0; |
1142 | iscsi_conn_failure(conn, ISCSI_ERR_DATA_DGST); | 1151 | } else { |
1143 | return 0; | 1152 | debug_tcp("iscsi_tcp: data digest match!" |
1144 | } else { | 1153 | "0x%x == 0x%x\n", recv_digest, |
1145 | debug_tcp("iscsi_tcp: data digest match!" | 1154 | conn->in.datadgst); |
1146 | "0x%x == 0x%x\n", recv_digest, | 1155 | conn->in_progress = IN_PROGRESS_WAIT_HEADER; |
1147 | conn->in.datadgst); | ||
1148 | conn->in_progress = IN_PROGRESS_WAIT_HEADER; | ||
1149 | } | ||
1150 | } | 1156 | } |
1151 | } | 1157 | } |
1152 | 1158 | ||
@@ -1167,8 +1173,7 @@ more: | |||
1167 | } | 1173 | } |
1168 | conn->in.copy -= conn->in.padding; | 1174 | conn->in.copy -= conn->in.padding; |
1169 | conn->in.offset += conn->in.padding; | 1175 | conn->in.offset += conn->in.padding; |
1170 | if (conn->datadgst_en && | 1176 | if (conn->datadgst_en) { |
1171 | conn->in.opcode == ISCSI_OP_SCSI_DATA_IN) { | ||
1172 | if (conn->in.padding) { | 1177 | if (conn->in.padding) { |
1173 | debug_tcp("padding -> %d\n", conn->in.padding); | 1178 | debug_tcp("padding -> %d\n", conn->in.padding); |
1174 | memset(pad, 0, conn->in.padding); | 1179 | memset(pad, 0, conn->in.padding); |
@@ -1237,8 +1242,9 @@ iscsi_tcp_state_change(struct sock *sk) | |||
1237 | conn = (struct iscsi_conn*)sk->sk_user_data; | 1242 | conn = (struct iscsi_conn*)sk->sk_user_data; |
1238 | session = conn->session; | 1243 | session = conn->session; |
1239 | 1244 | ||
1240 | if (sk->sk_state == TCP_CLOSE_WAIT || | 1245 | if ((sk->sk_state == TCP_CLOSE_WAIT || |
1241 | sk->sk_state == TCP_CLOSE) { | 1246 | sk->sk_state == TCP_CLOSE) && |
1247 | !atomic_read(&sk->sk_rmem_alloc)) { | ||
1242 | debug_tcp("iscsi_tcp_state_change: TCP_CLOSE|TCP_CLOSE_WAIT\n"); | 1248 | debug_tcp("iscsi_tcp_state_change: TCP_CLOSE|TCP_CLOSE_WAIT\n"); |
1243 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); | 1249 | iscsi_conn_failure(conn, ISCSI_ERR_CONN_FAILED); |
1244 | } | 1250 | } |
@@ -1261,7 +1267,7 @@ iscsi_write_space(struct sock *sk) | |||
1261 | conn->old_write_space(sk); | 1267 | conn->old_write_space(sk); |
1262 | debug_tcp("iscsi_write_space: cid %d\n", conn->id); | 1268 | debug_tcp("iscsi_write_space: cid %d\n", conn->id); |
1263 | clear_bit(SUSPEND_BIT, &conn->suspend_tx); | 1269 | clear_bit(SUSPEND_BIT, &conn->suspend_tx); |
1264 | schedule_work(&conn->xmitwork); | 1270 | scsi_queue_work(conn->session->host, &conn->xmitwork); |
1265 | } | 1271 | } |
1266 | 1272 | ||
1267 | static void | 1273 | static void |
@@ -1302,35 +1308,25 @@ iscsi_conn_restore_callbacks(struct iscsi_conn *conn) | |||
1302 | * @buf: buffer to write from | 1308 | * @buf: buffer to write from |
1303 | * @size: actual size to write | 1309 | * @size: actual size to write |
1304 | * @flags: socket's flags | 1310 | * @flags: socket's flags |
1305 | * | ||
1306 | * Notes: | ||
1307 | * depending on buffer will use tcp_sendpage() or tcp_sendmsg(). | ||
1308 | * buf->sg.offset == -1 tells us that buffer is non S/G and forces | ||
1309 | * to use tcp_sendmsg(). | ||
1310 | */ | 1311 | */ |
1311 | static inline int | 1312 | static inline int |
1312 | iscsi_send(struct socket *sk, struct iscsi_buf *buf, int size, int flags) | 1313 | iscsi_send(struct iscsi_conn *conn, struct iscsi_buf *buf, int size, int flags) |
1313 | { | 1314 | { |
1314 | int res; | 1315 | struct socket *sk = conn->sock; |
1315 | 1316 | int offset = buf->sg.offset + buf->sent; | |
1316 | if ((int)buf->sg.offset >= 0) { | ||
1317 | int offset = buf->sg.offset + buf->sent; | ||
1318 | |||
1319 | /* tcp_sendpage */ | ||
1320 | res = sk->ops->sendpage(sk, buf->sg.page, offset, size, flags); | ||
1321 | } else { | ||
1322 | struct msghdr msg; | ||
1323 | |||
1324 | buf->iov.iov_base = iscsi_buf_iov_base(buf); | ||
1325 | buf->iov.iov_len = size; | ||
1326 | |||
1327 | memset(&msg, 0, sizeof(struct msghdr)); | ||
1328 | |||
1329 | /* tcp_sendmsg */ | ||
1330 | res = kernel_sendmsg(sk, &msg, &buf->iov, 1, size); | ||
1331 | } | ||
1332 | 1317 | ||
1333 | return res; | 1318 | /* |
1319 | * if we got use_sg=0 or are sending something we kmallocd | ||
1320 | * then we did not have to do kmap (kmap returns page_address) | ||
1321 | * | ||
1322 | * if we got use_sg > 0, but had to drop down, we do not | ||
1323 | * set clustering so this should only happen for that | ||
1324 | * slab case. | ||
1325 | */ | ||
1326 | if (buf->use_sendmsg) | ||
1327 | return sock_no_sendpage(sk, buf->sg.page, offset, size, flags); | ||
1328 | else | ||
1329 | return conn->sendpage(sk, buf->sg.page, offset, size, flags); | ||
1334 | } | 1330 | } |
1335 | 1331 | ||
1336 | /** | 1332 | /** |
@@ -1345,7 +1341,6 @@ iscsi_send(struct socket *sk, struct iscsi_buf *buf, int size, int flags) | |||
1345 | static inline int | 1341 | static inline int |
1346 | iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen) | 1342 | iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen) |
1347 | { | 1343 | { |
1348 | struct socket *sk = conn->sock; | ||
1349 | int flags = 0; /* MSG_DONTWAIT; */ | 1344 | int flags = 0; /* MSG_DONTWAIT; */ |
1350 | int res, size; | 1345 | int res, size; |
1351 | 1346 | ||
@@ -1354,7 +1349,7 @@ iscsi_sendhdr(struct iscsi_conn *conn, struct iscsi_buf *buf, int datalen) | |||
1354 | if (buf->sent + size != buf->sg.length || datalen) | 1349 | if (buf->sent + size != buf->sg.length || datalen) |
1355 | flags |= MSG_MORE; | 1350 | flags |= MSG_MORE; |
1356 | 1351 | ||
1357 | res = iscsi_send(sk, buf, size, flags); | 1352 | res = iscsi_send(conn, buf, size, flags); |
1358 | debug_tcp("sendhdr %d bytes, sent %d res %d\n", size, buf->sent, res); | 1353 | debug_tcp("sendhdr %d bytes, sent %d res %d\n", size, buf->sent, res); |
1359 | if (res >= 0) { | 1354 | if (res >= 0) { |
1360 | conn->txdata_octets += res; | 1355 | conn->txdata_octets += res; |
@@ -1385,7 +1380,6 @@ static inline int | |||
1385 | iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf, | 1380 | iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf, |
1386 | int *count, int *sent) | 1381 | int *count, int *sent) |
1387 | { | 1382 | { |
1388 | struct socket *sk = conn->sock; | ||
1389 | int flags = 0; /* MSG_DONTWAIT; */ | 1383 | int flags = 0; /* MSG_DONTWAIT; */ |
1390 | int res, size; | 1384 | int res, size; |
1391 | 1385 | ||
@@ -1396,7 +1390,7 @@ iscsi_sendpage(struct iscsi_conn *conn, struct iscsi_buf *buf, | |||
1396 | if (buf->sent + size != buf->sg.length || *count != size) | 1390 | if (buf->sent + size != buf->sg.length || *count != size) |
1397 | flags |= MSG_MORE; | 1391 | flags |= MSG_MORE; |
1398 | 1392 | ||
1399 | res = iscsi_send(sk, buf, size, flags); | 1393 | res = iscsi_send(conn, buf, size, flags); |
1400 | debug_tcp("sendpage: %d bytes, sent %d left %d sent %d res %d\n", | 1394 | debug_tcp("sendpage: %d bytes, sent %d left %d sent %d res %d\n", |
1401 | size, buf->sent, *count, *sent, res); | 1395 | size, buf->sent, *count, *sent, res); |
1402 | if (res >= 0) { | 1396 | if (res >= 0) { |
@@ -1424,20 +1418,7 @@ iscsi_data_digest_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
1424 | ctask->digest_count = 4; | 1418 | ctask->digest_count = 4; |
1425 | } | 1419 | } |
1426 | 1420 | ||
1427 | static inline void | 1421 | static int |
1428 | iscsi_buf_data_digest_update(struct iscsi_conn *conn, struct iscsi_buf *buf) | ||
1429 | { | ||
1430 | struct scatterlist sg; | ||
1431 | |||
1432 | if (buf->sg.offset != -1) | ||
1433 | crypto_digest_update(conn->data_tx_tfm, &buf->sg, 1); | ||
1434 | else { | ||
1435 | sg_init_one(&sg, (char *)buf->sg.page, buf->sg.length); | ||
1436 | crypto_digest_update(conn->data_tx_tfm, &sg, 1); | ||
1437 | } | ||
1438 | } | ||
1439 | |||
1440 | static inline int | ||
1441 | iscsi_digest_final_send(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, | 1422 | iscsi_digest_final_send(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, |
1442 | struct iscsi_buf *buf, uint32_t *digest, int final) | 1423 | struct iscsi_buf *buf, uint32_t *digest, int final) |
1443 | { | 1424 | { |
@@ -1670,7 +1651,7 @@ iscsi_cmd_init(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask, | |||
1670 | zero_data(ctask->hdr.dlength); | 1651 | zero_data(ctask->hdr.dlength); |
1671 | } | 1652 | } |
1672 | 1653 | ||
1673 | iscsi_buf_init_virt(&ctask->headbuf, (char*)&ctask->hdr, | 1654 | iscsi_buf_init_virt(&ctask->headbuf, (char*)&ctask->hdr, |
1674 | sizeof(struct iscsi_hdr)); | 1655 | sizeof(struct iscsi_hdr)); |
1675 | conn->scsicmd_pdus_cnt++; | 1656 | conn->scsicmd_pdus_cnt++; |
1676 | } | 1657 | } |
@@ -1736,7 +1717,7 @@ static inline int | |||
1736 | handle_xmstate_r_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | 1717 | handle_xmstate_r_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) |
1737 | { | 1718 | { |
1738 | ctask->xmstate &= ~XMSTATE_R_HDR; | 1719 | ctask->xmstate &= ~XMSTATE_R_HDR; |
1739 | if (conn->hdrdgst_en) | 1720 | if (conn->hdrdgst_en) |
1740 | iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext); | 1721 | iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext); |
1741 | if (!iscsi_sendhdr(conn, &ctask->headbuf, 0)) { | 1722 | if (!iscsi_sendhdr(conn, &ctask->headbuf, 0)) { |
1742 | BUG_ON(ctask->xmstate != XMSTATE_IDLE); | 1723 | BUG_ON(ctask->xmstate != XMSTATE_IDLE); |
@@ -1750,7 +1731,7 @@ static inline int | |||
1750 | handle_xmstate_w_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | 1731 | handle_xmstate_w_hdr(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) |
1751 | { | 1732 | { |
1752 | ctask->xmstate &= ~XMSTATE_W_HDR; | 1733 | ctask->xmstate &= ~XMSTATE_W_HDR; |
1753 | if (conn->hdrdgst_en) | 1734 | if (conn->hdrdgst_en) |
1754 | iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext); | 1735 | iscsi_hdr_digest(conn, &ctask->headbuf, (u8*)ctask->hdrext); |
1755 | if (iscsi_sendhdr(conn, &ctask->headbuf, ctask->imm_count)) { | 1736 | if (iscsi_sendhdr(conn, &ctask->headbuf, ctask->imm_count)) { |
1756 | ctask->xmstate |= XMSTATE_W_HDR; | 1737 | ctask->xmstate |= XMSTATE_W_HDR; |
@@ -1799,7 +1780,8 @@ handle_xmstate_imm_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
1799 | return -EAGAIN; | 1780 | return -EAGAIN; |
1800 | } | 1781 | } |
1801 | if (conn->datadgst_en) | 1782 | if (conn->datadgst_en) |
1802 | iscsi_buf_data_digest_update(conn, &ctask->sendbuf); | 1783 | crypto_digest_update(conn->data_tx_tfm, |
1784 | &ctask->sendbuf.sg, 1); | ||
1803 | 1785 | ||
1804 | if (!ctask->imm_count) | 1786 | if (!ctask->imm_count) |
1805 | break; | 1787 | break; |
@@ -1884,7 +1866,8 @@ handle_xmstate_uns_data(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
1884 | * so pass it | 1866 | * so pass it |
1885 | */ | 1867 | */ |
1886 | if (conn->datadgst_en && ctask->sent - start > 0) | 1868 | if (conn->datadgst_en && ctask->sent - start > 0) |
1887 | iscsi_buf_data_digest_update(conn, &ctask->sendbuf); | 1869 | crypto_digest_update(conn->data_tx_tfm, |
1870 | &ctask->sendbuf.sg, 1); | ||
1888 | 1871 | ||
1889 | if (!ctask->data_count) | 1872 | if (!ctask->data_count) |
1890 | break; | 1873 | break; |
@@ -1962,7 +1945,7 @@ solicit_again: | |||
1962 | 1945 | ||
1963 | BUG_ON(r2t->data_count < 0); | 1946 | BUG_ON(r2t->data_count < 0); |
1964 | if (conn->datadgst_en) | 1947 | if (conn->datadgst_en) |
1965 | iscsi_buf_data_digest_update(conn, &r2t->sendbuf); | 1948 | crypto_digest_update(conn->data_tx_tfm, &r2t->sendbuf.sg, 1); |
1966 | 1949 | ||
1967 | if (r2t->data_count) { | 1950 | if (r2t->data_count) { |
1968 | BUG_ON(ctask->sc->use_sg == 0); | 1951 | BUG_ON(ctask->sc->use_sg == 0); |
@@ -2044,7 +2027,7 @@ handle_xmstate_w_pad(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) | |||
2044 | } | 2027 | } |
2045 | 2028 | ||
2046 | if (conn->datadgst_en) { | 2029 | if (conn->datadgst_en) { |
2047 | iscsi_buf_data_digest_update(conn, &ctask->sendbuf); | 2030 | crypto_digest_update(conn->data_tx_tfm, &ctask->sendbuf.sg, 1); |
2048 | /* imm data? */ | 2031 | /* imm data? */ |
2049 | if (!dtask) { | 2032 | if (!dtask) { |
2050 | if (iscsi_digest_final_send(conn, ctask, &ctask->immbuf, | 2033 | if (iscsi_digest_final_send(conn, ctask, &ctask->immbuf, |
@@ -2138,7 +2121,7 @@ unsolicit_head_again: | |||
2138 | solicit_head_again: | 2121 | solicit_head_again: |
2139 | r2t = ctask->r2t; | 2122 | r2t = ctask->r2t; |
2140 | if (conn->hdrdgst_en) | 2123 | if (conn->hdrdgst_en) |
2141 | iscsi_hdr_digest(conn, &r2t->headbuf, | 2124 | iscsi_hdr_digest(conn, &r2t->headbuf, |
2142 | (u8*)r2t->dtask->hdrext); | 2125 | (u8*)r2t->dtask->hdrext); |
2143 | if (iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count)) { | 2126 | if (iscsi_sendhdr(conn, &r2t->headbuf, r2t->data_count)) { |
2144 | ctask->xmstate &= ~XMSTATE_SOL_DATA; | 2127 | ctask->xmstate &= ~XMSTATE_SOL_DATA; |
@@ -2290,10 +2273,10 @@ iscsi_xmitworker(void *data) | |||
2290 | /* | 2273 | /* |
2291 | * serialize Xmit worker on a per-connection basis. | 2274 | * serialize Xmit worker on a per-connection basis. |
2292 | */ | 2275 | */ |
2293 | down(&conn->xmitsema); | 2276 | mutex_lock(&conn->xmitmutex); |
2294 | if (iscsi_data_xmit(conn)) | 2277 | if (iscsi_data_xmit(conn)) |
2295 | schedule_work(&conn->xmitwork); | 2278 | scsi_queue_work(conn->session->host, &conn->xmitwork); |
2296 | up(&conn->xmitsema); | 2279 | mutex_unlock(&conn->xmitmutex); |
2297 | } | 2280 | } |
2298 | 2281 | ||
2299 | #define FAILURE_BAD_HOST 1 | 2282 | #define FAILURE_BAD_HOST 1 |
@@ -2357,15 +2340,7 @@ iscsi_queuecommand(struct scsi_cmnd *sc, void (*done)(struct scsi_cmnd *)) | |||
2357 | session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1); | 2340 | session->cmdsn, session->max_cmdsn - session->exp_cmdsn + 1); |
2358 | spin_unlock(&session->lock); | 2341 | spin_unlock(&session->lock); |
2359 | 2342 | ||
2360 | if (!in_interrupt() && !down_trylock(&conn->xmitsema)) { | 2343 | scsi_queue_work(host, &conn->xmitwork); |
2361 | spin_unlock_irq(host->host_lock); | ||
2362 | if (iscsi_data_xmit(conn)) | ||
2363 | schedule_work(&conn->xmitwork); | ||
2364 | up(&conn->xmitsema); | ||
2365 | spin_lock_irq(host->host_lock); | ||
2366 | } else | ||
2367 | schedule_work(&conn->xmitwork); | ||
2368 | |||
2369 | return 0; | 2344 | return 0; |
2370 | 2345 | ||
2371 | reject: | 2346 | reject: |
@@ -2389,6 +2364,15 @@ fault: | |||
2389 | } | 2364 | } |
2390 | 2365 | ||
2391 | static int | 2366 | static int |
2367 | iscsi_change_queue_depth(struct scsi_device *sdev, int depth) | ||
2368 | { | ||
2369 | if (depth > ISCSI_MAX_CMD_PER_LUN) | ||
2370 | depth = ISCSI_MAX_CMD_PER_LUN; | ||
2371 | scsi_adjust_queue_depth(sdev, scsi_get_tag_type(sdev), depth); | ||
2372 | return sdev->queue_depth; | ||
2373 | } | ||
2374 | |||
2375 | static int | ||
2392 | iscsi_pool_init(struct iscsi_queue *q, int max, void ***items, int item_size) | 2376 | iscsi_pool_init(struct iscsi_queue *q, int max, void ***items, int item_size) |
2393 | { | 2377 | { |
2394 | int i; | 2378 | int i; |
@@ -2443,17 +2427,20 @@ iscsi_pool_free(struct iscsi_queue *q, void **items) | |||
2443 | kfree(items); | 2427 | kfree(items); |
2444 | } | 2428 | } |
2445 | 2429 | ||
2446 | static iscsi_connh_t | 2430 | static struct iscsi_cls_conn * |
2447 | iscsi_conn_create(iscsi_sessionh_t sessionh, uint32_t conn_idx) | 2431 | iscsi_conn_create(struct Scsi_Host *shost, uint32_t conn_idx) |
2448 | { | 2432 | { |
2449 | struct iscsi_session *session = iscsi_ptr(sessionh); | 2433 | struct iscsi_session *session = iscsi_hostdata(shost->hostdata); |
2450 | struct iscsi_conn *conn = NULL; | 2434 | struct iscsi_conn *conn; |
2435 | struct iscsi_cls_conn *cls_conn; | ||
2451 | 2436 | ||
2452 | conn = kmalloc(sizeof(struct iscsi_conn), GFP_KERNEL); | 2437 | cls_conn = iscsi_create_conn(hostdata_session(shost->hostdata), |
2453 | if (conn == NULL) | 2438 | conn_idx); |
2454 | goto conn_alloc_fail; | 2439 | if (!cls_conn) |
2455 | memset(conn, 0, sizeof(struct iscsi_conn)); | 2440 | return NULL; |
2441 | conn = cls_conn->dd_data; | ||
2456 | 2442 | ||
2443 | memset(conn, 0, sizeof(struct iscsi_conn)); | ||
2457 | conn->c_stage = ISCSI_CONN_INITIAL_STAGE; | 2444 | conn->c_stage = ISCSI_CONN_INITIAL_STAGE; |
2458 | conn->in_progress = IN_PROGRESS_WAIT_HEADER; | 2445 | conn->in_progress = IN_PROGRESS_WAIT_HEADER; |
2459 | conn->id = conn_idx; | 2446 | conn->id = conn_idx; |
@@ -2512,10 +2499,10 @@ iscsi_conn_create(iscsi_sessionh_t sessionh, uint32_t conn_idx) | |||
2512 | goto max_recv_dlenght_alloc_fail; | 2499 | goto max_recv_dlenght_alloc_fail; |
2513 | 2500 | ||
2514 | init_timer(&conn->tmabort_timer); | 2501 | init_timer(&conn->tmabort_timer); |
2515 | init_MUTEX(&conn->xmitsema); | 2502 | mutex_init(&conn->xmitmutex); |
2516 | init_waitqueue_head(&conn->ehwait); | 2503 | init_waitqueue_head(&conn->ehwait); |
2517 | 2504 | ||
2518 | return iscsi_handle(conn); | 2505 | return cls_conn; |
2519 | 2506 | ||
2520 | max_recv_dlenght_alloc_fail: | 2507 | max_recv_dlenght_alloc_fail: |
2521 | spin_lock_bh(&session->lock); | 2508 | spin_lock_bh(&session->lock); |
@@ -2531,18 +2518,18 @@ immqueue_alloc_fail: | |||
2531 | writequeue_alloc_fail: | 2518 | writequeue_alloc_fail: |
2532 | kfifo_free(conn->xmitqueue); | 2519 | kfifo_free(conn->xmitqueue); |
2533 | xmitqueue_alloc_fail: | 2520 | xmitqueue_alloc_fail: |
2534 | kfree(conn); | 2521 | iscsi_destroy_conn(cls_conn); |
2535 | conn_alloc_fail: | 2522 | return NULL; |
2536 | return iscsi_handle(NULL); | ||
2537 | } | 2523 | } |
2538 | 2524 | ||
2539 | static void | 2525 | static void |
2540 | iscsi_conn_destroy(iscsi_connh_t connh) | 2526 | iscsi_conn_destroy(struct iscsi_cls_conn *cls_conn) |
2541 | { | 2527 | { |
2542 | struct iscsi_conn *conn = iscsi_ptr(connh); | 2528 | struct iscsi_conn *conn = cls_conn->dd_data; |
2543 | struct iscsi_session *session = conn->session; | 2529 | struct iscsi_session *session = conn->session; |
2530 | unsigned long flags; | ||
2544 | 2531 | ||
2545 | down(&conn->xmitsema); | 2532 | mutex_lock(&conn->xmitmutex); |
2546 | set_bit(SUSPEND_BIT, &conn->suspend_tx); | 2533 | set_bit(SUSPEND_BIT, &conn->suspend_tx); |
2547 | if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE && conn->sock) { | 2534 | if (conn->c_stage == ISCSI_CONN_INITIAL_STAGE && conn->sock) { |
2548 | struct sock *sk = conn->sock->sk; | 2535 | struct sock *sk = conn->sock->sk; |
@@ -2573,19 +2560,19 @@ iscsi_conn_destroy(iscsi_connh_t connh) | |||
2573 | } | 2560 | } |
2574 | spin_unlock_bh(&session->lock); | 2561 | spin_unlock_bh(&session->lock); |
2575 | 2562 | ||
2576 | up(&conn->xmitsema); | 2563 | mutex_unlock(&conn->xmitmutex); |
2577 | 2564 | ||
2578 | /* | 2565 | /* |
2579 | * Block until all in-progress commands for this connection | 2566 | * Block until all in-progress commands for this connection |
2580 | * time out or fail. | 2567 | * time out or fail. |
2581 | */ | 2568 | */ |
2582 | for (;;) { | 2569 | for (;;) { |
2583 | spin_lock_bh(&conn->lock); | 2570 | spin_lock_irqsave(session->host->host_lock, flags); |
2584 | if (!session->host->host_busy) { /* OK for ERL == 0 */ | 2571 | if (!session->host->host_busy) { /* OK for ERL == 0 */ |
2585 | spin_unlock_bh(&conn->lock); | 2572 | spin_unlock_irqrestore(session->host->host_lock, flags); |
2586 | break; | 2573 | break; |
2587 | } | 2574 | } |
2588 | spin_unlock_bh(&conn->lock); | 2575 | spin_unlock_irqrestore(session->host->host_lock, flags); |
2589 | msleep_interruptible(500); | 2576 | msleep_interruptible(500); |
2590 | printk("conn_destroy(): host_busy %d host_failed %d\n", | 2577 | printk("conn_destroy(): host_busy %d host_failed %d\n", |
2591 | session->host->host_busy, session->host->host_failed); | 2578 | session->host->host_busy, session->host->host_failed); |
@@ -2633,7 +2620,8 @@ iscsi_conn_destroy(iscsi_connh_t connh) | |||
2633 | kfifo_free(conn->writequeue); | 2620 | kfifo_free(conn->writequeue); |
2634 | kfifo_free(conn->immqueue); | 2621 | kfifo_free(conn->immqueue); |
2635 | kfifo_free(conn->mgmtqueue); | 2622 | kfifo_free(conn->mgmtqueue); |
2636 | kfree(conn); | 2623 | |
2624 | iscsi_destroy_conn(cls_conn); | ||
2637 | } | 2625 | } |
2638 | 2626 | ||
2639 | static int | 2627 | static int |
@@ -2694,6 +2682,8 @@ iscsi_conn_bind(iscsi_sessionh_t sessionh, iscsi_connh_t connh, | |||
2694 | */ | 2682 | */ |
2695 | iscsi_conn_set_callbacks(conn); | 2683 | iscsi_conn_set_callbacks(conn); |
2696 | 2684 | ||
2685 | conn->sendpage = conn->sock->ops->sendpage; | ||
2686 | |||
2697 | /* | 2687 | /* |
2698 | * set receive state machine into initial state | 2688 | * set receive state machine into initial state |
2699 | */ | 2689 | */ |
@@ -2777,7 +2767,7 @@ iscsi_conn_stop(iscsi_connh_t connh, int flag) | |||
2777 | set_bit(SUSPEND_BIT, &conn->suspend_rx); | 2767 | set_bit(SUSPEND_BIT, &conn->suspend_rx); |
2778 | write_unlock_bh(&sk->sk_callback_lock); | 2768 | write_unlock_bh(&sk->sk_callback_lock); |
2779 | 2769 | ||
2780 | down(&conn->xmitsema); | 2770 | mutex_lock(&conn->xmitmutex); |
2781 | 2771 | ||
2782 | spin_lock_irqsave(session->host->host_lock, flags); | 2772 | spin_lock_irqsave(session->host->host_lock, flags); |
2783 | spin_lock(&session->lock); | 2773 | spin_lock(&session->lock); |
@@ -2853,10 +2843,13 @@ iscsi_conn_stop(iscsi_connh_t connh, int flag) | |||
2853 | * in hdr_extract() and will be re-negotiated at | 2843 | * in hdr_extract() and will be re-negotiated at |
2854 | * set_param() time. | 2844 | * set_param() time. |
2855 | */ | 2845 | */ |
2856 | if (flag == STOP_CONN_RECOVER) | 2846 | if (flag == STOP_CONN_RECOVER) { |
2857 | conn->hdr_size = sizeof(struct iscsi_hdr); | 2847 | conn->hdr_size = sizeof(struct iscsi_hdr); |
2848 | conn->hdrdgst_en = 0; | ||
2849 | conn->datadgst_en = 0; | ||
2850 | } | ||
2858 | } | 2851 | } |
2859 | up(&conn->xmitsema); | 2852 | mutex_unlock(&conn->xmitmutex); |
2860 | } | 2853 | } |
2861 | 2854 | ||
2862 | static int | 2855 | static int |
@@ -2941,8 +2934,7 @@ iscsi_conn_send_generic(struct iscsi_conn *conn, struct iscsi_hdr *hdr, | |||
2941 | else | 2934 | else |
2942 | __kfifo_put(conn->mgmtqueue, (void*)&mtask, sizeof(void*)); | 2935 | __kfifo_put(conn->mgmtqueue, (void*)&mtask, sizeof(void*)); |
2943 | 2936 | ||
2944 | schedule_work(&conn->xmitwork); | 2937 | scsi_queue_work(session->host, &conn->xmitwork); |
2945 | |||
2946 | return 0; | 2938 | return 0; |
2947 | } | 2939 | } |
2948 | 2940 | ||
@@ -3007,12 +2999,12 @@ iscsi_eh_abort(struct scsi_cmnd *sc) | |||
3007 | * 1) connection-level failure; | 2999 | * 1) connection-level failure; |
3008 | * 2) recovery due protocol error; | 3000 | * 2) recovery due protocol error; |
3009 | */ | 3001 | */ |
3010 | down(&conn->xmitsema); | 3002 | mutex_lock(&conn->xmitmutex); |
3011 | spin_lock_bh(&session->lock); | 3003 | spin_lock_bh(&session->lock); |
3012 | if (session->state != ISCSI_STATE_LOGGED_IN) { | 3004 | if (session->state != ISCSI_STATE_LOGGED_IN) { |
3013 | if (session->state == ISCSI_STATE_TERMINATE) { | 3005 | if (session->state == ISCSI_STATE_TERMINATE) { |
3014 | spin_unlock_bh(&session->lock); | 3006 | spin_unlock_bh(&session->lock); |
3015 | up(&conn->xmitsema); | 3007 | mutex_unlock(&conn->xmitmutex); |
3016 | goto failed; | 3008 | goto failed; |
3017 | } | 3009 | } |
3018 | spin_unlock_bh(&session->lock); | 3010 | spin_unlock_bh(&session->lock); |
@@ -3030,7 +3022,7 @@ iscsi_eh_abort(struct scsi_cmnd *sc) | |||
3030 | * 2) session was re-open during time out of ctask. | 3022 | * 2) session was re-open during time out of ctask. |
3031 | */ | 3023 | */ |
3032 | spin_unlock_bh(&session->lock); | 3024 | spin_unlock_bh(&session->lock); |
3033 | up(&conn->xmitsema); | 3025 | mutex_unlock(&conn->xmitmutex); |
3034 | goto success; | 3026 | goto success; |
3035 | } | 3027 | } |
3036 | conn->tmabort_state = TMABORT_INITIAL; | 3028 | conn->tmabort_state = TMABORT_INITIAL; |
@@ -3085,7 +3077,7 @@ iscsi_eh_abort(struct scsi_cmnd *sc) | |||
3085 | conn->tmabort_state == TMABORT_SUCCESS) { | 3077 | conn->tmabort_state == TMABORT_SUCCESS) { |
3086 | conn->tmabort_state = TMABORT_INITIAL; | 3078 | conn->tmabort_state = TMABORT_INITIAL; |
3087 | spin_unlock_bh(&session->lock); | 3079 | spin_unlock_bh(&session->lock); |
3088 | up(&conn->xmitsema); | 3080 | mutex_unlock(&conn->xmitmutex); |
3089 | goto success; | 3081 | goto success; |
3090 | } | 3082 | } |
3091 | conn->tmabort_state = TMABORT_INITIAL; | 3083 | conn->tmabort_state = TMABORT_INITIAL; |
@@ -3094,7 +3086,7 @@ iscsi_eh_abort(struct scsi_cmnd *sc) | |||
3094 | spin_unlock_bh(&session->lock); | 3086 | spin_unlock_bh(&session->lock); |
3095 | } | 3087 | } |
3096 | } | 3088 | } |
3097 | up(&conn->xmitsema); | 3089 | mutex_unlock(&conn->xmitmutex); |
3098 | 3090 | ||
3099 | 3091 | ||
3100 | /* | 3092 | /* |
@@ -3160,7 +3152,7 @@ failed: | |||
3160 | exit: | 3152 | exit: |
3161 | del_timer_sync(&conn->tmabort_timer); | 3153 | del_timer_sync(&conn->tmabort_timer); |
3162 | 3154 | ||
3163 | down(&conn->xmitsema); | 3155 | mutex_lock(&conn->xmitmutex); |
3164 | if (conn->sock) { | 3156 | if (conn->sock) { |
3165 | struct sock *sk = conn->sock->sk; | 3157 | struct sock *sk = conn->sock->sk; |
3166 | 3158 | ||
@@ -3168,7 +3160,7 @@ exit: | |||
3168 | iscsi_ctask_cleanup(conn, ctask); | 3160 | iscsi_ctask_cleanup(conn, ctask); |
3169 | write_unlock_bh(&sk->sk_callback_lock); | 3161 | write_unlock_bh(&sk->sk_callback_lock); |
3170 | } | 3162 | } |
3171 | up(&conn->xmitsema); | 3163 | mutex_unlock(&conn->xmitmutex); |
3172 | return rc; | 3164 | return rc; |
3173 | } | 3165 | } |
3174 | 3166 | ||
@@ -3247,28 +3239,35 @@ iscsi_r2tpool_free(struct iscsi_session *session) | |||
3247 | static struct scsi_host_template iscsi_sht = { | 3239 | static struct scsi_host_template iscsi_sht = { |
3248 | .name = "iSCSI Initiator over TCP/IP, v." | 3240 | .name = "iSCSI Initiator over TCP/IP, v." |
3249 | ISCSI_VERSION_STR, | 3241 | ISCSI_VERSION_STR, |
3250 | .queuecommand = iscsi_queuecommand, | 3242 | .queuecommand = iscsi_queuecommand, |
3243 | .change_queue_depth = iscsi_change_queue_depth, | ||
3251 | .can_queue = ISCSI_XMIT_CMDS_MAX - 1, | 3244 | .can_queue = ISCSI_XMIT_CMDS_MAX - 1, |
3252 | .sg_tablesize = ISCSI_SG_TABLESIZE, | 3245 | .sg_tablesize = ISCSI_SG_TABLESIZE, |
3253 | .cmd_per_lun = ISCSI_CMD_PER_LUN, | 3246 | .cmd_per_lun = ISCSI_DEF_CMD_PER_LUN, |
3254 | .eh_abort_handler = iscsi_eh_abort, | 3247 | .eh_abort_handler = iscsi_eh_abort, |
3255 | .eh_host_reset_handler = iscsi_eh_host_reset, | 3248 | .eh_host_reset_handler = iscsi_eh_host_reset, |
3256 | .use_clustering = DISABLE_CLUSTERING, | 3249 | .use_clustering = DISABLE_CLUSTERING, |
3257 | .proc_name = "iscsi_tcp", | 3250 | .proc_name = "iscsi_tcp", |
3258 | .this_id = -1, | 3251 | .this_id = -1, |
3259 | }; | 3252 | }; |
3260 | 3253 | ||
3261 | static iscsi_sessionh_t | 3254 | static struct iscsi_transport iscsi_tcp_transport; |
3262 | iscsi_session_create(uint32_t initial_cmdsn, struct Scsi_Host *host) | 3255 | |
3256 | static struct Scsi_Host * | ||
3257 | iscsi_session_create(struct scsi_transport_template *scsit, | ||
3258 | uint32_t initial_cmdsn) | ||
3263 | { | 3259 | { |
3264 | int cmd_i; | 3260 | struct Scsi_Host *shost; |
3265 | struct iscsi_session *session; | 3261 | struct iscsi_session *session; |
3262 | int cmd_i; | ||
3266 | 3263 | ||
3267 | session = iscsi_hostdata(host->hostdata); | 3264 | shost = iscsi_transport_create_session(scsit, &iscsi_tcp_transport); |
3268 | memset(session, 0, sizeof(struct iscsi_session)); | 3265 | if (!shost) |
3266 | return NULL; | ||
3269 | 3267 | ||
3270 | session->host = host; | 3268 | session = iscsi_hostdata(shost->hostdata); |
3271 | session->id = host->host_no; | 3269 | memset(session, 0, sizeof(struct iscsi_session)); |
3270 | session->host = shost; | ||
3272 | session->state = ISCSI_STATE_LOGGED_IN; | 3271 | session->state = ISCSI_STATE_LOGGED_IN; |
3273 | session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX; | 3272 | session->mgmtpool_max = ISCSI_MGMT_CMDS_MAX; |
3274 | session->cmds_max = ISCSI_XMIT_CMDS_MAX; | 3273 | session->cmds_max = ISCSI_XMIT_CMDS_MAX; |
@@ -3312,7 +3311,7 @@ iscsi_session_create(uint32_t initial_cmdsn, struct Scsi_Host *host) | |||
3312 | if (iscsi_r2tpool_alloc(session)) | 3311 | if (iscsi_r2tpool_alloc(session)) |
3313 | goto r2tpool_alloc_fail; | 3312 | goto r2tpool_alloc_fail; |
3314 | 3313 | ||
3315 | return iscsi_handle(session); | 3314 | return shost; |
3316 | 3315 | ||
3317 | r2tpool_alloc_fail: | 3316 | r2tpool_alloc_fail: |
3318 | for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) | 3317 | for (cmd_i = 0; cmd_i < session->mgmtpool_max; cmd_i++) |
@@ -3322,15 +3321,15 @@ immdata_alloc_fail: | |||
3322 | mgmtpool_alloc_fail: | 3321 | mgmtpool_alloc_fail: |
3323 | iscsi_pool_free(&session->cmdpool, (void**)session->cmds); | 3322 | iscsi_pool_free(&session->cmdpool, (void**)session->cmds); |
3324 | cmdpool_alloc_fail: | 3323 | cmdpool_alloc_fail: |
3325 | return iscsi_handle(NULL); | 3324 | return NULL; |
3326 | } | 3325 | } |
3327 | 3326 | ||
3328 | static void | 3327 | static void |
3329 | iscsi_session_destroy(iscsi_sessionh_t sessionh) | 3328 | iscsi_session_destroy(struct Scsi_Host *shost) |
3330 | { | 3329 | { |
3330 | struct iscsi_session *session = iscsi_hostdata(shost->hostdata); | ||
3331 | int cmd_i; | 3331 | int cmd_i; |
3332 | struct iscsi_data_task *dtask, *n; | 3332 | struct iscsi_data_task *dtask, *n; |
3333 | struct iscsi_session *session = iscsi_ptr(sessionh); | ||
3334 | 3333 | ||
3335 | for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { | 3334 | for (cmd_i = 0; cmd_i < session->cmds_max; cmd_i++) { |
3336 | struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; | 3335 | struct iscsi_cmd_task *ctask = session->cmds[cmd_i]; |
@@ -3346,6 +3345,8 @@ iscsi_session_destroy(iscsi_sessionh_t sessionh) | |||
3346 | iscsi_r2tpool_free(session); | 3345 | iscsi_r2tpool_free(session); |
3347 | iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds); | 3346 | iscsi_pool_free(&session->mgmtpool, (void**)session->mgmt_cmds); |
3348 | iscsi_pool_free(&session->cmdpool, (void**)session->cmds); | 3347 | iscsi_pool_free(&session->cmdpool, (void**)session->cmds); |
3348 | |||
3349 | iscsi_transport_destroy_session(shost); | ||
3349 | } | 3350 | } |
3350 | 3351 | ||
3351 | static int | 3352 | static int |
@@ -3444,6 +3445,8 @@ iscsi_conn_set_param(iscsi_connh_t connh, enum iscsi_param param, | |||
3444 | if (conn->data_rx_tfm) | 3445 | if (conn->data_rx_tfm) |
3445 | crypto_free_tfm(conn->data_rx_tfm); | 3446 | crypto_free_tfm(conn->data_rx_tfm); |
3446 | } | 3447 | } |
3448 | conn->sendpage = conn->datadgst_en ? | ||
3449 | sock_no_sendpage : conn->sock->ops->sendpage; | ||
3447 | break; | 3450 | break; |
3448 | case ISCSI_PARAM_INITIAL_R2T_EN: | 3451 | case ISCSI_PARAM_INITIAL_R2T_EN: |
3449 | session->initial_r2t_en = value; | 3452 | session->initial_r2t_en = value; |
@@ -3492,25 +3495,12 @@ iscsi_conn_set_param(iscsi_connh_t connh, enum iscsi_param param, | |||
3492 | } | 3495 | } |
3493 | 3496 | ||
3494 | static int | 3497 | static int |
3495 | iscsi_conn_get_param(iscsi_connh_t connh, enum iscsi_param param, | 3498 | iscsi_session_get_param(struct Scsi_Host *shost, |
3496 | uint32_t *value) | 3499 | enum iscsi_param param, uint32_t *value) |
3497 | { | 3500 | { |
3498 | struct iscsi_conn *conn = iscsi_ptr(connh); | 3501 | struct iscsi_session *session = iscsi_hostdata(shost->hostdata); |
3499 | struct iscsi_session *session = conn->session; | ||
3500 | 3502 | ||
3501 | switch(param) { | 3503 | switch(param) { |
3502 | case ISCSI_PARAM_MAX_RECV_DLENGTH: | ||
3503 | *value = conn->max_recv_dlength; | ||
3504 | break; | ||
3505 | case ISCSI_PARAM_MAX_XMIT_DLENGTH: | ||
3506 | *value = conn->max_xmit_dlength; | ||
3507 | break; | ||
3508 | case ISCSI_PARAM_HDRDGST_EN: | ||
3509 | *value = conn->hdrdgst_en; | ||
3510 | break; | ||
3511 | case ISCSI_PARAM_DATADGST_EN: | ||
3512 | *value = conn->datadgst_en; | ||
3513 | break; | ||
3514 | case ISCSI_PARAM_INITIAL_R2T_EN: | 3504 | case ISCSI_PARAM_INITIAL_R2T_EN: |
3515 | *value = session->initial_r2t_en; | 3505 | *value = session->initial_r2t_en; |
3516 | break; | 3506 | break; |
@@ -3548,6 +3538,31 @@ iscsi_conn_get_param(iscsi_connh_t connh, enum iscsi_param param, | |||
3548 | return 0; | 3538 | return 0; |
3549 | } | 3539 | } |
3550 | 3540 | ||
3541 | static int | ||
3542 | iscsi_conn_get_param(void *data, enum iscsi_param param, uint32_t *value) | ||
3543 | { | ||
3544 | struct iscsi_conn *conn = data; | ||
3545 | |||
3546 | switch(param) { | ||
3547 | case ISCSI_PARAM_MAX_RECV_DLENGTH: | ||
3548 | *value = conn->max_recv_dlength; | ||
3549 | break; | ||
3550 | case ISCSI_PARAM_MAX_XMIT_DLENGTH: | ||
3551 | *value = conn->max_xmit_dlength; | ||
3552 | break; | ||
3553 | case ISCSI_PARAM_HDRDGST_EN: | ||
3554 | *value = conn->hdrdgst_en; | ||
3555 | break; | ||
3556 | case ISCSI_PARAM_DATADGST_EN: | ||
3557 | *value = conn->datadgst_en; | ||
3558 | break; | ||
3559 | default: | ||
3560 | return ISCSI_ERR_PARAM_NOT_FOUND; | ||
3561 | } | ||
3562 | |||
3563 | return 0; | ||
3564 | } | ||
3565 | |||
3551 | static void | 3566 | static void |
3552 | iscsi_conn_get_stats(iscsi_connh_t connh, struct iscsi_stats *stats) | 3567 | iscsi_conn_get_stats(iscsi_connh_t connh, struct iscsi_stats *stats) |
3553 | { | 3568 | { |
@@ -3578,9 +3593,9 @@ iscsi_conn_send_pdu(iscsi_connh_t connh, struct iscsi_hdr *hdr, char *data, | |||
3578 | struct iscsi_conn *conn = iscsi_ptr(connh); | 3593 | struct iscsi_conn *conn = iscsi_ptr(connh); |
3579 | int rc; | 3594 | int rc; |
3580 | 3595 | ||
3581 | down(&conn->xmitsema); | 3596 | mutex_lock(&conn->xmitmutex); |
3582 | rc = iscsi_conn_send_generic(conn, hdr, data, data_size); | 3597 | rc = iscsi_conn_send_generic(conn, hdr, data, data_size); |
3583 | up(&conn->xmitsema); | 3598 | mutex_unlock(&conn->xmitmutex); |
3584 | 3599 | ||
3585 | return rc; | 3600 | return rc; |
3586 | } | 3601 | } |
@@ -3592,6 +3607,7 @@ static struct iscsi_transport iscsi_tcp_transport = { | |||
3592 | | CAP_DATADGST, | 3607 | | CAP_DATADGST, |
3593 | .host_template = &iscsi_sht, | 3608 | .host_template = &iscsi_sht, |
3594 | .hostdata_size = sizeof(struct iscsi_session), | 3609 | .hostdata_size = sizeof(struct iscsi_session), |
3610 | .conndata_size = sizeof(struct iscsi_conn), | ||
3595 | .max_conn = 1, | 3611 | .max_conn = 1, |
3596 | .max_cmd_len = ISCSI_TCP_MAX_CMD_LEN, | 3612 | .max_cmd_len = ISCSI_TCP_MAX_CMD_LEN, |
3597 | .create_session = iscsi_session_create, | 3613 | .create_session = iscsi_session_create, |
@@ -3600,7 +3616,8 @@ static struct iscsi_transport iscsi_tcp_transport = { | |||
3600 | .bind_conn = iscsi_conn_bind, | 3616 | .bind_conn = iscsi_conn_bind, |
3601 | .destroy_conn = iscsi_conn_destroy, | 3617 | .destroy_conn = iscsi_conn_destroy, |
3602 | .set_param = iscsi_conn_set_param, | 3618 | .set_param = iscsi_conn_set_param, |
3603 | .get_param = iscsi_conn_get_param, | 3619 | .get_conn_param = iscsi_conn_get_param, |
3620 | .get_session_param = iscsi_session_get_param, | ||
3604 | .start_conn = iscsi_conn_start, | 3621 | .start_conn = iscsi_conn_start, |
3605 | .stop_conn = iscsi_conn_stop, | 3622 | .stop_conn = iscsi_conn_stop, |
3606 | .send_pdu = iscsi_conn_send_pdu, | 3623 | .send_pdu = iscsi_conn_send_pdu, |
@@ -3610,8 +3627,6 @@ static struct iscsi_transport iscsi_tcp_transport = { | |||
3610 | static int __init | 3627 | static int __init |
3611 | iscsi_tcp_init(void) | 3628 | iscsi_tcp_init(void) |
3612 | { | 3629 | { |
3613 | int error; | ||
3614 | |||
3615 | if (iscsi_max_lun < 1) { | 3630 | if (iscsi_max_lun < 1) { |
3616 | printk(KERN_ERR "Invalid max_lun value of %u\n", iscsi_max_lun); | 3631 | printk(KERN_ERR "Invalid max_lun value of %u\n", iscsi_max_lun); |
3617 | return -EINVAL; | 3632 | return -EINVAL; |
@@ -3624,11 +3639,10 @@ iscsi_tcp_init(void) | |||
3624 | if (!taskcache) | 3639 | if (!taskcache) |
3625 | return -ENOMEM; | 3640 | return -ENOMEM; |
3626 | 3641 | ||
3627 | error = iscsi_register_transport(&iscsi_tcp_transport); | 3642 | if (!iscsi_register_transport(&iscsi_tcp_transport)) |
3628 | if (error) | ||
3629 | kmem_cache_destroy(taskcache); | 3643 | kmem_cache_destroy(taskcache); |
3630 | 3644 | ||
3631 | return error; | 3645 | return 0; |
3632 | } | 3646 | } |
3633 | 3647 | ||
3634 | static void __exit | 3648 | static void __exit |