diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2013-07-30 00:04:01 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2013-08-04 04:51:17 -0400 |
commit | 1aa58ccd029fc75c115ae35c3fcb4d43043c0725 (patch) | |
tree | 289d3918fa68a40168f20bb06016a8caec1b7e95 | |
parent | 6655d76ecb91fa618c4d0d0dd653e94078b3f050 (diff) |
iscsi-target: Fix iscsit_add_reject* usage for iser
commit ba159914086f06532079fc15141f46ffe7e04a41 upstream
This patch changes iscsit_add_reject() + iscsit_add_reject_from_cmd()
usage to not sleep on iscsi_cmd->reject_comp to address a free-after-use
usage bug in v3.10 with iser-target code.
It saves ->reject_reason for use within iscsit_build_reject() so the
correct value for both transport cases. It also drops the legacy
fail_conn parameter usage throughput iscsi-target code and adds
two iscsit_add_reject_cmd() and iscsit_reject_cmd helper functions,
along with various small cleanups.
(v2: Re-enable target_put_sess_cmd() to be called from
iscsit_add_reject_from_cmd() for rejects invoked after
target_get_sess_cmd() has been called)
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Cc: Or Gerlitz <ogerlitz@mellanox.com>
Cc: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | drivers/infiniband/ulp/isert/ib_isert.c | 5 | ||||
-rw-r--r-- | drivers/target/iscsi/iscsi_target.c | 251 | ||||
-rw-r--r-- | drivers/target/iscsi/iscsi_target.h | 2 | ||||
-rw-r--r-- | drivers/target/iscsi/iscsi_target_core.h | 4 | ||||
-rw-r--r-- | drivers/target/iscsi/iscsi_target_erl0.c | 7 | ||||
-rw-r--r-- | drivers/target/iscsi/iscsi_target_erl1.c | 20 | ||||
-rw-r--r-- | drivers/target/iscsi/iscsi_target_util.c | 1 | ||||
-rw-r--r-- | include/target/iscsi/iscsi_transport.h | 2 |
8 files changed, 116 insertions, 176 deletions
diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c index bfc21798bd5e..4f6faf0915d5 100644 --- a/drivers/infiniband/ulp/isert/ib_isert.c +++ b/drivers/infiniband/ulp/isert/ib_isert.c | |||
@@ -957,11 +957,6 @@ sequence_cmd: | |||
957 | if (!rc && dump_payload == false && unsol_data) | 957 | if (!rc && dump_payload == false && unsol_data) |
958 | iscsit_set_unsoliticed_dataout(cmd); | 958 | iscsit_set_unsoliticed_dataout(cmd); |
959 | 959 | ||
960 | if (rc == CMDSN_ERROR_CANNOT_RECOVER) | ||
961 | return iscsit_add_reject_from_cmd( | ||
962 | ISCSI_REASON_PROTOCOL_ERROR, | ||
963 | 1, 0, (unsigned char *)hdr, cmd); | ||
964 | |||
965 | return 0; | 960 | return 0; |
966 | } | 961 | } |
967 | 962 | ||
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index f1db6ee71006..03ccb610d2bb 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c | |||
@@ -628,25 +628,18 @@ static void __exit iscsi_target_cleanup_module(void) | |||
628 | } | 628 | } |
629 | 629 | ||
630 | static int iscsit_add_reject( | 630 | static int iscsit_add_reject( |
631 | struct iscsi_conn *conn, | ||
631 | u8 reason, | 632 | u8 reason, |
632 | int fail_conn, | 633 | unsigned char *buf) |
633 | unsigned char *buf, | ||
634 | struct iscsi_conn *conn) | ||
635 | { | 634 | { |
636 | struct iscsi_cmd *cmd; | 635 | struct iscsi_cmd *cmd; |
637 | struct iscsi_reject *hdr; | ||
638 | int ret; | ||
639 | 636 | ||
640 | cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); | 637 | cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); |
641 | if (!cmd) | 638 | if (!cmd) |
642 | return -1; | 639 | return -1; |
643 | 640 | ||
644 | cmd->iscsi_opcode = ISCSI_OP_REJECT; | 641 | cmd->iscsi_opcode = ISCSI_OP_REJECT; |
645 | if (fail_conn) | 642 | cmd->reject_reason = reason; |
646 | cmd->cmd_flags |= ICF_REJECT_FAIL_CONN; | ||
647 | |||
648 | hdr = (struct iscsi_reject *) cmd->pdu; | ||
649 | hdr->reason = reason; | ||
650 | 643 | ||
651 | cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL); | 644 | cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL); |
652 | if (!cmd->buf_ptr) { | 645 | if (!cmd->buf_ptr) { |
@@ -662,23 +655,16 @@ static int iscsit_add_reject( | |||
662 | cmd->i_state = ISTATE_SEND_REJECT; | 655 | cmd->i_state = ISTATE_SEND_REJECT; |
663 | iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state); | 656 | iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state); |
664 | 657 | ||
665 | ret = wait_for_completion_interruptible(&cmd->reject_comp); | 658 | return -1; |
666 | if (ret != 0) | ||
667 | return -1; | ||
668 | |||
669 | return (!fail_conn) ? 0 : -1; | ||
670 | } | 659 | } |
671 | 660 | ||
672 | int iscsit_add_reject_from_cmd( | 661 | static int iscsit_add_reject_from_cmd( |
662 | struct iscsi_cmd *cmd, | ||
673 | u8 reason, | 663 | u8 reason, |
674 | int fail_conn, | 664 | bool add_to_conn, |
675 | int add_to_conn, | 665 | unsigned char *buf) |
676 | unsigned char *buf, | ||
677 | struct iscsi_cmd *cmd) | ||
678 | { | 666 | { |
679 | struct iscsi_conn *conn; | 667 | struct iscsi_conn *conn; |
680 | struct iscsi_reject *hdr; | ||
681 | int ret; | ||
682 | 668 | ||
683 | if (!cmd->conn) { | 669 | if (!cmd->conn) { |
684 | pr_err("cmd->conn is NULL for ITT: 0x%08x\n", | 670 | pr_err("cmd->conn is NULL for ITT: 0x%08x\n", |
@@ -688,11 +674,7 @@ int iscsit_add_reject_from_cmd( | |||
688 | conn = cmd->conn; | 674 | conn = cmd->conn; |
689 | 675 | ||
690 | cmd->iscsi_opcode = ISCSI_OP_REJECT; | 676 | cmd->iscsi_opcode = ISCSI_OP_REJECT; |
691 | if (fail_conn) | 677 | cmd->reject_reason = reason; |
692 | cmd->cmd_flags |= ICF_REJECT_FAIL_CONN; | ||
693 | |||
694 | hdr = (struct iscsi_reject *) cmd->pdu; | ||
695 | hdr->reason = reason; | ||
696 | 678 | ||
697 | cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL); | 679 | cmd->buf_ptr = kmemdup(buf, ISCSI_HDR_LEN, GFP_KERNEL); |
698 | if (!cmd->buf_ptr) { | 680 | if (!cmd->buf_ptr) { |
@@ -709,8 +691,6 @@ int iscsit_add_reject_from_cmd( | |||
709 | 691 | ||
710 | cmd->i_state = ISTATE_SEND_REJECT; | 692 | cmd->i_state = ISTATE_SEND_REJECT; |
711 | iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state); | 693 | iscsit_add_cmd_to_response_queue(cmd, conn, cmd->i_state); |
712 | |||
713 | ret = wait_for_completion_interruptible(&cmd->reject_comp); | ||
714 | /* | 694 | /* |
715 | * Perform the kref_put now if se_cmd has already been setup by | 695 | * Perform the kref_put now if se_cmd has already been setup by |
716 | * scsit_setup_scsi_cmd() | 696 | * scsit_setup_scsi_cmd() |
@@ -719,12 +699,19 @@ int iscsit_add_reject_from_cmd( | |||
719 | pr_debug("iscsi reject: calling target_put_sess_cmd >>>>>>\n"); | 699 | pr_debug("iscsi reject: calling target_put_sess_cmd >>>>>>\n"); |
720 | target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); | 700 | target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); |
721 | } | 701 | } |
722 | if (ret != 0) | 702 | return -1; |
723 | return -1; | 703 | } |
704 | |||
705 | static int iscsit_add_reject_cmd(struct iscsi_cmd *cmd, u8 reason, | ||
706 | unsigned char *buf) | ||
707 | { | ||
708 | return iscsit_add_reject_from_cmd(cmd, reason, true, buf); | ||
709 | } | ||
724 | 710 | ||
725 | return (!fail_conn) ? 0 : -1; | 711 | int iscsit_reject_cmd(struct iscsi_cmd *cmd, u8 reason, unsigned char *buf) |
712 | { | ||
713 | return iscsit_add_reject_from_cmd(cmd, reason, false, buf); | ||
726 | } | 714 | } |
727 | EXPORT_SYMBOL(iscsit_add_reject_from_cmd); | ||
728 | 715 | ||
729 | /* | 716 | /* |
730 | * Map some portion of the allocated scatterlist to an iovec, suitable for | 717 | * Map some portion of the allocated scatterlist to an iovec, suitable for |
@@ -844,8 +831,8 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | |||
844 | !(hdr->flags & ISCSI_FLAG_CMD_FINAL)) { | 831 | !(hdr->flags & ISCSI_FLAG_CMD_FINAL)) { |
845 | pr_err("ISCSI_FLAG_CMD_WRITE & ISCSI_FLAG_CMD_FINAL" | 832 | pr_err("ISCSI_FLAG_CMD_WRITE & ISCSI_FLAG_CMD_FINAL" |
846 | " not set. Bad iSCSI Initiator.\n"); | 833 | " not set. Bad iSCSI Initiator.\n"); |
847 | return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID, | 834 | return iscsit_add_reject_cmd(cmd, |
848 | 1, 1, buf, cmd); | 835 | ISCSI_REASON_BOOKMARK_INVALID, buf); |
849 | } | 836 | } |
850 | 837 | ||
851 | if (((hdr->flags & ISCSI_FLAG_CMD_READ) || | 838 | if (((hdr->flags & ISCSI_FLAG_CMD_READ) || |
@@ -865,8 +852,8 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | |||
865 | pr_err("ISCSI_FLAG_CMD_READ or ISCSI_FLAG_CMD_WRITE" | 852 | pr_err("ISCSI_FLAG_CMD_READ or ISCSI_FLAG_CMD_WRITE" |
866 | " set when Expected Data Transfer Length is 0 for" | 853 | " set when Expected Data Transfer Length is 0 for" |
867 | " CDB: 0x%02x. Bad iSCSI Initiator.\n", hdr->cdb[0]); | 854 | " CDB: 0x%02x. Bad iSCSI Initiator.\n", hdr->cdb[0]); |
868 | return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID, | 855 | return iscsit_add_reject_cmd(cmd, |
869 | 1, 1, buf, cmd); | 856 | ISCSI_REASON_BOOKMARK_INVALID, buf); |
870 | } | 857 | } |
871 | done: | 858 | done: |
872 | 859 | ||
@@ -875,62 +862,62 @@ done: | |||
875 | pr_err("ISCSI_FLAG_CMD_READ and/or ISCSI_FLAG_CMD_WRITE" | 862 | pr_err("ISCSI_FLAG_CMD_READ and/or ISCSI_FLAG_CMD_WRITE" |
876 | " MUST be set if Expected Data Transfer Length is not 0." | 863 | " MUST be set if Expected Data Transfer Length is not 0." |
877 | " Bad iSCSI Initiator\n"); | 864 | " Bad iSCSI Initiator\n"); |
878 | return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID, | 865 | return iscsit_add_reject_cmd(cmd, |
879 | 1, 1, buf, cmd); | 866 | ISCSI_REASON_BOOKMARK_INVALID, buf); |
880 | } | 867 | } |
881 | 868 | ||
882 | if ((hdr->flags & ISCSI_FLAG_CMD_READ) && | 869 | if ((hdr->flags & ISCSI_FLAG_CMD_READ) && |
883 | (hdr->flags & ISCSI_FLAG_CMD_WRITE)) { | 870 | (hdr->flags & ISCSI_FLAG_CMD_WRITE)) { |
884 | pr_err("Bidirectional operations not supported!\n"); | 871 | pr_err("Bidirectional operations not supported!\n"); |
885 | return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID, | 872 | return iscsit_add_reject_cmd(cmd, |
886 | 1, 1, buf, cmd); | 873 | ISCSI_REASON_BOOKMARK_INVALID, buf); |
887 | } | 874 | } |
888 | 875 | ||
889 | if (hdr->opcode & ISCSI_OP_IMMEDIATE) { | 876 | if (hdr->opcode & ISCSI_OP_IMMEDIATE) { |
890 | pr_err("Illegally set Immediate Bit in iSCSI Initiator" | 877 | pr_err("Illegally set Immediate Bit in iSCSI Initiator" |
891 | " Scsi Command PDU.\n"); | 878 | " Scsi Command PDU.\n"); |
892 | return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID, | 879 | return iscsit_add_reject_cmd(cmd, |
893 | 1, 1, buf, cmd); | 880 | ISCSI_REASON_BOOKMARK_INVALID, buf); |
894 | } | 881 | } |
895 | 882 | ||
896 | if (payload_length && !conn->sess->sess_ops->ImmediateData) { | 883 | if (payload_length && !conn->sess->sess_ops->ImmediateData) { |
897 | pr_err("ImmediateData=No but DataSegmentLength=%u," | 884 | pr_err("ImmediateData=No but DataSegmentLength=%u," |
898 | " protocol error.\n", payload_length); | 885 | " protocol error.\n", payload_length); |
899 | return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, | 886 | return iscsit_add_reject_cmd(cmd, |
900 | 1, 1, buf, cmd); | 887 | ISCSI_REASON_PROTOCOL_ERROR, buf); |
901 | } | 888 | } |
902 | 889 | ||
903 | if ((be32_to_cpu(hdr->data_length )== payload_length) && | 890 | if ((be32_to_cpu(hdr->data_length) == payload_length) && |
904 | (!(hdr->flags & ISCSI_FLAG_CMD_FINAL))) { | 891 | (!(hdr->flags & ISCSI_FLAG_CMD_FINAL))) { |
905 | pr_err("Expected Data Transfer Length and Length of" | 892 | pr_err("Expected Data Transfer Length and Length of" |
906 | " Immediate Data are the same, but ISCSI_FLAG_CMD_FINAL" | 893 | " Immediate Data are the same, but ISCSI_FLAG_CMD_FINAL" |
907 | " bit is not set protocol error\n"); | 894 | " bit is not set protocol error\n"); |
908 | return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, | 895 | return iscsit_add_reject_cmd(cmd, |
909 | 1, 1, buf, cmd); | 896 | ISCSI_REASON_PROTOCOL_ERROR, buf); |
910 | } | 897 | } |
911 | 898 | ||
912 | if (payload_length > be32_to_cpu(hdr->data_length)) { | 899 | if (payload_length > be32_to_cpu(hdr->data_length)) { |
913 | pr_err("DataSegmentLength: %u is greater than" | 900 | pr_err("DataSegmentLength: %u is greater than" |
914 | " EDTL: %u, protocol error.\n", payload_length, | 901 | " EDTL: %u, protocol error.\n", payload_length, |
915 | hdr->data_length); | 902 | hdr->data_length); |
916 | return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, | 903 | return iscsit_add_reject_cmd(cmd, |
917 | 1, 1, buf, cmd); | 904 | ISCSI_REASON_PROTOCOL_ERROR, buf); |
918 | } | 905 | } |
919 | 906 | ||
920 | if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) { | 907 | if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) { |
921 | pr_err("DataSegmentLength: %u is greater than" | 908 | pr_err("DataSegmentLength: %u is greater than" |
922 | " MaxXmitDataSegmentLength: %u, protocol error.\n", | 909 | " MaxXmitDataSegmentLength: %u, protocol error.\n", |
923 | payload_length, conn->conn_ops->MaxXmitDataSegmentLength); | 910 | payload_length, conn->conn_ops->MaxXmitDataSegmentLength); |
924 | return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, | 911 | return iscsit_add_reject_cmd(cmd, |
925 | 1, 1, buf, cmd); | 912 | ISCSI_REASON_PROTOCOL_ERROR, buf); |
926 | } | 913 | } |
927 | 914 | ||
928 | if (payload_length > conn->sess->sess_ops->FirstBurstLength) { | 915 | if (payload_length > conn->sess->sess_ops->FirstBurstLength) { |
929 | pr_err("DataSegmentLength: %u is greater than" | 916 | pr_err("DataSegmentLength: %u is greater than" |
930 | " FirstBurstLength: %u, protocol error.\n", | 917 | " FirstBurstLength: %u, protocol error.\n", |
931 | payload_length, conn->sess->sess_ops->FirstBurstLength); | 918 | payload_length, conn->sess->sess_ops->FirstBurstLength); |
932 | return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID, | 919 | return iscsit_add_reject_cmd(cmd, |
933 | 1, 1, buf, cmd); | 920 | ISCSI_REASON_BOOKMARK_INVALID, buf); |
934 | } | 921 | } |
935 | 922 | ||
936 | data_direction = (hdr->flags & ISCSI_FLAG_CMD_WRITE) ? DMA_TO_DEVICE : | 923 | data_direction = (hdr->flags & ISCSI_FLAG_CMD_WRITE) ? DMA_TO_DEVICE : |
@@ -985,9 +972,8 @@ done: | |||
985 | 972 | ||
986 | dr = iscsit_allocate_datain_req(); | 973 | dr = iscsit_allocate_datain_req(); |
987 | if (!dr) | 974 | if (!dr) |
988 | return iscsit_add_reject_from_cmd( | 975 | return iscsit_add_reject_cmd(cmd, |
989 | ISCSI_REASON_BOOKMARK_NO_RESOURCES, | 976 | ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf); |
990 | 1, 1, buf, cmd); | ||
991 | 977 | ||
992 | iscsit_attach_datain_req(cmd, dr); | 978 | iscsit_attach_datain_req(cmd, dr); |
993 | } | 979 | } |
@@ -1015,18 +1001,16 @@ done: | |||
1015 | cmd->sense_reason = target_setup_cmd_from_cdb(&cmd->se_cmd, hdr->cdb); | 1001 | cmd->sense_reason = target_setup_cmd_from_cdb(&cmd->se_cmd, hdr->cdb); |
1016 | if (cmd->sense_reason) { | 1002 | if (cmd->sense_reason) { |
1017 | if (cmd->sense_reason == TCM_OUT_OF_RESOURCES) { | 1003 | if (cmd->sense_reason == TCM_OUT_OF_RESOURCES) { |
1018 | return iscsit_add_reject_from_cmd( | 1004 | return iscsit_add_reject_cmd(cmd, |
1019 | ISCSI_REASON_BOOKMARK_NO_RESOURCES, | 1005 | ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf); |
1020 | 1, 1, buf, cmd); | ||
1021 | } | 1006 | } |
1022 | 1007 | ||
1023 | goto attach_cmd; | 1008 | goto attach_cmd; |
1024 | } | 1009 | } |
1025 | 1010 | ||
1026 | if (iscsit_build_pdu_and_seq_lists(cmd, payload_length) < 0) { | 1011 | if (iscsit_build_pdu_and_seq_lists(cmd, payload_length) < 0) { |
1027 | return iscsit_add_reject_from_cmd( | 1012 | return iscsit_add_reject_cmd(cmd, |
1028 | ISCSI_REASON_BOOKMARK_NO_RESOURCES, | 1013 | ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf); |
1029 | 1, 1, buf, cmd); | ||
1030 | } | 1014 | } |
1031 | 1015 | ||
1032 | attach_cmd: | 1016 | attach_cmd: |
@@ -1075,10 +1059,6 @@ int iscsit_process_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | |||
1075 | 1059 | ||
1076 | target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); | 1060 | target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); |
1077 | return 0; | 1061 | return 0; |
1078 | } else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) { | ||
1079 | return iscsit_add_reject_from_cmd( | ||
1080 | ISCSI_REASON_PROTOCOL_ERROR, | ||
1081 | 1, 0, (unsigned char *)hdr, cmd); | ||
1082 | } | 1062 | } |
1083 | } | 1063 | } |
1084 | 1064 | ||
@@ -1149,11 +1129,6 @@ after_immediate_data: | |||
1149 | } else if (cmd->unsolicited_data) | 1129 | } else if (cmd->unsolicited_data) |
1150 | iscsit_set_unsoliticed_dataout(cmd); | 1130 | iscsit_set_unsoliticed_dataout(cmd); |
1151 | 1131 | ||
1152 | if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) | ||
1153 | return iscsit_add_reject_from_cmd( | ||
1154 | ISCSI_REASON_PROTOCOL_ERROR, | ||
1155 | 1, 0, (unsigned char *)hdr, cmd); | ||
1156 | |||
1157 | } else if (immed_ret == IMMEDIATE_DATA_ERL1_CRC_FAILURE) { | 1132 | } else if (immed_ret == IMMEDIATE_DATA_ERL1_CRC_FAILURE) { |
1158 | /* | 1133 | /* |
1159 | * Immediate Data failed DataCRC and ERL>=1, | 1134 | * Immediate Data failed DataCRC and ERL>=1, |
@@ -1190,9 +1165,8 @@ iscsit_handle_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | |||
1190 | * traditional iSCSI block I/O. | 1165 | * traditional iSCSI block I/O. |
1191 | */ | 1166 | */ |
1192 | if (iscsit_allocate_iovecs(cmd) < 0) { | 1167 | if (iscsit_allocate_iovecs(cmd) < 0) { |
1193 | return iscsit_add_reject_from_cmd( | 1168 | return iscsit_add_reject_cmd(cmd, |
1194 | ISCSI_REASON_BOOKMARK_NO_RESOURCES, | 1169 | ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf); |
1195 | 1, 0, buf, cmd); | ||
1196 | } | 1170 | } |
1197 | immed_data = cmd->immediate_data; | 1171 | immed_data = cmd->immediate_data; |
1198 | 1172 | ||
@@ -1283,8 +1257,8 @@ iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf, | |||
1283 | 1257 | ||
1284 | if (!payload_length) { | 1258 | if (!payload_length) { |
1285 | pr_err("DataOUT payload is ZERO, protocol error.\n"); | 1259 | pr_err("DataOUT payload is ZERO, protocol error.\n"); |
1286 | return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, | 1260 | return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR, |
1287 | buf, conn); | 1261 | buf); |
1288 | } | 1262 | } |
1289 | 1263 | ||
1290 | /* iSCSI write */ | 1264 | /* iSCSI write */ |
@@ -1301,8 +1275,8 @@ iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf, | |||
1301 | pr_err("DataSegmentLength: %u is greater than" | 1275 | pr_err("DataSegmentLength: %u is greater than" |
1302 | " MaxXmitDataSegmentLength: %u\n", payload_length, | 1276 | " MaxXmitDataSegmentLength: %u\n", payload_length, |
1303 | conn->conn_ops->MaxXmitDataSegmentLength); | 1277 | conn->conn_ops->MaxXmitDataSegmentLength); |
1304 | return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, | 1278 | return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR, |
1305 | buf, conn); | 1279 | buf); |
1306 | } | 1280 | } |
1307 | 1281 | ||
1308 | cmd = iscsit_find_cmd_from_itt_or_dump(conn, hdr->itt, | 1282 | cmd = iscsit_find_cmd_from_itt_or_dump(conn, hdr->itt, |
@@ -1325,8 +1299,7 @@ iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf, | |||
1325 | if (cmd->data_direction != DMA_TO_DEVICE) { | 1299 | if (cmd->data_direction != DMA_TO_DEVICE) { |
1326 | pr_err("Command ITT: 0x%08x received DataOUT for a" | 1300 | pr_err("Command ITT: 0x%08x received DataOUT for a" |
1327 | " NON-WRITE command.\n", cmd->init_task_tag); | 1301 | " NON-WRITE command.\n", cmd->init_task_tag); |
1328 | return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, | 1302 | return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, buf); |
1329 | 1, 0, buf, cmd); | ||
1330 | } | 1303 | } |
1331 | se_cmd = &cmd->se_cmd; | 1304 | se_cmd = &cmd->se_cmd; |
1332 | iscsit_mod_dataout_timer(cmd); | 1305 | iscsit_mod_dataout_timer(cmd); |
@@ -1335,8 +1308,7 @@ iscsit_check_dataout_hdr(struct iscsi_conn *conn, unsigned char *buf, | |||
1335 | pr_err("DataOut Offset: %u, Length %u greater than" | 1308 | pr_err("DataOut Offset: %u, Length %u greater than" |
1336 | " iSCSI Command EDTL %u, protocol error.\n", | 1309 | " iSCSI Command EDTL %u, protocol error.\n", |
1337 | hdr->offset, payload_length, cmd->se_cmd.data_length); | 1310 | hdr->offset, payload_length, cmd->se_cmd.data_length); |
1338 | return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID, | 1311 | return iscsit_reject_cmd(cmd, ISCSI_REASON_BOOKMARK_INVALID, buf); |
1339 | 1, 0, buf, cmd); | ||
1340 | } | 1312 | } |
1341 | 1313 | ||
1342 | if (cmd->unsolicited_data) { | 1314 | if (cmd->unsolicited_data) { |
@@ -1557,8 +1529,8 @@ int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | |||
1557 | if (hdr->itt == RESERVED_ITT && !(hdr->opcode & ISCSI_OP_IMMEDIATE)) { | 1529 | if (hdr->itt == RESERVED_ITT && !(hdr->opcode & ISCSI_OP_IMMEDIATE)) { |
1558 | pr_err("NOPOUT ITT is reserved, but Immediate Bit is" | 1530 | pr_err("NOPOUT ITT is reserved, but Immediate Bit is" |
1559 | " not set, protocol error.\n"); | 1531 | " not set, protocol error.\n"); |
1560 | return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, | 1532 | return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, |
1561 | buf, conn); | 1533 | (unsigned char *)hdr); |
1562 | } | 1534 | } |
1563 | 1535 | ||
1564 | if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) { | 1536 | if (payload_length > conn->conn_ops->MaxXmitDataSegmentLength) { |
@@ -1566,8 +1538,8 @@ int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | |||
1566 | " greater than MaxXmitDataSegmentLength: %u, protocol" | 1538 | " greater than MaxXmitDataSegmentLength: %u, protocol" |
1567 | " error.\n", payload_length, | 1539 | " error.\n", payload_length, |
1568 | conn->conn_ops->MaxXmitDataSegmentLength); | 1540 | conn->conn_ops->MaxXmitDataSegmentLength); |
1569 | return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, | 1541 | return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, |
1570 | buf, conn); | 1542 | (unsigned char *)hdr); |
1571 | } | 1543 | } |
1572 | 1544 | ||
1573 | pr_debug("Got NOPOUT Ping %s ITT: 0x%08x, TTT: 0x%08x," | 1545 | pr_debug("Got NOPOUT Ping %s ITT: 0x%08x, TTT: 0x%08x," |
@@ -1584,9 +1556,9 @@ int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | |||
1584 | */ | 1556 | */ |
1585 | if (hdr->ttt == cpu_to_be32(0xFFFFFFFF)) { | 1557 | if (hdr->ttt == cpu_to_be32(0xFFFFFFFF)) { |
1586 | if (!cmd) | 1558 | if (!cmd) |
1587 | return iscsit_add_reject( | 1559 | return iscsit_reject_cmd(cmd, |
1588 | ISCSI_REASON_BOOKMARK_NO_RESOURCES, | 1560 | ISCSI_REASON_BOOKMARK_NO_RESOURCES, |
1589 | 1, buf, conn); | 1561 | (unsigned char *)hdr); |
1590 | 1562 | ||
1591 | cmd->iscsi_opcode = ISCSI_OP_NOOP_OUT; | 1563 | cmd->iscsi_opcode = ISCSI_OP_NOOP_OUT; |
1592 | cmd->i_state = ISTATE_SEND_NOPIN; | 1564 | cmd->i_state = ISTATE_SEND_NOPIN; |
@@ -1706,9 +1678,7 @@ int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | |||
1706 | goto ping_out; | 1678 | goto ping_out; |
1707 | } | 1679 | } |
1708 | if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) | 1680 | if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) |
1709 | return iscsit_add_reject_from_cmd( | 1681 | return -1; |
1710 | ISCSI_REASON_PROTOCOL_ERROR, | ||
1711 | 1, 0, buf, cmd); | ||
1712 | 1682 | ||
1713 | return 0; | 1683 | return 0; |
1714 | } | 1684 | } |
@@ -1782,8 +1752,8 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | |||
1782 | pr_err("Task Management Request TASK_REASSIGN not" | 1752 | pr_err("Task Management Request TASK_REASSIGN not" |
1783 | " issued as immediate command, bad iSCSI Initiator" | 1753 | " issued as immediate command, bad iSCSI Initiator" |
1784 | "implementation\n"); | 1754 | "implementation\n"); |
1785 | return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, | 1755 | return iscsit_add_reject_cmd(cmd, |
1786 | 1, 1, buf, cmd); | 1756 | ISCSI_REASON_PROTOCOL_ERROR, buf); |
1787 | } | 1757 | } |
1788 | if ((function != ISCSI_TM_FUNC_ABORT_TASK) && | 1758 | if ((function != ISCSI_TM_FUNC_ABORT_TASK) && |
1789 | be32_to_cpu(hdr->refcmdsn) != ISCSI_RESERVED_TAG) | 1759 | be32_to_cpu(hdr->refcmdsn) != ISCSI_RESERVED_TAG) |
@@ -1795,9 +1765,9 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | |||
1795 | if (!cmd->tmr_req) { | 1765 | if (!cmd->tmr_req) { |
1796 | pr_err("Unable to allocate memory for" | 1766 | pr_err("Unable to allocate memory for" |
1797 | " Task Management command!\n"); | 1767 | " Task Management command!\n"); |
1798 | return iscsit_add_reject_from_cmd( | 1768 | return iscsit_add_reject_cmd(cmd, |
1799 | ISCSI_REASON_BOOKMARK_NO_RESOURCES, | 1769 | ISCSI_REASON_BOOKMARK_NO_RESOURCES, |
1800 | 1, 1, buf, cmd); | 1770 | buf); |
1801 | } | 1771 | } |
1802 | 1772 | ||
1803 | /* | 1773 | /* |
@@ -1842,17 +1812,15 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | |||
1842 | default: | 1812 | default: |
1843 | pr_err("Unknown iSCSI TMR Function:" | 1813 | pr_err("Unknown iSCSI TMR Function:" |
1844 | " 0x%02x\n", function); | 1814 | " 0x%02x\n", function); |
1845 | return iscsit_add_reject_from_cmd( | 1815 | return iscsit_add_reject_cmd(cmd, |
1846 | ISCSI_REASON_BOOKMARK_NO_RESOURCES, | 1816 | ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf); |
1847 | 1, 1, buf, cmd); | ||
1848 | } | 1817 | } |
1849 | 1818 | ||
1850 | ret = core_tmr_alloc_req(&cmd->se_cmd, cmd->tmr_req, | 1819 | ret = core_tmr_alloc_req(&cmd->se_cmd, cmd->tmr_req, |
1851 | tcm_function, GFP_KERNEL); | 1820 | tcm_function, GFP_KERNEL); |
1852 | if (ret < 0) | 1821 | if (ret < 0) |
1853 | return iscsit_add_reject_from_cmd( | 1822 | return iscsit_add_reject_cmd(cmd, |
1854 | ISCSI_REASON_BOOKMARK_NO_RESOURCES, | 1823 | ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf); |
1855 | 1, 1, buf, cmd); | ||
1856 | 1824 | ||
1857 | cmd->tmr_req->se_tmr_req = cmd->se_cmd.se_tmr_req; | 1825 | cmd->tmr_req->se_tmr_req = cmd->se_cmd.se_tmr_req; |
1858 | } | 1826 | } |
@@ -1911,9 +1879,8 @@ iscsit_handle_task_mgt_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | |||
1911 | break; | 1879 | break; |
1912 | 1880 | ||
1913 | if (iscsit_check_task_reassign_expdatasn(tmr_req, conn) < 0) | 1881 | if (iscsit_check_task_reassign_expdatasn(tmr_req, conn) < 0) |
1914 | return iscsit_add_reject_from_cmd( | 1882 | return iscsit_add_reject_cmd(cmd, |
1915 | ISCSI_REASON_BOOKMARK_INVALID, 1, 1, | 1883 | ISCSI_REASON_BOOKMARK_INVALID, buf); |
1916 | buf, cmd); | ||
1917 | break; | 1884 | break; |
1918 | default: | 1885 | default: |
1919 | pr_err("Unknown TMR function: 0x%02x, protocol" | 1886 | pr_err("Unknown TMR function: 0x%02x, protocol" |
@@ -1937,9 +1904,7 @@ attach: | |||
1937 | else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) | 1904 | else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) |
1938 | return 0; | 1905 | return 0; |
1939 | else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) | 1906 | else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) |
1940 | return iscsit_add_reject_from_cmd( | 1907 | return -1; |
1941 | ISCSI_REASON_PROTOCOL_ERROR, | ||
1942 | 1, 0, buf, cmd); | ||
1943 | } | 1908 | } |
1944 | iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn)); | 1909 | iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn)); |
1945 | 1910 | ||
@@ -1989,8 +1954,7 @@ static int iscsit_handle_text_cmd( | |||
1989 | pr_err("Unable to accept text parameter length: %u" | 1954 | pr_err("Unable to accept text parameter length: %u" |
1990 | "greater than MaxXmitDataSegmentLength %u.\n", | 1955 | "greater than MaxXmitDataSegmentLength %u.\n", |
1991 | payload_length, conn->conn_ops->MaxXmitDataSegmentLength); | 1956 | payload_length, conn->conn_ops->MaxXmitDataSegmentLength); |
1992 | return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, | 1957 | return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR, buf); |
1993 | buf, conn); | ||
1994 | } | 1958 | } |
1995 | 1959 | ||
1996 | pr_debug("Got Text Request: ITT: 0x%08x, CmdSN: 0x%08x," | 1960 | pr_debug("Got Text Request: ITT: 0x%08x, CmdSN: 0x%08x," |
@@ -2092,8 +2056,8 @@ static int iscsit_handle_text_cmd( | |||
2092 | 2056 | ||
2093 | cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); | 2057 | cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); |
2094 | if (!cmd) | 2058 | if (!cmd) |
2095 | return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES, | 2059 | return iscsit_add_reject(conn, |
2096 | 1, buf, conn); | 2060 | ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf); |
2097 | 2061 | ||
2098 | cmd->iscsi_opcode = ISCSI_OP_TEXT; | 2062 | cmd->iscsi_opcode = ISCSI_OP_TEXT; |
2099 | cmd->i_state = ISTATE_SEND_TEXTRSP; | 2063 | cmd->i_state = ISTATE_SEND_TEXTRSP; |
@@ -2113,9 +2077,7 @@ static int iscsit_handle_text_cmd( | |||
2113 | if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) { | 2077 | if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) { |
2114 | cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); | 2078 | cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); |
2115 | if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) | 2079 | if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) |
2116 | return iscsit_add_reject_from_cmd( | 2080 | return -1; |
2117 | ISCSI_REASON_PROTOCOL_ERROR, | ||
2118 | 1, 0, buf, cmd); | ||
2119 | 2081 | ||
2120 | return 0; | 2082 | return 0; |
2121 | } | 2083 | } |
@@ -2301,13 +2263,10 @@ iscsit_handle_logout_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | |||
2301 | return ret; | 2263 | return ret; |
2302 | } else { | 2264 | } else { |
2303 | cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); | 2265 | cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); |
2304 | if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) { | 2266 | if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) |
2305 | logout_remove = 0; | 2267 | logout_remove = 0; |
2306 | } else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) { | 2268 | else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) |
2307 | return iscsit_add_reject_from_cmd( | 2269 | return -1; |
2308 | ISCSI_REASON_PROTOCOL_ERROR, | ||
2309 | 1, 0, buf, cmd); | ||
2310 | } | ||
2311 | } | 2270 | } |
2312 | 2271 | ||
2313 | return logout_remove; | 2272 | return logout_remove; |
@@ -2331,8 +2290,8 @@ static int iscsit_handle_snack( | |||
2331 | if (!conn->sess->sess_ops->ErrorRecoveryLevel) { | 2290 | if (!conn->sess->sess_ops->ErrorRecoveryLevel) { |
2332 | pr_err("Initiator sent SNACK request while in" | 2291 | pr_err("Initiator sent SNACK request while in" |
2333 | " ErrorRecoveryLevel=0.\n"); | 2292 | " ErrorRecoveryLevel=0.\n"); |
2334 | return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, | 2293 | return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR, |
2335 | buf, conn); | 2294 | buf); |
2336 | } | 2295 | } |
2337 | /* | 2296 | /* |
2338 | * SNACK_DATA and SNACK_R2T are both 0, so check which function to | 2297 | * SNACK_DATA and SNACK_R2T are both 0, so check which function to |
@@ -2356,13 +2315,13 @@ static int iscsit_handle_snack( | |||
2356 | case ISCSI_FLAG_SNACK_TYPE_RDATA: | 2315 | case ISCSI_FLAG_SNACK_TYPE_RDATA: |
2357 | /* FIXME: Support R-Data SNACK */ | 2316 | /* FIXME: Support R-Data SNACK */ |
2358 | pr_err("R-Data SNACK Not Supported.\n"); | 2317 | pr_err("R-Data SNACK Not Supported.\n"); |
2359 | return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, | 2318 | return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR, |
2360 | buf, conn); | 2319 | buf); |
2361 | default: | 2320 | default: |
2362 | pr_err("Unknown SNACK type 0x%02x, protocol" | 2321 | pr_err("Unknown SNACK type 0x%02x, protocol" |
2363 | " error.\n", hdr->flags & 0x0f); | 2322 | " error.\n", hdr->flags & 0x0f); |
2364 | return iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, | 2323 | return iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR, |
2365 | buf, conn); | 2324 | buf); |
2366 | } | 2325 | } |
2367 | 2326 | ||
2368 | return 0; | 2327 | return 0; |
@@ -2434,14 +2393,14 @@ static int iscsit_handle_immediate_data( | |||
2434 | pr_err("Unable to recover from" | 2393 | pr_err("Unable to recover from" |
2435 | " Immediate Data digest failure while" | 2394 | " Immediate Data digest failure while" |
2436 | " in ERL=0.\n"); | 2395 | " in ERL=0.\n"); |
2437 | iscsit_add_reject_from_cmd( | 2396 | iscsit_reject_cmd(cmd, |
2438 | ISCSI_REASON_DATA_DIGEST_ERROR, | 2397 | ISCSI_REASON_DATA_DIGEST_ERROR, |
2439 | 1, 0, (unsigned char *)hdr, cmd); | 2398 | (unsigned char *)hdr); |
2440 | return IMMEDIATE_DATA_CANNOT_RECOVER; | 2399 | return IMMEDIATE_DATA_CANNOT_RECOVER; |
2441 | } else { | 2400 | } else { |
2442 | iscsit_add_reject_from_cmd( | 2401 | iscsit_reject_cmd(cmd, |
2443 | ISCSI_REASON_DATA_DIGEST_ERROR, | 2402 | ISCSI_REASON_DATA_DIGEST_ERROR, |
2444 | 0, 0, (unsigned char *)hdr, cmd); | 2403 | (unsigned char *)hdr); |
2445 | return IMMEDIATE_DATA_ERL1_CRC_FAILURE; | 2404 | return IMMEDIATE_DATA_ERL1_CRC_FAILURE; |
2446 | } | 2405 | } |
2447 | } else { | 2406 | } else { |
@@ -3541,6 +3500,7 @@ iscsit_build_reject(struct iscsi_cmd *cmd, struct iscsi_conn *conn, | |||
3541 | struct iscsi_reject *hdr) | 3500 | struct iscsi_reject *hdr) |
3542 | { | 3501 | { |
3543 | hdr->opcode = ISCSI_OP_REJECT; | 3502 | hdr->opcode = ISCSI_OP_REJECT; |
3503 | hdr->reason = cmd->reject_reason; | ||
3544 | hdr->flags |= ISCSI_FLAG_CMD_FINAL; | 3504 | hdr->flags |= ISCSI_FLAG_CMD_FINAL; |
3545 | hton24(hdr->dlength, ISCSI_HDR_LEN); | 3505 | hton24(hdr->dlength, ISCSI_HDR_LEN); |
3546 | hdr->ffffffff = cpu_to_be32(0xffffffff); | 3506 | hdr->ffffffff = cpu_to_be32(0xffffffff); |
@@ -3814,18 +3774,11 @@ check_rsp_state: | |||
3814 | case ISTATE_SEND_STATUS_RECOVERY: | 3774 | case ISTATE_SEND_STATUS_RECOVERY: |
3815 | case ISTATE_SEND_TEXTRSP: | 3775 | case ISTATE_SEND_TEXTRSP: |
3816 | case ISTATE_SEND_TASKMGTRSP: | 3776 | case ISTATE_SEND_TASKMGTRSP: |
3777 | case ISTATE_SEND_REJECT: | ||
3817 | spin_lock_bh(&cmd->istate_lock); | 3778 | spin_lock_bh(&cmd->istate_lock); |
3818 | cmd->i_state = ISTATE_SENT_STATUS; | 3779 | cmd->i_state = ISTATE_SENT_STATUS; |
3819 | spin_unlock_bh(&cmd->istate_lock); | 3780 | spin_unlock_bh(&cmd->istate_lock); |
3820 | break; | 3781 | break; |
3821 | case ISTATE_SEND_REJECT: | ||
3822 | if (cmd->cmd_flags & ICF_REJECT_FAIL_CONN) { | ||
3823 | cmd->cmd_flags &= ~ICF_REJECT_FAIL_CONN; | ||
3824 | complete(&cmd->reject_comp); | ||
3825 | goto err; | ||
3826 | } | ||
3827 | complete(&cmd->reject_comp); | ||
3828 | break; | ||
3829 | default: | 3782 | default: |
3830 | pr_err("Unknown Opcode: 0x%02x ITT:" | 3783 | pr_err("Unknown Opcode: 0x%02x ITT:" |
3831 | " 0x%08x, i_state: %d on CID: %hu\n", | 3784 | " 0x%08x, i_state: %d on CID: %hu\n", |
@@ -3930,8 +3883,7 @@ static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf) | |||
3930 | case ISCSI_OP_SCSI_CMD: | 3883 | case ISCSI_OP_SCSI_CMD: |
3931 | cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); | 3884 | cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); |
3932 | if (!cmd) | 3885 | if (!cmd) |
3933 | return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES, | 3886 | goto reject; |
3934 | 1, buf, conn); | ||
3935 | 3887 | ||
3936 | ret = iscsit_handle_scsi_cmd(conn, cmd, buf); | 3888 | ret = iscsit_handle_scsi_cmd(conn, cmd, buf); |
3937 | break; | 3889 | break; |
@@ -3943,16 +3895,14 @@ static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf) | |||
3943 | if (hdr->ttt == cpu_to_be32(0xFFFFFFFF)) { | 3895 | if (hdr->ttt == cpu_to_be32(0xFFFFFFFF)) { |
3944 | cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); | 3896 | cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); |
3945 | if (!cmd) | 3897 | if (!cmd) |
3946 | return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES, | 3898 | goto reject; |
3947 | 1, buf, conn); | ||
3948 | } | 3899 | } |
3949 | ret = iscsit_handle_nop_out(conn, cmd, buf); | 3900 | ret = iscsit_handle_nop_out(conn, cmd, buf); |
3950 | break; | 3901 | break; |
3951 | case ISCSI_OP_SCSI_TMFUNC: | 3902 | case ISCSI_OP_SCSI_TMFUNC: |
3952 | cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); | 3903 | cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); |
3953 | if (!cmd) | 3904 | if (!cmd) |
3954 | return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES, | 3905 | goto reject; |
3955 | 1, buf, conn); | ||
3956 | 3906 | ||
3957 | ret = iscsit_handle_task_mgt_cmd(conn, cmd, buf); | 3907 | ret = iscsit_handle_task_mgt_cmd(conn, cmd, buf); |
3958 | break; | 3908 | break; |
@@ -3962,8 +3912,7 @@ static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf) | |||
3962 | case ISCSI_OP_LOGOUT: | 3912 | case ISCSI_OP_LOGOUT: |
3963 | cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); | 3913 | cmd = iscsit_allocate_cmd(conn, GFP_KERNEL); |
3964 | if (!cmd) | 3914 | if (!cmd) |
3965 | return iscsit_add_reject(ISCSI_REASON_BOOKMARK_NO_RESOURCES, | 3915 | goto reject; |
3966 | 1, buf, conn); | ||
3967 | 3916 | ||
3968 | ret = iscsit_handle_logout_cmd(conn, cmd, buf); | 3917 | ret = iscsit_handle_logout_cmd(conn, cmd, buf); |
3969 | if (ret > 0) | 3918 | if (ret > 0) |
@@ -3995,6 +3944,8 @@ static int iscsi_target_rx_opcode(struct iscsi_conn *conn, unsigned char *buf) | |||
3995 | } | 3944 | } |
3996 | 3945 | ||
3997 | return ret; | 3946 | return ret; |
3947 | reject: | ||
3948 | return iscsit_add_reject(conn, ISCSI_REASON_BOOKMARK_NO_RESOURCES, buf); | ||
3998 | } | 3949 | } |
3999 | 3950 | ||
4000 | int iscsi_target_rx_thread(void *arg) | 3951 | int iscsi_target_rx_thread(void *arg) |
@@ -4094,8 +4045,8 @@ restart: | |||
4094 | (!(opcode & ISCSI_OP_LOGOUT)))) { | 4045 | (!(opcode & ISCSI_OP_LOGOUT)))) { |
4095 | pr_err("Received illegal iSCSI Opcode: 0x%02x" | 4046 | pr_err("Received illegal iSCSI Opcode: 0x%02x" |
4096 | " while in Discovery Session, rejecting.\n", opcode); | 4047 | " while in Discovery Session, rejecting.\n", opcode); |
4097 | iscsit_add_reject(ISCSI_REASON_PROTOCOL_ERROR, 1, | 4048 | iscsit_add_reject(conn, ISCSI_REASON_PROTOCOL_ERROR, |
4098 | buffer, conn); | 4049 | buffer); |
4099 | goto transport_err; | 4050 | goto transport_err; |
4100 | } | 4051 | } |
4101 | 4052 | ||
diff --git a/drivers/target/iscsi/iscsi_target.h b/drivers/target/iscsi/iscsi_target.h index a0050b2f294e..2c437cb8ca00 100644 --- a/drivers/target/iscsi/iscsi_target.h +++ b/drivers/target/iscsi/iscsi_target.h | |||
@@ -15,7 +15,7 @@ extern struct iscsi_np *iscsit_add_np(struct __kernel_sockaddr_storage *, | |||
15 | extern int iscsit_reset_np_thread(struct iscsi_np *, struct iscsi_tpg_np *, | 15 | extern int iscsit_reset_np_thread(struct iscsi_np *, struct iscsi_tpg_np *, |
16 | struct iscsi_portal_group *); | 16 | struct iscsi_portal_group *); |
17 | extern int iscsit_del_np(struct iscsi_np *); | 17 | extern int iscsit_del_np(struct iscsi_np *); |
18 | extern int iscsit_add_reject_from_cmd(u8, int, int, unsigned char *, struct iscsi_cmd *); | 18 | extern int iscsit_reject_cmd(struct iscsi_cmd *cmd, u8, unsigned char *); |
19 | extern void iscsit_set_unsoliticed_dataout(struct iscsi_cmd *); | 19 | extern void iscsit_set_unsoliticed_dataout(struct iscsi_cmd *); |
20 | extern int iscsit_logout_closesession(struct iscsi_cmd *, struct iscsi_conn *); | 20 | extern int iscsit_logout_closesession(struct iscsi_cmd *, struct iscsi_conn *); |
21 | extern int iscsit_logout_closeconnection(struct iscsi_cmd *, struct iscsi_conn *); | 21 | extern int iscsit_logout_closeconnection(struct iscsi_cmd *, struct iscsi_conn *); |
diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index 60ec4b92be03..8907dcdc0db9 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h | |||
@@ -132,7 +132,6 @@ enum cmd_flags_table { | |||
132 | ICF_CONTIG_MEMORY = 0x00000020, | 132 | ICF_CONTIG_MEMORY = 0x00000020, |
133 | ICF_ATTACHED_TO_RQUEUE = 0x00000040, | 133 | ICF_ATTACHED_TO_RQUEUE = 0x00000040, |
134 | ICF_OOO_CMDSN = 0x00000080, | 134 | ICF_OOO_CMDSN = 0x00000080, |
135 | ICF_REJECT_FAIL_CONN = 0x00000100, | ||
136 | }; | 135 | }; |
137 | 136 | ||
138 | /* struct iscsi_cmd->i_state */ | 137 | /* struct iscsi_cmd->i_state */ |
@@ -366,6 +365,8 @@ struct iscsi_cmd { | |||
366 | u8 maxcmdsn_inc; | 365 | u8 maxcmdsn_inc; |
367 | /* Immediate Unsolicited Dataout */ | 366 | /* Immediate Unsolicited Dataout */ |
368 | u8 unsolicited_data; | 367 | u8 unsolicited_data; |
368 | /* Reject reason code */ | ||
369 | u8 reject_reason; | ||
369 | /* CID contained in logout PDU when opcode == ISCSI_INIT_LOGOUT_CMND */ | 370 | /* CID contained in logout PDU when opcode == ISCSI_INIT_LOGOUT_CMND */ |
370 | u16 logout_cid; | 371 | u16 logout_cid; |
371 | /* Command flags */ | 372 | /* Command flags */ |
@@ -446,7 +447,6 @@ struct iscsi_cmd { | |||
446 | struct list_head datain_list; | 447 | struct list_head datain_list; |
447 | /* R2T List */ | 448 | /* R2T List */ |
448 | struct list_head cmd_r2t_list; | 449 | struct list_head cmd_r2t_list; |
449 | struct completion reject_comp; | ||
450 | /* Timer for DataOUT */ | 450 | /* Timer for DataOUT */ |
451 | struct timer_list dataout_timer; | 451 | struct timer_list dataout_timer; |
452 | /* Iovecs for SCSI data payload RX/TX w/ kernel level sockets */ | 452 | /* Iovecs for SCSI data payload RX/TX w/ kernel level sockets */ |
diff --git a/drivers/target/iscsi/iscsi_target_erl0.c b/drivers/target/iscsi/iscsi_target_erl0.c index 7f1116635d17..08bd87833321 100644 --- a/drivers/target/iscsi/iscsi_target_erl0.c +++ b/drivers/target/iscsi/iscsi_target_erl0.c | |||
@@ -746,13 +746,12 @@ int iscsit_check_post_dataout( | |||
746 | if (!conn->sess->sess_ops->ErrorRecoveryLevel) { | 746 | if (!conn->sess->sess_ops->ErrorRecoveryLevel) { |
747 | pr_err("Unable to recover from DataOUT CRC" | 747 | pr_err("Unable to recover from DataOUT CRC" |
748 | " failure while ERL=0, closing session.\n"); | 748 | " failure while ERL=0, closing session.\n"); |
749 | iscsit_add_reject_from_cmd(ISCSI_REASON_DATA_DIGEST_ERROR, | 749 | iscsit_reject_cmd(cmd, ISCSI_REASON_DATA_DIGEST_ERROR, |
750 | 1, 0, buf, cmd); | 750 | buf); |
751 | return DATAOUT_CANNOT_RECOVER; | 751 | return DATAOUT_CANNOT_RECOVER; |
752 | } | 752 | } |
753 | 753 | ||
754 | iscsit_add_reject_from_cmd(ISCSI_REASON_DATA_DIGEST_ERROR, | 754 | iscsit_reject_cmd(cmd, ISCSI_REASON_DATA_DIGEST_ERROR, buf); |
755 | 0, 0, buf, cmd); | ||
756 | return iscsit_dataout_post_crc_failed(cmd, buf); | 755 | return iscsit_dataout_post_crc_failed(cmd, buf); |
757 | } | 756 | } |
758 | } | 757 | } |
diff --git a/drivers/target/iscsi/iscsi_target_erl1.c b/drivers/target/iscsi/iscsi_target_erl1.c index 40d9dbca987b..d00f1326f0c8 100644 --- a/drivers/target/iscsi/iscsi_target_erl1.c +++ b/drivers/target/iscsi/iscsi_target_erl1.c | |||
@@ -162,9 +162,8 @@ static int iscsit_handle_r2t_snack( | |||
162 | " protocol error.\n", cmd->init_task_tag, begrun, | 162 | " protocol error.\n", cmd->init_task_tag, begrun, |
163 | (begrun + runlength), cmd->acked_data_sn); | 163 | (begrun + runlength), cmd->acked_data_sn); |
164 | 164 | ||
165 | return iscsit_add_reject_from_cmd( | 165 | return iscsit_reject_cmd(cmd, |
166 | ISCSI_REASON_PROTOCOL_ERROR, | 166 | ISCSI_REASON_PROTOCOL_ERROR, buf); |
167 | 1, 0, buf, cmd); | ||
168 | } | 167 | } |
169 | 168 | ||
170 | if (runlength) { | 169 | if (runlength) { |
@@ -173,8 +172,8 @@ static int iscsit_handle_r2t_snack( | |||
173 | " with BegRun: 0x%08x, RunLength: 0x%08x, exceeds" | 172 | " with BegRun: 0x%08x, RunLength: 0x%08x, exceeds" |
174 | " current R2TSN: 0x%08x, protocol error.\n", | 173 | " current R2TSN: 0x%08x, protocol error.\n", |
175 | cmd->init_task_tag, begrun, runlength, cmd->r2t_sn); | 174 | cmd->init_task_tag, begrun, runlength, cmd->r2t_sn); |
176 | return iscsit_add_reject_from_cmd( | 175 | return iscsit_reject_cmd(cmd, |
177 | ISCSI_REASON_BOOKMARK_INVALID, 1, 0, buf, cmd); | 176 | ISCSI_REASON_BOOKMARK_INVALID, buf); |
178 | } | 177 | } |
179 | last_r2tsn = (begrun + runlength); | 178 | last_r2tsn = (begrun + runlength); |
180 | } else | 179 | } else |
@@ -433,8 +432,7 @@ static int iscsit_handle_recovery_datain( | |||
433 | " protocol error.\n", cmd->init_task_tag, begrun, | 432 | " protocol error.\n", cmd->init_task_tag, begrun, |
434 | (begrun + runlength), cmd->acked_data_sn); | 433 | (begrun + runlength), cmd->acked_data_sn); |
435 | 434 | ||
436 | return iscsit_add_reject_from_cmd(ISCSI_REASON_PROTOCOL_ERROR, | 435 | return iscsit_reject_cmd(cmd, ISCSI_REASON_PROTOCOL_ERROR, buf); |
437 | 1, 0, buf, cmd); | ||
438 | } | 436 | } |
439 | 437 | ||
440 | /* | 438 | /* |
@@ -445,14 +443,14 @@ static int iscsit_handle_recovery_datain( | |||
445 | pr_err("Initiator requesting BegRun: 0x%08x, RunLength" | 443 | pr_err("Initiator requesting BegRun: 0x%08x, RunLength" |
446 | ": 0x%08x greater than maximum DataSN: 0x%08x.\n", | 444 | ": 0x%08x greater than maximum DataSN: 0x%08x.\n", |
447 | begrun, runlength, (cmd->data_sn - 1)); | 445 | begrun, runlength, (cmd->data_sn - 1)); |
448 | return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_INVALID, | 446 | return iscsit_reject_cmd(cmd, ISCSI_REASON_BOOKMARK_INVALID, |
449 | 1, 0, buf, cmd); | 447 | buf); |
450 | } | 448 | } |
451 | 449 | ||
452 | dr = iscsit_allocate_datain_req(); | 450 | dr = iscsit_allocate_datain_req(); |
453 | if (!dr) | 451 | if (!dr) |
454 | return iscsit_add_reject_from_cmd(ISCSI_REASON_BOOKMARK_NO_RESOURCES, | 452 | return iscsit_reject_cmd(cmd, ISCSI_REASON_BOOKMARK_NO_RESOURCES, |
455 | 1, 0, buf, cmd); | 453 | buf); |
456 | 454 | ||
457 | dr->data_sn = dr->begrun = begrun; | 455 | dr->data_sn = dr->begrun = begrun; |
458 | dr->runlength = runlength; | 456 | dr->runlength = runlength; |
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index 08a3bacef0c5..6374a1a98d6b 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c | |||
@@ -178,7 +178,6 @@ struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *conn, gfp_t gfp_mask) | |||
178 | INIT_LIST_HEAD(&cmd->i_conn_node); | 178 | INIT_LIST_HEAD(&cmd->i_conn_node); |
179 | INIT_LIST_HEAD(&cmd->datain_list); | 179 | INIT_LIST_HEAD(&cmd->datain_list); |
180 | INIT_LIST_HEAD(&cmd->cmd_r2t_list); | 180 | INIT_LIST_HEAD(&cmd->cmd_r2t_list); |
181 | init_completion(&cmd->reject_comp); | ||
182 | spin_lock_init(&cmd->datain_lock); | 181 | spin_lock_init(&cmd->datain_lock); |
183 | spin_lock_init(&cmd->dataout_timeout_lock); | 182 | spin_lock_init(&cmd->dataout_timeout_lock); |
184 | spin_lock_init(&cmd->istate_lock); | 183 | spin_lock_init(&cmd->istate_lock); |
diff --git a/include/target/iscsi/iscsi_transport.h b/include/target/iscsi/iscsi_transport.h index 6db632eb3821..c8da4dd11d26 100644 --- a/include/target/iscsi/iscsi_transport.h +++ b/include/target/iscsi/iscsi_transport.h | |||
@@ -34,8 +34,6 @@ extern void iscsit_put_transport(struct iscsit_transport *); | |||
34 | /* | 34 | /* |
35 | * From iscsi_target.c | 35 | * From iscsi_target.c |
36 | */ | 36 | */ |
37 | extern int iscsit_add_reject_from_cmd(u8, int, int, unsigned char *, | ||
38 | struct iscsi_cmd *); | ||
39 | extern int iscsit_setup_scsi_cmd(struct iscsi_conn *, struct iscsi_cmd *, | 37 | extern int iscsit_setup_scsi_cmd(struct iscsi_conn *, struct iscsi_cmd *, |
40 | unsigned char *); | 38 | unsigned char *); |
41 | extern void iscsit_set_unsoliticed_dataout(struct iscsi_cmd *); | 39 | extern void iscsit_set_unsoliticed_dataout(struct iscsi_cmd *); |