aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2013-07-03 06:58:58 -0400
committerNicholas Bellinger <nab@linux-iscsi.org>2013-07-07 00:59:54 -0400
commit561bf15892375597ee59d473a704a3e634c4f311 (patch)
tree9c731875ce9cb03540692e8e6332a7ba47273c97
parentba159914086f06532079fc15141f46ffe7e04a41 (diff)
iscsi-target: Fix iscsit_sequence_cmd reject handling for iser
This patch moves ISCSI_OP_REJECT failures into iscsit_sequence_cmd() in order to avoid external iscsit_reject_cmd() reject usage for all PDU types. It also updates PDU specific handlers for traditional iscsi-target code to not reset the session after posting a ISCSI_OP_REJECT during setup. (v2: Fix CMDSN_LOWER_THAN_EXP for ISCSI_OP_SCSI to call target_put_sess_cmd() after iscsit_sequence_cmd() failure) Cc: Or Gerlitz <ogerlitz@mellanox.com> Cc: Mike Christie <michaelc@cs.wisc.edu> Cc: stable@vger.kernel.org # 3.10+ Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
-rw-r--r--drivers/infiniband/ulp/isert/ib_isert.c2
-rw-r--r--drivers/target/iscsi/iscsi_target.c55
-rw-r--r--drivers/target/iscsi/iscsi_target_erl1.c6
-rw-r--r--drivers/target/iscsi/iscsi_target_util.c26
-rw-r--r--drivers/target/iscsi/iscsi_target_util.h3
-rw-r--r--include/target/iscsi/iscsi_transport.h3
6 files changed, 62 insertions, 33 deletions
diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c
index 134ff58c6b17..7e219a46e7ca 100644
--- a/drivers/infiniband/ulp/isert/ib_isert.c
+++ b/drivers/infiniband/ulp/isert/ib_isert.c
@@ -934,7 +934,7 @@ isert_handle_scsi_cmd(struct isert_conn *isert_conn,
934 } 934 }
935 935
936sequence_cmd: 936sequence_cmd:
937 rc = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); 937 rc = iscsit_sequence_cmd(conn, cmd, buf, hdr->cmdsn);
938 938
939 if (!rc && dump_payload == false && unsol_data) 939 if (!rc && dump_payload == false && unsol_data)
940 iscsit_set_unsoliticed_dataout(cmd); 940 iscsit_set_unsoliticed_dataout(cmd);
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index 2a25bd3b065c..4319dad7d919 100644
--- a/drivers/target/iscsi/iscsi_target.c
+++ b/drivers/target/iscsi/iscsi_target.c
@@ -1052,11 +1052,11 @@ int iscsit_process_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
1052 * be acknowledged. (See below) 1052 * be acknowledged. (See below)
1053 */ 1053 */
1054 if (!cmd->immediate_data) { 1054 if (!cmd->immediate_data) {
1055 cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); 1055 cmdsn_ret = iscsit_sequence_cmd(conn, cmd,
1056 if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) { 1056 (unsigned char *)hdr, hdr->cmdsn);
1057 if (!cmd->sense_reason) 1057 if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
1058 return 0; 1058 return -1;
1059 1059 else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
1060 target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); 1060 target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
1061 return 0; 1061 return 0;
1062 } 1062 }
@@ -1083,6 +1083,9 @@ int iscsit_process_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
1083 * iscsit_check_received_cmdsn() in iscsit_get_immediate_data() below. 1083 * iscsit_check_received_cmdsn() in iscsit_get_immediate_data() below.
1084 */ 1084 */
1085 if (cmd->sense_reason) { 1085 if (cmd->sense_reason) {
1086 if (cmd->reject_reason)
1087 return 0;
1088
1086 target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd); 1089 target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
1087 return 1; 1090 return 1;
1088 } 1091 }
@@ -1091,10 +1094,8 @@ int iscsit_process_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
1091 * the backend memory allocation. 1094 * the backend memory allocation.
1092 */ 1095 */
1093 cmd->sense_reason = transport_generic_new_cmd(&cmd->se_cmd); 1096 cmd->sense_reason = transport_generic_new_cmd(&cmd->se_cmd);
1094 if (cmd->sense_reason) { 1097 if (cmd->sense_reason)
1095 target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
1096 return 1; 1098 return 1;
1097 }
1098 1099
1099 return 0; 1100 return 0;
1100} 1101}
@@ -1104,6 +1105,7 @@ static int
1104iscsit_get_immediate_data(struct iscsi_cmd *cmd, struct iscsi_scsi_req *hdr, 1105iscsit_get_immediate_data(struct iscsi_cmd *cmd, struct iscsi_scsi_req *hdr,
1105 bool dump_payload) 1106 bool dump_payload)
1106{ 1107{
1108 struct iscsi_conn *conn = cmd->conn;
1107 int cmdsn_ret = 0, immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION; 1109 int cmdsn_ret = 0, immed_ret = IMMEDIATE_DATA_NORMAL_OPERATION;
1108 /* 1110 /*
1109 * Special case for Unsupported SAM WRITE Opcodes and ImmediateData=Yes. 1111 * Special case for Unsupported SAM WRITE Opcodes and ImmediateData=Yes.
@@ -1120,12 +1122,22 @@ after_immediate_data:
1120 * DataCRC, check against ExpCmdSN/MaxCmdSN if 1122 * DataCRC, check against ExpCmdSN/MaxCmdSN if
1121 * Immediate Bit is not set. 1123 * Immediate Bit is not set.
1122 */ 1124 */
1123 cmdsn_ret = iscsit_sequence_cmd(cmd->conn, cmd, hdr->cmdsn); 1125 cmdsn_ret = iscsit_sequence_cmd(cmd->conn, cmd,
1126 (unsigned char *)hdr, hdr->cmdsn);
1127 if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) {
1128 return -1;
1129 } else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
1130 target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
1131 return 0;
1132 }
1124 1133
1125 if (cmd->sense_reason) { 1134 if (cmd->sense_reason) {
1126 if (iscsit_dump_data_payload(cmd->conn, 1135 int rc;
1127 cmd->first_burst_len, 1) < 0) 1136
1128 return -1; 1137 rc = iscsit_dump_data_payload(cmd->conn,
1138 cmd->first_burst_len, 1);
1139 target_put_sess_cmd(conn->sess->se_sess, &cmd->se_cmd);
1140 return rc;
1129 } else if (cmd->unsolicited_data) 1141 } else if (cmd->unsolicited_data)
1130 iscsit_set_unsoliticed_dataout(cmd); 1142 iscsit_set_unsoliticed_dataout(cmd);
1131 1143
@@ -1159,7 +1171,7 @@ iscsit_handle_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
1159 1171
1160 rc = iscsit_setup_scsi_cmd(conn, cmd, buf); 1172 rc = iscsit_setup_scsi_cmd(conn, cmd, buf);
1161 if (rc < 0) 1173 if (rc < 0)
1162 return rc; 1174 return 0;
1163 /* 1175 /*
1164 * Allocation iovecs needed for struct socket operations for 1176 * Allocation iovecs needed for struct socket operations for
1165 * traditional iSCSI block I/O. 1177 * traditional iSCSI block I/O.
@@ -1494,7 +1506,7 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf)
1494 1506
1495 rc = iscsit_check_dataout_hdr(conn, buf, &cmd); 1507 rc = iscsit_check_dataout_hdr(conn, buf, &cmd);
1496 if (rc < 0) 1508 if (rc < 0)
1497 return rc; 1509 return 0;
1498 else if (!cmd) 1510 else if (!cmd)
1499 return 0; 1511 return 0;
1500 1512
@@ -1579,10 +1591,10 @@ int iscsit_process_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
1579 return 0; 1591 return 0;
1580 } 1592 }
1581 1593
1582 cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); 1594 cmdsn_ret = iscsit_sequence_cmd(conn, cmd,
1595 (unsigned char *)hdr, hdr->cmdsn);
1583 if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) 1596 if (cmdsn_ret == CMDSN_LOWER_THAN_EXP)
1584 return 0; 1597 return 0;
1585
1586 if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) 1598 if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
1587 return -1; 1599 return -1;
1588 1600
@@ -1623,7 +1635,7 @@ static int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
1623 1635
1624 ret = iscsit_setup_nop_out(conn, cmd, hdr); 1636 ret = iscsit_setup_nop_out(conn, cmd, hdr);
1625 if (ret < 0) 1637 if (ret < 0)
1626 return ret; 1638 return 0;
1627 /* 1639 /*
1628 * Handle NOP-OUT payload for traditional iSCSI sockets 1640 * Handle NOP-OUT payload for traditional iSCSI sockets
1629 */ 1641 */
@@ -1893,7 +1905,7 @@ attach:
1893 spin_unlock_bh(&conn->cmd_lock); 1905 spin_unlock_bh(&conn->cmd_lock);
1894 1906
1895 if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) { 1907 if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
1896 int cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); 1908 int cmdsn_ret = iscsit_sequence_cmd(conn, cmd, buf, hdr->cmdsn);
1897 if (cmdsn_ret == CMDSN_HIGHER_THAN_EXP) 1909 if (cmdsn_ret == CMDSN_HIGHER_THAN_EXP)
1898 out_of_order_cmdsn = 1; 1910 out_of_order_cmdsn = 1;
1899 else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) 1911 else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP)
@@ -1996,7 +2008,8 @@ iscsit_process_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
1996 iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn)); 2008 iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
1997 2009
1998 if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) { 2010 if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
1999 cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); 2011 cmdsn_ret = iscsit_sequence_cmd(conn, cmd,
2012 (unsigned char *)hdr, hdr->cmdsn);
2000 if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) 2013 if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
2001 return -1; 2014 return -1;
2002 2015
@@ -2022,7 +2035,7 @@ iscsit_handle_text_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
2022 2035
2023 rc = iscsit_setup_text_cmd(conn, cmd, hdr); 2036 rc = iscsit_setup_text_cmd(conn, cmd, hdr);
2024 if (rc < 0) 2037 if (rc < 0)
2025 return rc; 2038 return 0;
2026 2039
2027 rx_size = payload_length; 2040 rx_size = payload_length;
2028 if (payload_length) { 2041 if (payload_length) {
@@ -2284,7 +2297,7 @@ iscsit_handle_logout_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
2284 if (ret < 0) 2297 if (ret < 0)
2285 return ret; 2298 return ret;
2286 } else { 2299 } else {
2287 cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); 2300 cmdsn_ret = iscsit_sequence_cmd(conn, cmd, buf, hdr->cmdsn);
2288 if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) 2301 if (cmdsn_ret == CMDSN_LOWER_THAN_EXP)
2289 logout_remove = 0; 2302 logout_remove = 0;
2290 else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) 2303 else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
diff --git a/drivers/target/iscsi/iscsi_target_erl1.c b/drivers/target/iscsi/iscsi_target_erl1.c
index d00f1326f0c8..586c268679a4 100644
--- a/drivers/target/iscsi/iscsi_target_erl1.c
+++ b/drivers/target/iscsi/iscsi_target_erl1.c
@@ -1088,7 +1088,7 @@ int iscsit_handle_ooo_cmdsn(
1088 1088
1089 ooo_cmdsn = iscsit_allocate_ooo_cmdsn(); 1089 ooo_cmdsn = iscsit_allocate_ooo_cmdsn();
1090 if (!ooo_cmdsn) 1090 if (!ooo_cmdsn)
1091 return CMDSN_ERROR_CANNOT_RECOVER; 1091 return -ENOMEM;
1092 1092
1093 ooo_cmdsn->cmd = cmd; 1093 ooo_cmdsn->cmd = cmd;
1094 ooo_cmdsn->batch_count = (batch) ? 1094 ooo_cmdsn->batch_count = (batch) ?
@@ -1099,10 +1099,10 @@ int iscsit_handle_ooo_cmdsn(
1099 1099
1100 if (iscsit_attach_ooo_cmdsn(sess, ooo_cmdsn) < 0) { 1100 if (iscsit_attach_ooo_cmdsn(sess, ooo_cmdsn) < 0) {
1101 kmem_cache_free(lio_ooo_cache, ooo_cmdsn); 1101 kmem_cache_free(lio_ooo_cache, ooo_cmdsn);
1102 return CMDSN_ERROR_CANNOT_RECOVER; 1102 return -ENOMEM;
1103 } 1103 }
1104 1104
1105 return CMDSN_HIGHER_THAN_EXP; 1105 return 0;
1106} 1106}
1107 1107
1108static int iscsit_set_dataout_timeout_values( 1108static int iscsit_set_dataout_timeout_values(
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c
index 96ce6f2ec428..1df06d5e4e01 100644
--- a/drivers/target/iscsi/iscsi_target_util.c
+++ b/drivers/target/iscsi/iscsi_target_util.c
@@ -283,13 +283,12 @@ static inline int iscsit_check_received_cmdsn(struct iscsi_session *sess, u32 cm
283 * Commands may be received out of order if MC/S is in use. 283 * Commands may be received out of order if MC/S is in use.
284 * Ensure they are executed in CmdSN order. 284 * Ensure they are executed in CmdSN order.
285 */ 285 */
286int iscsit_sequence_cmd( 286int iscsit_sequence_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
287 struct iscsi_conn *conn, 287 unsigned char *buf, __be32 cmdsn)
288 struct iscsi_cmd *cmd,
289 __be32 cmdsn)
290{ 288{
291 int ret; 289 int ret, cmdsn_ret;
292 int cmdsn_ret; 290 bool reject = false;
291 u8 reason = ISCSI_REASON_BOOKMARK_NO_RESOURCES;
293 292
294 mutex_lock(&conn->sess->cmdsn_mutex); 293 mutex_lock(&conn->sess->cmdsn_mutex);
295 294
@@ -299,9 +298,19 @@ int iscsit_sequence_cmd(
299 ret = iscsit_execute_cmd(cmd, 0); 298 ret = iscsit_execute_cmd(cmd, 0);
300 if ((ret >= 0) && !list_empty(&conn->sess->sess_ooo_cmdsn_list)) 299 if ((ret >= 0) && !list_empty(&conn->sess->sess_ooo_cmdsn_list))
301 iscsit_execute_ooo_cmdsns(conn->sess); 300 iscsit_execute_ooo_cmdsns(conn->sess);
301 else if (ret < 0) {
302 reject = true;
303 ret = CMDSN_ERROR_CANNOT_RECOVER;
304 }
302 break; 305 break;
303 case CMDSN_HIGHER_THAN_EXP: 306 case CMDSN_HIGHER_THAN_EXP:
304 ret = iscsit_handle_ooo_cmdsn(conn->sess, cmd, be32_to_cpu(cmdsn)); 307 ret = iscsit_handle_ooo_cmdsn(conn->sess, cmd, be32_to_cpu(cmdsn));
308 if (ret < 0) {
309 reject = true;
310 ret = CMDSN_ERROR_CANNOT_RECOVER;
311 break;
312 }
313 ret = CMDSN_HIGHER_THAN_EXP;
305 break; 314 break;
306 case CMDSN_LOWER_THAN_EXP: 315 case CMDSN_LOWER_THAN_EXP:
307 cmd->i_state = ISTATE_REMOVE; 316 cmd->i_state = ISTATE_REMOVE;
@@ -309,11 +318,16 @@ int iscsit_sequence_cmd(
309 ret = cmdsn_ret; 318 ret = cmdsn_ret;
310 break; 319 break;
311 default: 320 default:
321 reason = ISCSI_REASON_PROTOCOL_ERROR;
322 reject = true;
312 ret = cmdsn_ret; 323 ret = cmdsn_ret;
313 break; 324 break;
314 } 325 }
315 mutex_unlock(&conn->sess->cmdsn_mutex); 326 mutex_unlock(&conn->sess->cmdsn_mutex);
316 327
328 if (reject)
329 iscsit_reject_cmd(cmd, reason, buf);
330
317 return ret; 331 return ret;
318} 332}
319EXPORT_SYMBOL(iscsit_sequence_cmd); 333EXPORT_SYMBOL(iscsit_sequence_cmd);
diff --git a/drivers/target/iscsi/iscsi_target_util.h b/drivers/target/iscsi/iscsi_target_util.h
index a4422659d049..e4fc34a02f57 100644
--- a/drivers/target/iscsi/iscsi_target_util.h
+++ b/drivers/target/iscsi/iscsi_target_util.h
@@ -13,7 +13,8 @@ extern struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *, gfp_t);
13extern struct iscsi_seq *iscsit_get_seq_holder_for_datain(struct iscsi_cmd *, u32); 13extern struct iscsi_seq *iscsit_get_seq_holder_for_datain(struct iscsi_cmd *, u32);
14extern struct iscsi_seq *iscsit_get_seq_holder_for_r2t(struct iscsi_cmd *); 14extern struct iscsi_seq *iscsit_get_seq_holder_for_r2t(struct iscsi_cmd *);
15extern struct iscsi_r2t *iscsit_get_holder_for_r2tsn(struct iscsi_cmd *, u32); 15extern struct iscsi_r2t *iscsit_get_holder_for_r2tsn(struct iscsi_cmd *, u32);
16int iscsit_sequence_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, __be32 cmdsn); 16extern int iscsit_sequence_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
17 unsigned char * ,__be32 cmdsn);
17extern int iscsit_check_unsolicited_dataout(struct iscsi_cmd *, unsigned char *); 18extern int iscsit_check_unsolicited_dataout(struct iscsi_cmd *, unsigned char *);
18extern struct iscsi_cmd *iscsit_find_cmd_from_itt(struct iscsi_conn *, itt_t); 19extern struct iscsi_cmd *iscsit_find_cmd_from_itt(struct iscsi_conn *, itt_t);
19extern struct iscsi_cmd *iscsit_find_cmd_from_itt_or_dump(struct iscsi_conn *, 20extern struct iscsi_cmd *iscsit_find_cmd_from_itt_or_dump(struct iscsi_conn *,
diff --git a/include/target/iscsi/iscsi_transport.h b/include/target/iscsi/iscsi_transport.h
index 19a43ad977c2..ce4070d8f156 100644
--- a/include/target/iscsi/iscsi_transport.h
+++ b/include/target/iscsi/iscsi_transport.h
@@ -86,4 +86,5 @@ extern int iscsit_tmr_post_handler(struct iscsi_cmd *, struct iscsi_conn *);
86 * From iscsi_target_util.c 86 * From iscsi_target_util.c
87 */ 87 */
88extern struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *, gfp_t); 88extern struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *, gfp_t);
89extern int iscsit_sequence_cmd(struct iscsi_conn *, struct iscsi_cmd *, __be32); 89extern int iscsit_sequence_cmd(struct iscsi_conn *, struct iscsi_cmd *,
90 unsigned char *, __be32);