aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2013-03-07 01:18:24 -0500
committerNicholas Bellinger <nab@linux-iscsi.org>2013-04-25 04:05:27 -0400
commit3e1c81a95f0d776cea68a36cfc78a0ce8f6d3a77 (patch)
tree99ceb306765cc6231c32b65c0a9766ab781caf76
parentcdb726651c357c19c02b17ee3c99a224b03022b6 (diff)
iscsi-target: Refactor RX PDU logic + export request PDU handling
This patch refactors existing traditional iscsi RX side PDU handling to use iscsit_transport, and exports the necessary logic for external transport modules. This includes: - Refactor iscsit_handle_scsi_cmd() into PDU setup / processing - Add updated iscsit_handle_scsi_cmd() for tradtional iscsi code - Add iscsit_set_unsoliticed_dataout() wrapper - Refactor iscsit_handle_data_out() into PDU check / processing - Add updated iscsit_handle_data_out() for tradtional iscsi code - Add iscsit_handle_nop_out() + iscsit_handle_task_mgt_cmd() to accept pre-allocated struct iscsi_cmd - Add iscsit_build_r2ts_for_cmd() caller for iscsi_target_transport to handle ISTATE_SEND_R2T for TX immediate queue - Refactor main traditional iscsi iscsi_target_rx_thread() PDU switch into iscsi_target_rx_opcode() using iscsit_allocate_cmd() - Turn iscsi_target_rx_thread() process context into NOP for ib_isert side work-queue. v5 changes: - Make iscsit_handle_scsi_cmd() static (Fengguang) - Fix iscsit_handle_scsi_cmd() exception se_cmd leak (nab) v3 changes: - Add extra target_put_sess_cmd call in iscsit_add_reject_from_cmd after completion v2 changes: - Disable iscsit_ack_from_expstatsn() usage for RDMAExtentions=Yes - Disable iscsit_allocate_datain_req() usage for RDMAExtentions=Yes - Add target_get_sess_cmd() reference counting to iscsit_setup_scsi_cmd() - Add TFO->lio_check_stop_free() fabric API caller - Add export of iscsit_stop_dataout_timer() symbol - Add iscsit_build_r2ts_for_cmd() for iscsit_transport->iscsit_get_dataout() - Convert existing usage of iscsit_build_r2ts_for_cmd() to ->iscsit_get_dataout() - Drop RDMAExtentions=Yes specific check in iscsit_build_r2ts_for_cmd() - Fix RDMAExtentions -> RDMAExtensions typo (andy) - Pass correct dump_payload value into iscsit_get_immediate_data() for iscsit_handle_scsi_cmd() Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r--drivers/target/iscsi/iscsi_target.c503
-rw-r--r--drivers/target/iscsi/iscsi_target.h3
-rw-r--r--drivers/target/iscsi/iscsi_target_configfs.c9
-rw-r--r--drivers/target/iscsi/iscsi_target_erl1.c13
-rw-r--r--drivers/target/iscsi/iscsi_target_login.c3
-rw-r--r--drivers/target/iscsi/iscsi_target_nego.c15
-rw-r--r--drivers/target/iscsi/iscsi_target_tmr.c3
-rw-r--r--drivers/target/iscsi/iscsi_target_util.c1
8 files changed, 346 insertions, 204 deletions
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index b01a10eae365..40bb916f57ff 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -492,6 +492,7 @@ static struct iscsit_transport iscsi_target_transport = {
492 .iscsit_alloc_cmd = iscsit_alloc_cmd, 492 .iscsit_alloc_cmd = iscsit_alloc_cmd,
493 .iscsit_get_login_rx = iscsit_get_login_rx, 493 .iscsit_get_login_rx = iscsit_get_login_rx,
494 .iscsit_put_login_tx = iscsit_put_login_tx, 494 .iscsit_put_login_tx = iscsit_put_login_tx,
495 .iscsit_get_dataout = iscsit_build_r2ts_for_cmd,
495}; 496};
496 497
497static int __init iscsi_target_init_module(void) 498static int __init iscsi_target_init_module(void)
@@ -650,6 +651,14 @@ static int iscsit_add_reject(
650 iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state); 651 iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
651 652
652 ret = wait_for_completion_interruptible(&cmd->reject_comp); 653 ret = wait_for_completion_interruptible(&cmd->reject_comp);
654 /*
655 * Perform the kref_put now if se_cmd has been setup by
656 * iscsit_setup_scsi_cmd()
657 */
658 if (cmd->se_cmd.se_tfo != NULL) {
659 pr_debug("iscsi reject: calling target_put_sess_cmd >>>>>>\n");
660 target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
661 }
653 if (ret != 0) 662 if (ret != 0)
654 return -1; 663 return -1;
655 664
@@ -698,11 +707,20 @@ int iscsit_add_reject_from_cmd(
698 iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state); 707 iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
699 708
700 ret = wait_for_completion_interruptible(&cmd->reject_comp); 709 ret = wait_for_completion_interruptible(&cmd->reject_comp);
710 /*
711 * Perform the kref_put now if se_cmd has already been setup by
712 * scsit_setup_scsi_cmd()
713 */
714 if (cmd->se_cmd.se_tfo != NULL) {
715 pr_debug("iscsi reject: calling target_put_sess_cmd >>>>>>\n");
716 target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
717 }
701 if (ret != 0) 718 if (ret != 0)
702 return -1; 719 return -1;
703 720
704 return (!fail_conn) ? 0 : -1; 721 return (!fail_conn) ? 0 : -1;
705} 722}
723EXPORT_SYMBOL(iscsit_add_reject_from_cmd);
706 724
707/* 725/*
708 * Map some portion of the allocated scatterlist to an iovec, suitable for 726 * Map some portion of the allocated scatterlist to an iovec, suitable for
@@ -761,6 +779,9 @@ static void iscsit_ack_from_expstatsn(struct iscsi_conn *conn, u32 exp_statsn)
761 779
762 conn->exp_statsn = exp_statsn; 780 conn->exp_statsn = exp_statsn;
763 781
782 if (conn->sess->sess_ops->RDMAExtensions)
783 return;
784
764 spin_lock_bh(&conn->cmd_lock); 785 spin_lock_bh(&conn->cmd_lock);
765 list_for_each_entry(cmd, &conn->conn_cmd_list, i_conn_node) { 786 list_for_each_entry(cmd, &conn->conn_cmd_list, i_conn_node) {
766 spin_lock(&cmd->istate_lock); 787 spin_lock(&cmd->istate_lock);
@@ -793,12 +814,10 @@ static int iscsit_allocate_iovecs(struct iscsi_cmd *cmd)
793 return 0; 814 return 0;
794} 815}
795 816
796static int iscsit_handle_scsi_cmd( 817int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
797 struct iscsi_conn *conn, 818 unsigned char *buf)
798 unsigned char *buf)
799{ 819{
800 int data_direction, payload_length, cmdsn_ret = 0, immed_ret; 820 int data_direction, payload_length;
801 struct iscsi_cmd *cmd = NULL;
802 struct iscsi_scsi_req *hdr; 821 struct iscsi_scsi_req *hdr;
803 int iscsi_task_attr; 822 int iscsi_task_attr;
804 int sam_task_attr; 823 int sam_task_attr;
@@ -821,8 +840,8 @@ static int iscsit_handle_scsi_cmd(
821 !(hdr->flags & ISCSI_FLAG_CMD_FINAL)) { 840 !(hdr->flags & ISCSI_FLAG_CMD_FINAL)) {
822 pr_err("ISCSI_FLAG_CMD_WRITE & ISCSI_FLAG_CMD_FINAL" 841 pr_err("ISCSI_FLAG_CMD_WRITE & ISCSI_FLAG_CMD_FINAL"
823 " not set. Bad iSCSI Initiator.\n"); 842 " not set. Bad iSCSI Initiator.\n");
824 return iscsit_add_reject(ISCSI_REASON_BOOKMARK_INVALID, 1, 843 return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID,
825 buf, conn); 844 1, 1, buf, cmd);
826 } 845 }
827 846
828 if (((hdr->flags & ISCSI_FLAG_CMD_READ) || 847 if (((hdr->flags & ISCSI_FLAG_CMD_READ) ||
@@ -842,8 +861,8 @@ static int iscsit_handle_scsi_cmd(
842 pr_err("ISCSI_FLAG_CMD_READ or ISCSI_FLAG_CMD_WRITE" 861 pr_err("ISCSI_FLAG_CMD_READ or ISCSI_FLAG_CMD_WRITE"
843 " set when Expected Data Transfer Length is 0 for" 862 " set when Expected Data Transfer Length is 0 for"
844 " CDB: 0x%02x. Bad iSCSI Initiator.\n", hdr->cdb[0]); 863 " CDB: 0x%02x. Bad iSCSI Initiator.\n", hdr->cdb[0]);
845 return iscsit_add_reject(ISCSI_REASON_BOOKMARK_INVALID, 1, 864 return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID,
846 buf, conn); 865 1, 1, buf, cmd);
847 } 866 }
848done: 867done:
849 868
@@ -852,29 +871,29 @@ done:
852 pr_err("ISCSI_FLAG_CMD_READ and/or ISCSI_FLAG_CMD_WRITE" 871 pr_err("ISCSI_FLAG_CMD_READ and/or ISCSI_FLAG_CMD_WRITE"
853 " MUST be set if Expected Data Transfer Length is not 0." 872 " MUST be set if Expected Data Transfer Length is not 0."
854 " Bad iSCSI Initiator\n"); 873 " Bad iSCSI Initiator\n");
855 return iscsit_add_reject(ISCSI_REASON_BOOKMARK_INVALID, 1, 874 return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID,
856 buf, conn); 875 1, 1, buf, cmd);
857 } 876 }
858 877
859 if ((hdr->flags & ISCSI_FLAG_CMD_READ) && 878 if ((hdr->flags & ISCSI_FLAG_CMD_READ) &&
860 (hdr->flags & ISCSI_FLAG_CMD_WRITE)) { 879 (hdr->flags & ISCSI_FLAG_CMD_WRITE)) {
861 pr_err("Bidirectional operations not supported!\n"); 880 pr_err("Bidirectional operations not supported!\n");
862 return iscsit_add_reject(ISCSI_REASON_BOOKMARK_INVALID, 1, 881 return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID,
863 buf, conn); 882 1, 1, buf, cmd);
864 } 883 }
865 884
866 if (hdr->opcode & ISCSI_OP_IMMEDIATE) { 885 if (hdr->opcode & ISCSI_OP_IMMEDIATE) {
867 pr_err("Illegally set Immediate Bit in iSCSI Initiator" 886 pr_err("Illegally set Immediate Bit in iSCSI Initiator"
868 " Scsi Command PDU.\n"); 887 " Scsi Command PDU.\n");
869 return iscsit_add_reject(ISCSI_REASON_BOOKMARK_INVALID, 1, 888 return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID,
870 buf, conn); 889 1, 1, buf, cmd);
871 } 890 }
872 891
873 if (payload_length && !conn->sess->sess_ops->ImmediateData) { 892 if (payload_length && !conn->sess->sess_ops->ImmediateData) {
874 pr_err("ImmediateData=No but DataSegmentLength=%u," 893 pr_err("ImmediateData=No but DataSegmentLength=%u,"
875 " protocol error.\n", payload_length); 894 " protocol error.\n", payload_length);
876 return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, 895 return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
877 buf, conn); 896 1, 1, buf, cmd);
878 } 897 }
879 898
880 if ((be32_to_cpu(hdr->data_length )== payload_length) && 899 if ((be32_to_cpu(hdr->data_length )== payload_length) &&
@@ -882,43 +901,38 @@ done:
882 pr_err("Expected Data Transfer Length and Length of" 901 pr_err("Expected Data Transfer Length and Length of"
883 " Immediate Data are the same, but ISCSI_FLAG_CMD_FINAL" 902 " Immediate Data are the same, but ISCSI_FLAG_CMD_FINAL"
884 " bit is not set protocol error\n"); 903 " bit is not set protocol error\n");
885 return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, 904 return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
886 buf, conn); 905 1, 1, buf, cmd);
887 } 906 }
888 907
889 if (payload_length > be32_to_cpu(hdr->data_length)) { 908 if (payload_length > be32_to_cpu(hdr->data_length)) {
890 pr_err("DataSegmentLength: %u is greater than" 909 pr_err("DataSegmentLength: %u is greater than"
891 " EDTL: %u, protocol error.\n", payload_length, 910 " EDTL: %u, protocol error.\n", payload_length,
892 hdr->data_length); 911 hdr->data_length);
893 return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, 912 return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
894 buf, conn); 913 1, 1, buf, cmd);
895 } 914 }
896 915
897 if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) { 916 if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) {
898 pr_err("DataSegmentLength: %u is greater than" 917 pr_err("DataSegmentLength: %u is greater than"
899 " MaxXmitDataSegmentLength: %u, protocol error.\n", 918 " MaxXmitDataSegmentLength: %u, protocol error.\n",
900 payload_length, conn->conn_ops->MaxXmitDataSegmentLength); 919 payload_length, conn->conn_ops->MaxXmitDataSegmentLength);
901 return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, 920 return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
902 buf, conn); 921 1, 1, buf, cmd);
903 } 922 }
904 923
905 if (payload_length > conn->sess->sess_ops->FirstBurstLength) { 924 if (payload_length > conn->sess->sess_ops->FirstBurstLength) {
906 pr_err("DataSegmentLength: %u is greater than" 925 pr_err("DataSegmentLength: %u is greater than"
907 " FirstBurstLength: %u, protocol error.\n", 926 " FirstBurstLength: %u, protocol error.\n",
908 payload_length, conn->sess->sess_ops->FirstBurstLength); 927 payload_length, conn->sess->sess_ops->FirstBurstLength);
909 return iscsit_add_reject(ISCSI_REASON_BOOKMARK_INVALID, 1, 928 return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID,
910 buf, conn); 929 1, 1, buf, cmd);
911 } 930 }
912 931
913 data_direction = (hdr->flags & ISCSI_FLAG_CMD_WRITE) ? DMA_TO_DEVICE : 932 data_direction = (hdr->flags & ISCSI_FLAG_CMD_WRITE) ? DMA_TO_DEVICE :
914 (hdr->flags & ISCSI_FLAG_CMD_READ) ? DMA_FROM_DEVICE : 933 (hdr->flags & ISCSI_FLAG_CMD_READ) ? DMA_FROM_DEVICE :
915 DMA_NONE; 934 DMA_NONE;
916 935
917 cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
918 if (!cmd)
919 return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES, 1,
920 buf, conn);
921
922 cmd->data_direction = data_direction; 936 cmd->data_direction = data_direction;
923 iscsi_task_attr = hdr->flags & ISCSI_FLAG_CMD_ATTR_MASK; 937 iscsi_task_attr = hdr->flags & ISCSI_FLAG_CMD_ATTR_MASK;
924 /* 938 /*
@@ -961,7 +975,8 @@ done:
961 cmd->exp_stat_sn = be32_to_cpu(hdr->exp_statsn); 975 cmd->exp_stat_sn = be32_to_cpu(hdr->exp_statsn);
962 cmd->first_burst_len = payload_length; 976 cmd->first_burst_len = payload_length;
963 977
964 if (cmd->data_direction == DMA_FROM_DEVICE) { 978 if (!conn->sess->sess_ops->RDMAExtensions &&
979 cmd->data_direction == DMA_FROM_DEVICE) {
965 struct iscsi_datain_req *dr; 980 struct iscsi_datain_req *dr;
966 981
967 dr = iscsit_allocate_datain_req(); 982 dr = iscsit_allocate_datain_req();
@@ -983,7 +998,10 @@ done:
983 998
984 pr_debug("Got SCSI Command, ITT: 0x%08x, CmdSN: 0x%08x," 999 pr_debug("Got SCSI Command, ITT: 0x%08x, CmdSN: 0x%08x,"
985 " ExpXferLen: %u, Length: %u, CID: %hu\n", hdr->itt, 1000 " ExpXferLen: %u, Length: %u, CID: %hu\n", hdr->itt,
986 hdr->cmdsn, hdr->data_length, payload_length, conn->cid); 1001 hdr->cmdsn, be32_to_cpu(hdr->data_length), payload_length,
1002 conn->cid);
1003
1004 target_get_sess_cmd(conn->sess->se_sess, &cmd->se_cmd, true);
987 1005
988 cmd->sense_reason = transport_lookup_cmd_lun(&cmd->se_cmd, 1006 cmd->sense_reason = transport_lookup_cmd_lun(&cmd->se_cmd,
989 scsilun_to_int(&hdr->lun)); 1007 scsilun_to_int(&hdr->lun));
@@ -1017,12 +1035,24 @@ attach_cmd:
1017 */ 1035 */
1018 core_alua_check_nonop_delay(&cmd->se_cmd); 1036 core_alua_check_nonop_delay(&cmd->se_cmd);
1019 1037
1020 if (iscsit_allocate_iovecs(cmd) < 0) { 1038 return 0;
1021 return iscsit_add_reject_from_cmd( 1039}
1022 ISCSI_REASON_BOOKMARK_NO_RESOURCES, 1040EXPORT_SYMBOL(iscsit_setup_scsi_cmd);
1023 1, 0, buf, cmd);
1024 }
1025 1041
1042void iscsit_set_unsoliticed_dataout(struct iscsi_cmd *cmd)
1043{
1044 iscsit_set_dataout_sequence_values(cmd);
1045
1046 spin_lock_bh(&cmd->dataout_timeout_lock);
1047 iscsit_start_dataout_timer(cmd, cmd->conn);
1048 spin_unlock_bh(&cmd->dataout_timeout_lock);
1049}
1050EXPORT_SYMBOL(iscsit_set_unsoliticed_dataout);
1051
1052int iscsit_process_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
1053 struct iscsi_scsi_req *hdr)
1054{
1055 int cmdsn_ret = 0;
1026 /* 1056 /*
1027 * Check the CmdSN against ExpCmdSN/MaxCmdSN here if 1057 * Check the CmdSN against ExpCmdSN/MaxCmdSN here if
1028 * the Immediate Bit is not set, and no Immediate 1058 * the Immediate Bit is not set, and no Immediate
@@ -1035,12 +1065,17 @@ attach_cmd:
1035 */ 1065 */
1036 if (!cmd->immediate_data) { 1066 if (!cmd->immediate_data) {
1037 cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); 1067 cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn);
1038 if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) 1068 if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
1069 if (!cmd->sense_reason)
1070 return 0;
1071
1072 target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
1039 return 0; 1073 return 0;
1040 else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) 1074 } else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) {
1041 return iscsit_add_reject_from_cmd( 1075 return iscsit_add_reject_from_cmd(
1042 ISCSI_REASON_PROTOCOL_ERROR, 1076 ISCSI_REASON_PROTOCOL_ERROR,
1043 1, 0, buf, cmd); 1077 1, 0, (unsigned char *)hdr, cmd);
1078 }
1044 } 1079 }
1045 1080
1046 iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn)); 1081 iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
@@ -1049,25 +1084,23 @@ attach_cmd:
1049 * If no Immediate Data is attached, it's OK to return now. 1084 * If no Immediate Data is attached, it's OK to return now.
1050 */ 1085 */
1051 if (!cmd->immediate_data) { 1086 if (!cmd->immediate_data) {
1052 if (!cmd->sense_reason && cmd->unsolicited_data) { 1087 if (!cmd->sense_reason && cmd->unsolicited_data)
1053 iscsit_set_dataout_sequence_values(cmd); 1088 iscsit_set_unsoliticed_dataout(cmd);
1054 1089 if (!cmd->sense_reason)
1055 spin_lock_bh(&cmd->dataout_timeout_lock); 1090 return 0;
1056 iscsit_start_dataout_timer(cmd, cmd->conn);
1057 spin_unlock_bh(&cmd->dataout_timeout_lock);
1058 }
1059 1091
1092 target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
1060 return 0; 1093 return 0;
1061 } 1094 }
1062 1095
1063 /* 1096 /*
1064 * Early CHECK_CONDITIONs never make it to the transport processing 1097 * Early CHECK_CONDITIONs with ImmediateData never make it to command
1065 * thread. They are processed in CmdSN order by 1098 * execution. These exceptions are processed in CmdSN order using
1066 * iscsit_check_received_cmdsn() below. 1099 * iscsit_check_received_cmdsn() in iscsit_get_immediate_data() below.
1067 */ 1100 */
1068 if (cmd->sense_reason) { 1101 if (cmd->sense_reason) {
1069 immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION; 1102 target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
1070 goto after_immediate_data; 1103 return 1;
1071 } 1104 }
1072 /* 1105 /*
1073 * Call directly into transport_generic_new_cmd() to perform 1106 * Call directly into transport_generic_new_cmd() to perform
@@ -1075,11 +1108,27 @@ attach_cmd:
1075 */ 1108 */
1076 cmd->sense_reason = transport_generic_new_cmd(&cmd->se_cmd); 1109 cmd->sense_reason = transport_generic_new_cmd(&cmd->se_cmd);
1077 if (cmd->sense_reason) { 1110 if (cmd->sense_reason) {
1078 immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION; 1111 target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
1079 goto after_immediate_data; 1112 return 1;
1080 } 1113 }
1081 1114
1082 immed_ret = iscsit_handle_immediate_data(cmd, buf, payload_length); 1115 return 0;
1116}
1117EXPORT_SYMBOL(iscsit_process_scsi_cmd);
1118
1119static int
1120iscsit_get_immediate_data(struct iscsi_cmd *cmd, struct iscsi_scsi_req *hdr,
1121 bool dump_payload)
1122{
1123 int cmdsn_ret = 0, immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION;
1124 /*
1125 * Special case for Unsupported SAM WRITE Opcodes and ImmediateData=Yes.
1126 */
1127 if (dump_payload == true)
1128 goto after_immediate_data;
1129
1130 immed_ret = iscsit_handle_immediate_data(cmd, hdr,
1131 cmd->first_burst_len);
1083after_immediate_data: 1132after_immediate_data:
1084 if (immed_ret == IMMEDIATE_DATA_NORMAL_OPERATION) { 1133 if (immed_ret == IMMEDIATE_DATA_NORMAL_OPERATION) {
1085 /* 1134 /*
@@ -1087,26 +1136,19 @@ after_immediate_data:
1087 * DataCRC, check against ExpCmdSN/MaxCmdSN if 1136 * DataCRC, check against ExpCmdSN/MaxCmdSN if
1088 * Immediate Bit is not set. 1137 * Immediate Bit is not set.
1089 */ 1138 */
1090 cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); 1139 cmdsn_ret = iscsit_sequence_cmd(cmd->conn, cmd, hdr->cmdsn);
1091 /* 1140
1092 * Special case for Unsupported SAM WRITE Opcodes
1093 * and ImmediateData=Yes.
1094 */
1095 if (cmd->sense_reason) { 1141 if (cmd->sense_reason) {
1096 if (iscsit_dump_data_payload(conn, payload_length, 1) < 0) 1142 if (iscsit_dump_data_payload(cmd->conn,
1143 cmd->first_burst_len, 1) < 0)
1097 return -1; 1144 return -1;
1098 } else if (cmd->unsolicited_data) { 1145 } else if (cmd->unsolicited_data)
1099 iscsit_set_dataout_sequence_values(cmd); 1146 iscsit_set_unsoliticed_dataout(cmd);
1100
1101 spin_lock_bh(&cmd->dataout_timeout_lock);
1102 iscsit_start_dataout_timer(cmd, cmd->conn);
1103 spin_unlock_bh(&cmd->dataout_timeout_lock);
1104 }
1105 1147
1106 if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) 1148 if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
1107 return iscsit_add_reject_from_cmd( 1149 return iscsit_add_reject_from_cmd(
1108 ISCSI_REASON_PROTOCOL_ERROR, 1150 ISCSI_REASON_PROTOCOL_ERROR,
1109 1, 0, buf, cmd); 1151 1, 0, (unsigned char *)hdr, cmd);
1110 1152
1111 } else if (immed_ret == IMMEDIATE_DATA_ERL1_CRC_FAILURE) { 1153 } else if (immed_ret == IMMEDIATE_DATA_ERL1_CRC_FAILURE) {
1112 /* 1154 /*
@@ -1121,13 +1163,47 @@ after_immediate_data:
1121 * CmdSN and issue a retry to plug the sequence. 1163 * CmdSN and issue a retry to plug the sequence.
1122 */ 1164 */
1123 cmd->i_state = ISTATE_REMOVE; 1165 cmd->i_state = ISTATE_REMOVE;
1124 iscsit_add_cmd_to_immediate_queue(cmd, conn, cmd->i_state); 1166 iscsit_add_cmd_to_immediate_queue(cmd, cmd->conn, cmd->i_state);
1125 } else /* immed_ret == IMMEDIATE_DATA_CANNOT_RECOVER */ 1167 } else /* immed_ret == IMMEDIATE_DATA_CANNOT_RECOVER */
1126 return -1; 1168 return -1;
1127 1169
1128 return 0; 1170 return 0;
1129} 1171}
1130 1172
1173static int
1174iscsit_handle_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
1175 unsigned char *buf)
1176{
1177 struct iscsi_scsi_req *hdr = (struct iscsi_scsi_req *)buf;
1178 int rc, immed_data;
1179 bool dump_payload = false;
1180
1181 rc = iscsit_setup_scsi_cmd(conn, cmd, buf);
1182 if (rc < 0)
1183 return rc;
1184 /*
1185 * Allocation iovecs needed for struct socket operations for
1186 * traditional iSCSI block I/O.
1187 */
1188 if (iscsit_allocate_iovecs(cmd) < 0) {
1189 return iscsit_add_reject_from_cmd(
1190 ISCSI_REASON_BOOKMARK_NO_RESOURCES,
1191 1, 0, buf, cmd);
1192 }
1193 immed_data = cmd->immediate_data;
1194
1195 rc = iscsit_process_scsi_cmd(conn, cmd, hdr);
1196 if (rc < 0)
1197 return rc;
1198 else if (rc > 0)
1199 dump_payload = true;
1200
1201 if (!immed_data)
1202 return 0;
1203
1204 return iscsit_get_immediate_data(cmd, hdr, dump_payload);
1205}
1206
1131static u32 iscsit_do_crypto_hash_sg( 1207static u32 iscsit_do_crypto_hash_sg(
1132 struct hash_desc *hash, 1208 struct hash_desc *hash,
1133 struct iscsi_cmd *cmd, 1209 struct iscsi_cmd *cmd,
@@ -1190,20 +1266,16 @@ static void iscsit_do_crypto_hash_buf(
1190 crypto_hash_final(hash, data_crc); 1266 crypto_hash_final(hash, data_crc);
1191} 1267}
1192 1268
1193static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf) 1269int
1270iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf,
1271 struct iscsi_cmd **out_cmd)
1194{ 1272{
1195 int iov_ret, ooo_cmdsn = 0, ret; 1273 struct iscsi_data *hdr = (struct iscsi_data *)buf;
1196 u8 data_crc_failed = 0;
1197 u32 checksum, iov_count = 0, padding = 0, rx_got = 0;
1198 u32 rx_size = 0, payload_length;
1199 struct iscsi_cmd *cmd = NULL; 1274 struct iscsi_cmd *cmd = NULL;
1200 struct se_cmd *se_cmd; 1275 struct se_cmd *se_cmd;
1201 struct iscsi_data *hdr;
1202 struct kvec *iov;
1203 unsigned long flags; 1276 unsigned long flags;
1204 1277 u32 payload_length = ntoh24(hdr->dlength);
1205 hdr = (struct iscsi_data *) buf; 1278 int rc;
1206 payload_length = ntoh24(hdr->dlength);
1207 1279
1208 if (!payload_length) { 1280 if (!payload_length) {
1209 pr_err("DataOUT payload is ZERO, protocol error.\n"); 1281 pr_err("DataOUT payload is ZERO, protocol error.\n");
@@ -1236,7 +1308,7 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf)
1236 1308
1237 pr_debug("Got DataOut ITT: 0x%08x, TTT: 0x%08x," 1309 pr_debug("Got DataOut ITT: 0x%08x, TTT: 0x%08x,"
1238 " DataSN: 0x%08x, Offset: %u, Length: %u, CID: %hu\n", 1310 " DataSN: 0x%08x, Offset: %u, Length: %u, CID: %hu\n",
1239 hdr->itt, hdr->ttt, hdr->datasn, hdr->offset, 1311 hdr->itt, hdr->ttt, hdr->datasn, ntohl(hdr->offset),
1240 payload_length, conn->cid); 1312 payload_length, conn->cid);
1241 1313
1242 if (cmd->cmd_flags & ICF_GOT_LAST_DATAOUT) { 1314 if (cmd->cmd_flags & ICF_GOT_LAST_DATAOUT) {
@@ -1328,12 +1400,26 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf)
1328 * Preform DataSN, DataSequenceInOrder, DataPDUInOrder, and 1400 * Preform DataSN, DataSequenceInOrder, DataPDUInOrder, and
1329 * within-command recovery checks before receiving the payload. 1401 * within-command recovery checks before receiving the payload.
1330 */ 1402 */
1331 ret = iscsit_check_pre_dataout(cmd, buf); 1403 rc = iscsit_check_pre_dataout(cmd, buf);
1332 if (ret == DATAOUT_WITHIN_COMMAND_RECOVERY) 1404 if (rc == DATAOUT_WITHIN_COMMAND_RECOVERY)
1333 return 0; 1405 return 0;
1334 else if (ret == DATAOUT_CANNOT_RECOVER) 1406 else if (rc == DATAOUT_CANNOT_RECOVER)
1335 return -1; 1407 return -1;
1336 1408
1409 *out_cmd = cmd;
1410 return 0;
1411}
1412EXPORT_SYMBOL(iscsit_check_dataout_hdr);
1413
1414static int
1415iscsit_get_dataout(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
1416 struct iscsi_data *hdr)
1417{
1418 struct kvec *iov;
1419 u32 checksum, iov_count = 0, padding = 0, rx_got = 0, rx_size = 0;
1420 u32 payload_length = ntoh24(hdr->dlength);
1421 int iov_ret, data_crc_failed = 0;
1422
1337 rx_size += payload_length; 1423 rx_size += payload_length;
1338 iov = &cmd->iov_data[0]; 1424 iov = &cmd->iov_data[0];
1339 1425
@@ -1386,17 +1472,27 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf)
1386 payload_length); 1472 payload_length);
1387 } 1473 }
1388 } 1474 }
1475
1476 return data_crc_failed;
1477}
1478
1479int
1480iscsit_check_dataout_payload(struct iscsi_cmd *cmd, struct iscsi_data *hdr,
1481 bool data_crc_failed)
1482{
1483 struct iscsi_conn *conn = cmd->conn;
1484 int rc, ooo_cmdsn;
1389 /* 1485 /*
1390 * Increment post receive data and CRC values or perform 1486 * Increment post receive data and CRC values or perform
1391 * within-command recovery. 1487 * within-command recovery.
1392 */ 1488 */
1393 ret = iscsit_check_post_dataout(cmd, buf, data_crc_failed); 1489 rc = iscsit_check_post_dataout(cmd, (unsigned char *)hdr, data_crc_failed);
1394 if ((ret == DATAOUT_NORMAL) || (ret == DATAOUT_WITHIN_COMMAND_RECOVERY)) 1490 if ((rc == DATAOUT_NORMAL) || (rc == DATAOUT_WITHIN_COMMAND_RECOVERY))
1395 return 0; 1491 return 0;
1396 else if (ret == DATAOUT_SEND_R2T) { 1492 else if (rc == DATAOUT_SEND_R2T) {
1397 iscsit_set_dataout_sequence_values(cmd); 1493 iscsit_set_dataout_sequence_values(cmd);
1398 iscsit_build_r2ts_for_cmd(cmd, conn, false); 1494 conn->conn_transport->iscsit_get_dataout(conn, cmd, false);
1399 } else if (ret == DATAOUT_SEND_TO_TRANSPORT) { 1495 } else if (rc == DATAOUT_SEND_TO_TRANSPORT) {
1400 /* 1496 /*
1401 * Handle extra special case for out of order 1497 * Handle extra special case for out of order
1402 * Unsolicited Data Out. 1498 * Unsolicited Data Out.
@@ -1417,15 +1513,37 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf)
1417 1513
1418 return 0; 1514 return 0;
1419} 1515}
1516EXPORT_SYMBOL(iscsit_check_dataout_payload);
1420 1517
1421static int iscsit_handle_nop_out( 1518static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf)
1422 struct iscsi_conn *conn, 1519{
1423 unsigned char *buf) 1520 struct iscsi_cmd *cmd;
1521 struct iscsi_data *hdr = (struct iscsi_data *)buf;
1522 int rc;
1523 bool data_crc_failed = false;
1524
1525 rc = iscsit_check_dataout_hdr(conn, buf, &cmd);
1526 if (rc < 0)
1527 return rc;
1528 else if (!cmd)
1529 return 0;
1530
1531 rc = iscsit_get_dataout(conn, cmd, hdr);
1532 if (rc < 0)
1533 return rc;
1534 else if (rc > 0)
1535 data_crc_failed = true;
1536
1537 return iscsit_check_dataout_payload(cmd, hdr, data_crc_failed);
1538}
1539
1540int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
1541 unsigned char *buf)
1424{ 1542{
1425 unsigned char *ping_data = NULL; 1543 unsigned char *ping_data = NULL;
1426 int cmdsn_ret, niov = 0, ret = 0, rx_got, rx_size; 1544 int cmdsn_ret, niov = 0, ret = 0, rx_got, rx_size;
1427 u32 checksum, data_crc, padding = 0, payload_length; 1545 u32 checksum, data_crc, padding = 0, payload_length;
1428 struct iscsi_cmd *cmd = NULL; 1546 struct iscsi_cmd *cmd_p = NULL;
1429 struct kvec *iov = NULL; 1547 struct kvec *iov = NULL;
1430 struct iscsi_nopout *hdr; 1548 struct iscsi_nopout *hdr;
1431 1549
@@ -1448,7 +1566,7 @@ static int iscsit_handle_nop_out(
1448 buf, conn); 1566 buf, conn);
1449 } 1567 }
1450 1568
1451 pr_debug("Got NOPOUT Ping %s ITT: 0x%08x, TTT: 0x%09x," 1569 pr_debug("Got NOPOUT Ping %s ITT: 0x%08x, TTT: 0x%08x,"
1452 " CmdSN: 0x%08x, ExpStatSN: 0x%08x, Length: %u\n", 1570 " CmdSN: 0x%08x, ExpStatSN: 0x%08x, Length: %u\n",
1453 hdr->itt == RESERVED_ITT ? "Response" : "Request", 1571 hdr->itt == RESERVED_ITT ? "Response" : "Request",
1454 hdr->itt, hdr->ttt, hdr->cmdsn, hdr->exp_statsn, 1572 hdr->itt, hdr->ttt, hdr->cmdsn, hdr->exp_statsn,
@@ -1461,7 +1579,6 @@ static int iscsit_handle_nop_out(
1461 * can contain ping data. 1579 * can contain ping data.
1462 */ 1580 */
1463 if (hdr->ttt == cpu_to_be32(0xFFFFFFFF)) { 1581 if (hdr->ttt == cpu_to_be32(0xFFFFFFFF)) {
1464 cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
1465 if (!cmd) 1582 if (!cmd)
1466 return iscsit_add_reject( 1583 return iscsit_add_reject(
1467 ISCSI_REASON_BOOKMARK_NO_RESOURCES, 1584 ISCSI_REASON_BOOKMARK_NO_RESOURCES,
@@ -1596,14 +1713,14 @@ static int iscsit_handle_nop_out(
1596 /* 1713 /*
1597 * This was a response to a unsolicited NOPIN ping. 1714 * This was a response to a unsolicited NOPIN ping.
1598 */ 1715 */
1599 cmd = iscsit_find_cmd_from_ttt(conn, be32_to_cpu(hdr->ttt)); 1716 cmd_p = iscsit_find_cmd_from_ttt(conn, be32_to_cpu(hdr->ttt));
1600 if (!cmd) 1717 if (!cmd_p)
1601 return -1; 1718 return -1;
1602 1719
1603 iscsit_stop_nopin_response_timer(conn); 1720 iscsit_stop_nopin_response_timer(conn);
1604 1721
1605 cmd->i_state = ISTATE_REMOVE; 1722 cmd_p->i_state = ISTATE_REMOVE;
1606 iscsit_add_cmd_to_immediate_queue(cmd, conn, cmd->i_state); 1723 iscsit_add_cmd_to_immediate_queue(cmd_p, conn, cmd_p->i_state);
1607 iscsit_start_nopin_timer(conn); 1724 iscsit_start_nopin_timer(conn);
1608 } else { 1725 } else {
1609 /* 1726 /*
@@ -1627,12 +1744,12 @@ ping_out:
1627 kfree(ping_data); 1744 kfree(ping_data);
1628 return ret; 1745 return ret;
1629} 1746}
1747EXPORT_SYMBOL(iscsit_handle_nop_out);
1630 1748
1631static int iscsit_handle_task_mgt_cmd( 1749int
1632 struct iscsi_conn *conn, 1750iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
1633 unsigned char *buf) 1751 unsigned char *buf)
1634{ 1752{
1635 struct iscsi_cmd *cmd;
1636 struct se_tmr_req *se_tmr; 1753 struct se_tmr_req *se_tmr;
1637 struct iscsi_tmr_req *tmr_req; 1754 struct iscsi_tmr_req *tmr_req;
1638 struct iscsi_tm *hdr; 1755 struct iscsi_tm *hdr;
@@ -1661,18 +1778,13 @@ static int iscsit_handle_task_mgt_cmd(
1661 pr_err("Task Management Request TASK_REASSIGN not" 1778 pr_err("Task Management Request TASK_REASSIGN not"
1662 " issued as immediate command, bad iSCSI Initiator" 1779 " issued as immediate command, bad iSCSI Initiator"
1663 "implementation\n"); 1780 "implementation\n");
1664 return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, 1781 return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR,
1665 buf, conn); 1782 1, 1, buf, cmd);
1666 } 1783 }
1667 if ((function != ISCSI_TM_FUNC_ABORT_TASK) && 1784 if ((function != ISCSI_TM_FUNC_ABORT_TASK) &&
1668 be32_to_cpu(hdr->refcmdsn) != ISCSI_RESERVED_TAG) 1785 be32_to_cpu(hdr->refcmdsn) != ISCSI_RESERVED_TAG)
1669 hdr->refcmdsn = cpu_to_be32(ISCSI_RESERVED_TAG); 1786 hdr->refcmdsn = cpu_to_be32(ISCSI_RESERVED_TAG);
1670 1787
1671 cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
1672 if (!cmd)
1673 return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES,
1674 1, buf, conn);
1675
1676 cmd->data_direction = DMA_NONE; 1788 cmd->data_direction = DMA_NONE;
1677 1789
1678 cmd->tmr_req = kzalloc(sizeof(struct iscsi_tmr_req), GFP_KERNEL); 1790 cmd->tmr_req = kzalloc(sizeof(struct iscsi_tmr_req), GFP_KERNEL);
@@ -1843,6 +1955,7 @@ attach:
1843 iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state); 1955 iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state);
1844 return 0; 1956 return 0;
1845} 1957}
1958EXPORT_SYMBOL(iscsit_handle_task_mgt_cmd);
1846 1959
1847/* #warning FIXME: Support Text Command parameters besides SendTargets */ 1960/* #warning FIXME: Support Text Command parameters besides SendTargets */
1848static int iscsit_handle_text_cmd( 1961static int iscsit_handle_text_cmd(
@@ -2105,13 +2218,12 @@ int iscsit_logout_removeconnforrecovery(struct iscsi_cmd *cmd, struct iscsi_conn
2105 return 0; 2218 return 0;
2106} 2219}
2107 2220
2108static int iscsit_handle_logout_cmd( 2221int
2109 struct iscsi_conn *conn, 2222iscsit_handle_logout_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
2110 unsigned char *buf) 2223 unsigned char *buf)
2111{ 2224{
2112 int cmdsn_ret, logout_remove = 0; 2225 int cmdsn_ret, logout_remove = 0;
2113 u8 reason_code = 0; 2226 u8 reason_code = 0;
2114 struct iscsi_cmd *cmd;
2115 struct iscsi_logout *hdr; 2227 struct iscsi_logout *hdr;
2116 struct iscsi_tiqn *tiqn = iscsit_snmp_get_tiqn(conn); 2228 struct iscsi_tiqn *tiqn = iscsit_snmp_get_tiqn(conn);
2117 2229
@@ -2135,14 +2247,10 @@ static int iscsit_handle_logout_cmd(
2135 if (conn->conn_state != TARG_CONN_STATE_LOGGED_IN) { 2247 if (conn->conn_state != TARG_CONN_STATE_LOGGED_IN) {
2136 pr_err("Received logout request on connection that" 2248 pr_err("Received logout request on connection that"
2137 " is not in logged in state, ignoring request.\n"); 2249 " is not in logged in state, ignoring request.\n");
2250 iscsit_release_cmd(cmd);
2138 return 0; 2251 return 0;
2139 } 2252 }
2140 2253
2141 cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
2142 if (!cmd)
2143 return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES, 1,
2144 buf, conn);
2145
2146 cmd->iscsi_opcode = ISCSI_OP_LOGOUT; 2254 cmd->iscsi_opcode = ISCSI_OP_LOGOUT;
2147 cmd->i_state = ISTATE_SEND_LOGOUTRSP; 2255 cmd->i_state = ISTATE_SEND_LOGOUTRSP;
2148 cmd->immediate_cmd = ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1 : 0); 2256 cmd->immediate_cmd = ((hdr->opcode & ISCSI_OP_IMMEDIATE) ? 1 : 0);
@@ -2192,6 +2300,7 @@ static int iscsit_handle_logout_cmd(
2192 2300
2193 return logout_remove; 2301 return logout_remove;
2194} 2302}
2303EXPORT_SYMBOL(iscsit_handle_logout_cmd);
2195 2304
2196static int iscsit_handle_snack( 2305static int iscsit_handle_snack(
2197 struct iscsi_conn *conn, 2306 struct iscsi_conn *conn,
@@ -2259,7 +2368,7 @@ static void iscsit_rx_thread_wait_for_tcp(struct iscsi_conn *conn)
2259 2368
2260static int iscsit_handle_immediate_data( 2369static int iscsit_handle_immediate_data(
2261 struct iscsi_cmd *cmd, 2370 struct iscsi_cmd *cmd,
2262 unsigned char *buf, 2371 struct iscsi_scsi_req *hdr,
2263 u32 length) 2372 u32 length)
2264{ 2373{
2265 int iov_ret, rx_got = 0, rx_size = 0; 2374 int iov_ret, rx_got = 0, rx_size = 0;
@@ -2315,12 +2424,12 @@ static int iscsit_handle_immediate_data(
2315 " in ERL=0.\n"); 2424 " in ERL=0.\n");
2316 iscsit_add_reject_from_cmd( 2425 iscsit_add_reject_from_cmd(
2317 ISCSI_REASON_DATA_DIGEST_ERROR, 2426 ISCSI_REASON_DATA_DIGEST_ERROR,
2318 1, 0, buf, cmd); 2427 1, 0, (unsigned char *)hdr, cmd);
2319 return IMMEDIATE_DATA_CANNOT_RECOVER; 2428 return IMMEDIATE_DATA_CANNOT_RECOVER;
2320 } else { 2429 } else {
2321 iscsit_add_reject_from_cmd( 2430 iscsit_add_reject_from_cmd(
2322 ISCSI_REASON_DATA_DIGEST_ERROR, 2431 ISCSI_REASON_DATA_DIGEST_ERROR,
2323 0, 0, buf, cmd); 2432 0, 0, (unsigned char *)hdr, cmd);
2324 return IMMEDIATE_DATA_ERL1_CRC_FAILURE; 2433 return IMMEDIATE_DATA_ERL1_CRC_FAILURE;
2325 } 2434 }
2326 } else { 2435 } else {
@@ -2955,8 +3064,8 @@ static int iscsit_send_r2t(
2955 * connection recovery. 3064 * connection recovery.
2956 */ 3065 */
2957int iscsit_build_r2ts_for_cmd( 3066int iscsit_build_r2ts_for_cmd(
2958 struct iscsi_cmd *cmd,
2959 struct iscsi_conn *conn, 3067 struct iscsi_conn *conn,
3068 struct iscsi_cmd *cmd,
2960 bool recovery) 3069 bool recovery)
2961{ 3070{
2962 int first_r2t = 1; 3071 int first_r2t = 1;
@@ -3758,6 +3867,83 @@ out:
3758 return 0; 3867 return 0;
3759} 3868}
3760 3869
3870static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf)
3871{
3872 struct iscsi_hdr *hdr = (struct iscsi_hdr *)buf;
3873 struct iscsi_cmd *cmd;
3874 int ret = 0;
3875
3876 switch (hdr->opcode & ISCSI_OPCODE_MASK) {
3877 case ISCSI_OP_SCSI_CMD:
3878 cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
3879 if (!cmd)
3880 return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES,
3881 1, buf, conn);
3882
3883 ret = iscsit_handle_scsi_cmd(conn, cmd, buf);
3884 break;
3885 case ISCSI_OP_SCSI_DATA_OUT:
3886 ret = iscsit_handle_data_out(conn, buf);
3887 break;
3888 case ISCSI_OP_NOOP_OUT:
3889 cmd = NULL;
3890 if (hdr->ttt == cpu_to_be32(0xFFFFFFFF)) {
3891 cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
3892 if (!cmd)
3893 return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES,
3894 1, buf, conn);
3895 }
3896 ret = iscsit_handle_nop_out(conn, cmd, buf);
3897 break;
3898 case ISCSI_OP_SCSI_TMFUNC:
3899 cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
3900 if (!cmd)
3901 return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES,
3902 1, buf, conn);
3903
3904 ret = iscsit_handle_task_mgt_cmd(conn, cmd, buf);
3905 break;
3906 case ISCSI_OP_TEXT:
3907 ret = iscsit_handle_text_cmd(conn, buf);
3908 break;
3909 case ISCSI_OP_LOGOUT:
3910 cmd = iscsit_allocate_cmd(conn, GFP_KERNEL);
3911 if (!cmd)
3912 return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES,
3913 1, buf, conn);
3914
3915 ret = iscsit_handle_logout_cmd(conn, cmd, buf);
3916 if (ret > 0)
3917 wait_for_completion_timeout(&conn->conn_logout_comp,
3918 SECONDS_FOR_LOGOUT_COMP * HZ);
3919 break;
3920 case ISCSI_OP_SNACK:
3921 ret = iscsit_handle_snack(conn, buf);
3922 break;
3923 default:
3924 pr_err("Got unknown iSCSI OpCode: 0x%02x\n", hdr->opcode);
3925 if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
3926 pr_err("Cannot recover from unknown"
3927 " opcode while ERL=0, closing iSCSI connection.\n");
3928 return -1;
3929 }
3930 if (!conn->conn_ops->OFMarker) {
3931 pr_err("Unable to recover from unknown"
3932 " opcode while OFMarker=No, closing iSCSI"
3933 " connection.\n");
3934 return -1;
3935 }
3936 if (iscsit_recover_from_unknown_opcode(conn) < 0) {
3937 pr_err("Unable to recover from unknown"
3938 " opcode, closing iSCSI connection.\n");
3939 return -1;
3940 }
3941 break;
3942 }
3943
3944 return ret;
3945}
3946
3761int iscsi_target_rx_thread(void *arg) 3947int iscsi_target_rx_thread(void *arg)
3762{ 3948{
3763 int ret; 3949 int ret;
@@ -3777,6 +3963,18 @@ restart:
3777 if (!conn) 3963 if (!conn)
3778 goto out; 3964 goto out;
3779 3965
3966 if (conn->conn_transport->transport_type == ISCSI_INFINIBAND) {
3967 struct completion comp;
3968 int rc;
3969
3970 init_completion(&comp);
3971 rc = wait_for_completion_interruptible(&comp);
3972 if (rc < 0)
3973 goto transport_err;
3974
3975 goto out;
3976 }
3977
3780 while (!kthread_should_stop()) { 3978 while (!kthread_should_stop()) {
3781 /* 3979 /*
3782 * Ensure that both TX and RX per connection kthreads 3980 * Ensure that both TX and RX per connection kthreads
@@ -3848,62 +4046,9 @@ restart:
3848 goto transport_err; 4046 goto transport_err;
3849 } 4047 }
3850 4048
3851 switch (opcode) { 4049 ret = iscsi_target_rx_opcode(conn, buffer);
3852 case ISCSI_OP_SCSI_CMD: 4050 if (ret < 0)
3853 if (iscsit_handle_scsi_cmd(conn, buffer) < 0) 4051 goto transport_err;
3854 goto transport_err;
3855 break;
3856 case ISCSI_OP_SCSI_DATA_OUT:
3857 if (iscsit_handle_data_out(conn, buffer) < 0)
3858 goto transport_err;
3859 break;
3860 case ISCSI_OP_NOOP_OUT:
3861 if (iscsit_handle_nop_out(conn, buffer) < 0)
3862 goto transport_err;
3863 break;
3864 case ISCSI_OP_SCSI_TMFUNC:
3865 if (iscsit_handle_task_mgt_cmd(conn, buffer) < 0)
3866 goto transport_err;
3867 break;
3868 case ISCSI_OP_TEXT:
3869 if (iscsit_handle_text_cmd(conn, buffer) < 0)
3870 goto transport_err;
3871 break;
3872 case ISCSI_OP_LOGOUT:
3873 ret = iscsit_handle_logout_cmd(conn, buffer);
3874 if (ret > 0) {
3875 wait_for_completion_timeout(&conn->conn_logout_comp,
3876 SECONDS_FOR_LOGOUT_COMP * HZ);
3877 goto transport_err;
3878 } else if (ret < 0)
3879 goto transport_err;
3880 break;
3881 case ISCSI_OP_SNACK:
3882 if (iscsit_handle_snack(conn, buffer) < 0)
3883 goto transport_err;
3884 break;
3885 default:
3886 pr_err("Got unknown iSCSI OpCode: 0x%02x\n",
3887 opcode);
3888 if (!conn->sess->sess_ops->ErrorRecoveryLevel) {
3889 pr_err("Cannot recover from unknown"
3890 " opcode while ERL=0, closing iSCSI connection"
3891 ".\n");
3892 goto transport_err;
3893 }
3894 if (!conn->conn_ops->OFMarker) {
3895 pr_err("Unable to recover from unknown"
3896 " opcode while OFMarker=No, closing iSCSI"
3897 " connection.\n");
3898 goto transport_err;
3899 }
3900 if (iscsit_recover_from_unknown_opcode(conn) < 0) {
3901 pr_err("Unable to recover from unknown"
3902 " opcode, closing iSCSI connection.\n");
3903 goto transport_err;
3904 }
3905 break;
3906 }
3907 } 4052 }
3908 4053
3909transport_err: 4054transport_err:
diff --git a/drivers/target/iscsi/iscsi_target.h b/drivers/target/iscsi/iscsi_target.h
index b1a1e6350707..a0050b2f294e 100644
--- a/drivers/target/iscsi/iscsi_target.h
+++ b/drivers/target/iscsi/iscsi_target.h
@@ -16,11 +16,12 @@ extern int iscsit_reset_np_thread(struct iscsi_np *, struct iscsi_tpg_np *,
16 struct iscsi_portal_group *); 16 struct iscsi_portal_group *);
17extern int iscsit_del_np(struct iscsi_np *); 17extern int iscsit_del_np(struct iscsi_np *);
18extern int iscsit_add_reject_from_cmd(u8, int, int, unsigned char *, struct iscsi_cmd *); 18extern int iscsit_add_reject_from_cmd(u8, int, int, unsigned char *, struct iscsi_cmd *);
19extern void iscsit_set_unsoliticed_dataout(struct iscsi_cmd *);
19extern int iscsit_logout_closesession(struct iscsi_cmd *, struct iscsi_conn *); 20extern int iscsit_logout_closesession(struct iscsi_cmd *, struct iscsi_conn *);
20extern int iscsit_logout_closeconnection(struct iscsi_cmd *, struct iscsi_conn *); 21extern int iscsit_logout_closeconnection(struct iscsi_cmd *, struct iscsi_conn *);
21extern int iscsit_logout_removeconnforrecovery(struct iscsi_cmd *, struct iscsi_conn *); 22extern int iscsit_logout_removeconnforrecovery(struct iscsi_cmd *, struct iscsi_conn *);
22extern int iscsit_send_async_msg(struct iscsi_conn *, u16, u8, u8); 23extern int iscsit_send_async_msg(struct iscsi_conn *, u16, u8, u8);
23extern int iscsit_build_r2ts_for_cmd(struct iscsi_cmd *, struct iscsi_conn *, bool recovery); 24extern int iscsit_build_r2ts_for_cmd(struct iscsi_conn *, struct iscsi_cmd *, bool recovery);
24extern void iscsit_thread_get_cpumask(struct iscsi_conn *); 25extern void iscsit_thread_get_cpumask(struct iscsi_conn *);
25extern int iscsi_target_tx_thread(void *); 26extern int iscsi_target_tx_thread(void *);
26extern int iscsi_target_rx_thread(void *); 27extern int iscsi_target_rx_thread(void *);
diff --git a/drivers/target/iscsi/iscsi_target_configfs.c b/drivers/target/iscsi/iscsi_target_configfs.c
index c78b824194e6..ce3d3210fe41 100644
--- a/drivers/target/iscsi/iscsi_target_configfs.c
+++ b/drivers/target/iscsi/iscsi_target_configfs.c
@@ -1543,9 +1543,10 @@ static int lio_queue_data_in(struct se_cmd *se_cmd)
1543static int lio_write_pending(struct se_cmd *se_cmd) 1543static int lio_write_pending(struct se_cmd *se_cmd)
1544{ 1544{
1545 struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd); 1545 struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
1546 struct iscsi_conn *conn = cmd->conn;
1546 1547
1547 if (!cmd->immediate_data && !cmd->unsolicited_data) 1548 if (!cmd->immediate_data && !cmd->unsolicited_data)
1548 return iscsit_build_r2ts_for_cmd(cmd, cmd->conn, false); 1549 return conn->conn_transport->iscsit_get_dataout(conn, cmd, false);
1549 1550
1550 return 0; 1551 return 0;
1551} 1552}
@@ -1696,6 +1697,11 @@ static void lio_set_default_node_attributes(struct se_node_acl *se_acl)
1696 iscsit_set_default_node_attribues(acl); 1697 iscsit_set_default_node_attribues(acl);
1697} 1698}
1698 1699
1700static int lio_check_stop_free(struct se_cmd *se_cmd)
1701{
1702 return target_put_sess_cmd(se_cmd->se_sess, se_cmd);
1703}
1704
1699static void lio_release_cmd(struct se_cmd *se_cmd) 1705static void lio_release_cmd(struct se_cmd *se_cmd)
1700{ 1706{
1701 struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd); 1707 struct iscsi_cmd *cmd = container_of(se_cmd, struct iscsi_cmd, se_cmd);
@@ -1741,6 +1747,7 @@ int iscsi_target_register_configfs(void)
1741 fabric->tf_ops.tpg_alloc_fabric_acl = &lio_tpg_alloc_fabric_acl; 1747 fabric->tf_ops.tpg_alloc_fabric_acl = &lio_tpg_alloc_fabric_acl;
1742 fabric->tf_ops.tpg_release_fabric_acl = &lio_tpg_release_fabric_acl; 1748 fabric->tf_ops.tpg_release_fabric_acl = &lio_tpg_release_fabric_acl;
1743 fabric->tf_ops.tpg_get_inst_index = &lio_tpg_get_inst_index; 1749 fabric->tf_ops.tpg_get_inst_index = &lio_tpg_get_inst_index;
1750 fabric->tf_ops.check_stop_free = &lio_check_stop_free,
1744 fabric->tf_ops.release_cmd = &lio_release_cmd; 1751 fabric->tf_ops.release_cmd = &lio_release_cmd;
1745 fabric->tf_ops.shutdown_session = &lio_tpg_shutdown_session; 1752 fabric->tf_ops.shutdown_session = &lio_tpg_shutdown_session;
1746 fabric->tf_ops.close_session = &lio_tpg_close_session; 1753 fabric->tf_ops.close_session = &lio_tpg_close_session;
diff --git a/drivers/target/iscsi/iscsi_target_erl1.c b/drivers/target/iscsi/iscsi_target_erl1.c
index 0b52a2371305..7816af6cdd12 100644
--- a/drivers/target/iscsi/iscsi_target_erl1.c
+++ b/drivers/target/iscsi/iscsi_target_erl1.c
@@ -22,6 +22,7 @@
22#include <scsi/iscsi_proto.h> 22#include <scsi/iscsi_proto.h>
23#include <target/target_core_base.h> 23#include <target/target_core_base.h>
24#include <target/target_core_fabric.h> 24#include <target/target_core_fabric.h>
25#include <target/iscsi/iscsi_transport.h>
25 26
26#include "iscsi_target_core.h" 27#include "iscsi_target_core.h"
27#include "iscsi_target_seq_pdu_list.h" 28#include "iscsi_target_seq_pdu_list.h"
@@ -53,6 +54,9 @@ int iscsit_dump_data_payload(
53 u32 length, padding, offset = 0, size; 54 u32 length, padding, offset = 0, size;
54 struct kvec iov; 55 struct kvec iov;
55 56
57 if (conn->sess->sess_ops->RDMAExtensions)
58 return 0;
59
56 length = (buf_len > OFFLOAD_BUF_SIZE) ? OFFLOAD_BUF_SIZE : buf_len; 60 length = (buf_len > OFFLOAD_BUF_SIZE) ? OFFLOAD_BUF_SIZE : buf_len;
57 61
58 buf = kzalloc(length, GFP_ATOMIC); 62 buf = kzalloc(length, GFP_ATOMIC);
@@ -919,6 +923,7 @@ int iscsit_execute_ooo_cmdsns(struct iscsi_session *sess)
919int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo) 923int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo)
920{ 924{
921 struct se_cmd *se_cmd = &cmd->se_cmd; 925 struct se_cmd *se_cmd = &cmd->se_cmd;
926 struct iscsi_conn *conn = cmd->conn;
922 int lr = 0; 927 int lr = 0;
923 928
924 spin_lock_bh(&cmd->istate_lock); 929 spin_lock_bh(&cmd->istate_lock);
@@ -981,7 +986,7 @@ int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo)
981 return 0; 986 return 0;
982 987
983 iscsit_set_dataout_sequence_values(cmd); 988 iscsit_set_dataout_sequence_values(cmd);
984 iscsit_build_r2ts_for_cmd(cmd, cmd->conn, false); 989 conn->conn_transport->iscsit_get_dataout(conn, cmd, false);
985 } 990 }
986 return 0; 991 return 0;
987 } 992 }
@@ -999,10 +1004,7 @@ int iscsit_execute_cmd(struct iscsi_cmd *cmd, int ooo)
999 if (transport_check_aborted_status(se_cmd, 1) != 0) 1004 if (transport_check_aborted_status(se_cmd, 1) != 0)
1000 return 0; 1005 return 0;
1001 1006
1002 iscsit_set_dataout_sequence_values(cmd); 1007 iscsit_set_unsoliticed_dataout(cmd);
1003 spin_lock_bh(&cmd->dataout_timeout_lock);
1004 iscsit_start_dataout_timer(cmd, cmd->conn);
1005 spin_unlock_bh(&cmd->dataout_timeout_lock);
1006 } 1008 }
1007 return transport_handle_cdb_direct(&cmd->se_cmd); 1009 return transport_handle_cdb_direct(&cmd->se_cmd);
1008 1010
@@ -1290,3 +1292,4 @@ void iscsit_stop_dataout_timer(struct iscsi_cmd *cmd)
1290 cmd->init_task_tag); 1292 cmd->init_task_tag);
1291 spin_unlock_bh(&cmd->dataout_timeout_lock); 1293 spin_unlock_bh(&cmd->dataout_timeout_lock);
1292} 1294}
1295EXPORT_SYMBOL(iscsit_stop_dataout_timer);
diff --git a/drivers/target/iscsi/iscsi_target_login.c b/drivers/target/iscsi/iscsi_target_login.c
index e6a826927a40..bb5d5c5bce65 100644
--- a/drivers/target/iscsi/iscsi_target_login.c
+++ b/drivers/target/iscsi/iscsi_target_login.c
@@ -1068,8 +1068,7 @@ int iscsit_get_login_rx(struct iscsi_conn *conn, struct iscsi_login *login)
1068 if (login->first_request) { 1068 if (login->first_request) {
1069 login_req = (struct iscsi_login_req *)login->req; 1069 login_req = (struct iscsi_login_req *)login->req;
1070 login->leading_connection = (!login_req->tsih) ? 1 : 0; 1070 login->leading_connection = (!login_req->tsih) ? 1 : 0;
1071 login->current_stage = 1071 login->current_stage = ISCSI_LOGIN_CURRENT_STAGE(login_req->flags);
1072 (login_req->flags & ISCSI_FLAG_LOGIN_CURRENT_STAGE_MASK) >> 2;
1073 login->version_min = login_req->min_version; 1072 login->version_min = login_req->min_version;
1074 login->version_max = login_req->max_version; 1073 login->version_max = login_req->max_version;
1075 memcpy(login->isid, login_req->isid, 6); 1074 memcpy(login->isid, login_req->isid, 6);
diff --git a/drivers/target/iscsi/iscsi_target_nego.c b/drivers/target/iscsi/iscsi_target_nego.c
index 879a0cb44bc3..7ad912060e21 100644
--- a/drivers/target/iscsi/iscsi_target_nego.c
+++ b/drivers/target/iscsi/iscsi_target_nego.c
@@ -691,21 +691,6 @@ int iscsi_target_locate_portal(
691 login_req = (struct iscsi_login_req *) login->req; 691 login_req = (struct iscsi_login_req *) login->req;
692 payload_length = ntoh24(login_req->dlength); 692 payload_length = ntoh24(login_req->dlength);
693 693
694 login->first_request = 1;
695 login->leading_connection = (!login_req->tsih) ? 1 : 0;
696 login->current_stage = ISCSI_LOGIN_CURRENT_STAGE(login_req->flags);
697 login->version_min = login_req->min_version;
698 login->version_max = login_req->max_version;
699 memcpy(login->isid, login_req->isid, 6);
700 login->cmd_sn = be32_to_cpu(login_req->cmdsn);
701 login->init_task_tag = login_req->itt;
702 login->initial_exp_statsn = be32_to_cpu(login_req->exp_statsn);
703 login->cid = be16_to_cpu(login_req->cid);
704 login->tsih = be16_to_cpu(login_req->tsih);
705
706 if (iscsi_target_get_initial_payload(conn, login) < 0)
707 return -1;
708
709 tmpbuf = kzalloc(payload_length + 1, GFP_KERNEL); 694 tmpbuf = kzalloc(payload_length + 1, GFP_KERNEL);
710 if (!tmpbuf) { 695 if (!tmpbuf) {
711 pr_err("Unable to allocate memory for tmpbuf.\n"); 696 pr_err("Unable to allocate memory for tmpbuf.\n");
diff --git a/drivers/target/iscsi/iscsi_target_tmr.c b/drivers/target/iscsi/iscsi_target_tmr.c
index 9d4417aae921..16ca0ef9266f 100644
--- a/drivers/target/iscsi/iscsi_target_tmr.c
+++ b/drivers/target/iscsi/iscsi_target_tmr.c
@@ -23,6 +23,7 @@
23#include <scsi/iscsi_proto.h> 23#include <scsi/iscsi_proto.h>
24#include <target/target_core_base.h> 24#include <target/target_core_base.h>
25#include <target/target_core_fabric.h> 25#include <target/target_core_fabric.h>
26#include <target/iscsi/iscsi_transport.h>
26 27
27#include "iscsi_target_core.h" 28#include "iscsi_target_core.h"
28#include "iscsi_target_seq_pdu_list.h" 29#include "iscsi_target_seq_pdu_list.h"
@@ -301,7 +302,7 @@ static int iscsit_task_reassign_complete_write(
301 /* 302 /*
302 * iscsit_build_r2ts_for_cmd() can handle the rest from here. 303 * iscsit_build_r2ts_for_cmd() can handle the rest from here.
303 */ 304 */
304 return iscsit_build_r2ts_for_cmd(cmd, conn, true); 305 return conn->conn_transport->iscsit_get_dataout(conn, cmd, true);
305} 306}
306 307
307static int iscsit_task_reassign_complete_read( 308static int iscsit_task_reassign_complete_read(
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c
index 0b73f90c9c54..2cc6c9a3ffb8 100644
--- a/drivers/target/iscsi/iscsi_target_util.c
+++ b/drivers/target/iscsi/iscsi_target_util.c
@@ -317,6 +317,7 @@ int iscsit_sequence_cmd(
317 317
318 return ret; 318 return ret;
319} 319}
320EXPORT_SYMBOL(iscsit_sequence_cmd);
320 321
321int iscsit_check_unsolicited_dataout(struct iscsi_cmd *cmd, unsigned char *buf) 322int iscsit_check_unsolicited_dataout(struct iscsi_cmd *cmd, unsigned char *buf)
322{ 323{