aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNicholas Bellinger <nab@linux-iscsi.org>2013-07-30 00:04:02 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-08-04 04:51:17 -0400
commitadb97c299904814edb0bb26ae894139ca46ae446 (patch)
tree280a717a52abb15847e98d4e9f85b5c54b672d26
parent1aa58ccd029fc75c115ae35c3fcb4d43043c0725 (diff)
iscsi-target: Fix iscsit_sequence_cmd reject handling for iser
commit 561bf15892375597ee59d473a704a3e634c4f311 upstream 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) 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.c2
-rw-r--r--drivers/target/iscsi/iscsi_target.c50
-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, 60 insertions, 30 deletions
diff --git a/drivers/infiniband/ulp/isert/ib_isert.c b/drivers/infiniband/ulp/isert/ib_isert.c
index 4f6faf0915d5..5849dc0726b9 100644
--- a/drivers/infiniband/ulp/isert/ib_isert.c
+++ b/drivers/infiniband/ulp/isert/ib_isert.c
@@ -952,7 +952,7 @@ isert_handle_scsi_cmd(struct isert_conn *isert_conn,
952 } 952 }
953 953
954sequence_cmd: 954sequence_cmd:
955 rc = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); 955 rc = iscsit_sequence_cmd(conn, cmd, buf, hdr->cmdsn);
956 956
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);
diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c
index 03ccb610d2bb..012ff8bab0f8 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.
@@ -1500,7 +1512,7 @@ static int iscsit_handle_data_out(struct iscsi_conn *conn, unsigned char *buf)
1500 1512
1501 rc = iscsit_check_dataout_hdr(conn, buf, &cmd); 1513 rc = iscsit_check_dataout_hdr(conn, buf, &cmd);
1502 if (rc < 0) 1514 if (rc < 0)
1503 return rc; 1515 return 0;
1504 else if (!cmd) 1516 else if (!cmd)
1505 return 0; 1517 return 0;
1506 1518
@@ -1672,7 +1684,8 @@ int iscsit_handle_nop_out(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
1672 return 0; 1684 return 0;
1673 } 1685 }
1674 1686
1675 cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); 1687 cmdsn_ret = iscsit_sequence_cmd(conn, cmd,
1688 (unsigned char *)hdr, hdr->cmdsn);
1676 if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) { 1689 if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) {
1677 ret = 0; 1690 ret = 0;
1678 goto ping_out; 1691 goto ping_out;
@@ -1898,7 +1911,7 @@ attach:
1898 spin_unlock_bh(&conn->cmd_lock); 1911 spin_unlock_bh(&conn->cmd_lock);
1899 1912
1900 if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) { 1913 if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
1901 int cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); 1914 int cmdsn_ret = iscsit_sequence_cmd(conn, cmd, buf, hdr->cmdsn);
1902 if (cmdsn_ret == CMDSN_HIGHER_THAN_EXP) 1915 if (cmdsn_ret == CMDSN_HIGHER_THAN_EXP)
1903 out_of_order_cmdsn = 1; 1916 out_of_order_cmdsn = 1;
1904 else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) 1917 else if (cmdsn_ret == CMDSN_LOWER_THAN_EXP)
@@ -2075,7 +2088,8 @@ static int iscsit_handle_text_cmd(
2075 iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn)); 2088 iscsit_ack_from_expstatsn(conn, be32_to_cpu(hdr->exp_statsn));
2076 2089
2077 if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) { 2090 if (!(hdr->opcode & ISCSI_OP_IMMEDIATE)) {
2078 cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); 2091 cmdsn_ret = iscsit_sequence_cmd(conn, cmd,
2092 (unsigned char *)hdr, hdr->cmdsn);
2079 if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) 2093 if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER)
2080 return -1; 2094 return -1;
2081 2095
@@ -2262,7 +2276,7 @@ iscsit_handle_logout_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd,
2262 if (ret < 0) 2276 if (ret < 0)
2263 return ret; 2277 return ret;
2264 } else { 2278 } else {
2265 cmdsn_ret = iscsit_sequence_cmd(conn, cmd, hdr->cmdsn); 2279 cmdsn_ret = iscsit_sequence_cmd(conn, cmd, buf, hdr->cmdsn);
2266 if (cmdsn_ret == CMDSN_LOWER_THAN_EXP) 2280 if (cmdsn_ret == CMDSN_LOWER_THAN_EXP)
2267 logout_remove = 0; 2281 logout_remove = 0;
2268 else if (cmdsn_ret == CMDSN_ERROR_CANNOT_RECOVER) 2282 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 6374a1a98d6b..96e7fdbba9fc 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 c8da4dd11d26..c5aade523863 100644
--- a/include/target/iscsi/iscsi_transport.h
+++ b/include/target/iscsi/iscsi_transport.h
@@ -82,4 +82,5 @@ extern int iscsit_tmr_post_handler(struct iscsi_cmd *, struct iscsi_conn *);
82 * From iscsi_target_util.c 82 * From iscsi_target_util.c
83 */ 83 */
84extern struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *, gfp_t); 84extern struct iscsi_cmd *iscsit_allocate_cmd(struct iscsi_conn *, gfp_t);
85extern int iscsit_sequence_cmd(struct iscsi_conn *, struct iscsi_cmd *, __be32); 85extern int iscsit_sequence_cmd(struct iscsi_conn *, struct iscsi_cmd *,
86 unsigned char *, __be32);