diff options
author | Nicholas Bellinger <nab@linux-iscsi.org> | 2013-11-18 13:55:10 -0500 |
---|---|---|
committer | Nicholas Bellinger <nab@linux-iscsi.org> | 2013-11-20 00:39:21 -0500 |
commit | ea7e32bec1b9d9e5b159d80ceb563c702e28b02a (patch) | |
tree | 80c83169f85677f050280703f480bd5988d98840 /drivers/target | |
parent | 04f3b31bff720f01d684100c868c88f67ced8dc8 (diff) |
iscsi-target: Do not reject non-immediate CmdSNs exceeding MaxCmdSN
This patch changes iscsit_sequence_cmd() logic to no longer reject
non-immediate CmdSNs that exceed MaxCmdSN with a protocol error,
but instead silently ignore them.
This is done to correctly follow RFC-3720 Section 3.2.2.1:
For non-immediate commands, the CmdSN field can take any
value from ExpCmdSN to MaxCmdSN inclusive. The target MUST silently
ignore any non-immediate command outside of this range or non-
immediate duplicates within the range.
Reported-by: Santosh Kulkarni <santosh.kulkarni@calsoftinc.com>
Signed-off-by: Nicholas Bellinger <nab@linux-iscsi.org>
Diffstat (limited to 'drivers/target')
-rw-r--r-- | drivers/target/iscsi/iscsi_target_core.h | 1 | ||||
-rw-r--r-- | drivers/target/iscsi/iscsi_target_util.c | 18 |
2 files changed, 11 insertions, 8 deletions
diff --git a/drivers/target/iscsi/iscsi_target_core.h b/drivers/target/iscsi/iscsi_target_core.h index f2094d2f8eef..8dcb3c1aa801 100644 --- a/drivers/target/iscsi/iscsi_target_core.h +++ b/drivers/target/iscsi/iscsi_target_core.h | |||
@@ -193,6 +193,7 @@ enum recover_cmdsn_ret_table { | |||
193 | CMDSN_NORMAL_OPERATION = 0, | 193 | CMDSN_NORMAL_OPERATION = 0, |
194 | CMDSN_LOWER_THAN_EXP = 1, | 194 | CMDSN_LOWER_THAN_EXP = 1, |
195 | CMDSN_HIGHER_THAN_EXP = 2, | 195 | CMDSN_HIGHER_THAN_EXP = 2, |
196 | CMDSN_MAXCMDSN_OVERRUN = 3, | ||
196 | }; | 197 | }; |
197 | 198 | ||
198 | /* Used for iscsi_handle_immediate_data() return values */ | 199 | /* Used for iscsi_handle_immediate_data() return values */ |
diff --git a/drivers/target/iscsi/iscsi_target_util.c b/drivers/target/iscsi/iscsi_target_util.c index 45b8fd13fa72..9064926a0370 100644 --- a/drivers/target/iscsi/iscsi_target_util.c +++ b/drivers/target/iscsi/iscsi_target_util.c | |||
@@ -242,9 +242,9 @@ static inline int iscsit_check_received_cmdsn(struct iscsi_session *sess, u32 cm | |||
242 | */ | 242 | */ |
243 | if (iscsi_sna_gt(cmdsn, sess->max_cmd_sn)) { | 243 | if (iscsi_sna_gt(cmdsn, sess->max_cmd_sn)) { |
244 | pr_err("Received CmdSN: 0x%08x is greater than" | 244 | pr_err("Received CmdSN: 0x%08x is greater than" |
245 | " MaxCmdSN: 0x%08x, protocol error.\n", cmdsn, | 245 | " MaxCmdSN: 0x%08x, ignoring.\n", cmdsn, |
246 | sess->max_cmd_sn); | 246 | sess->max_cmd_sn); |
247 | ret = CMDSN_ERROR_CANNOT_RECOVER; | 247 | ret = CMDSN_MAXCMDSN_OVERRUN; |
248 | 248 | ||
249 | } else if (cmdsn == sess->exp_cmd_sn) { | 249 | } else if (cmdsn == sess->exp_cmd_sn) { |
250 | sess->exp_cmd_sn++; | 250 | sess->exp_cmd_sn++; |
@@ -303,14 +303,16 @@ int iscsit_sequence_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, | |||
303 | ret = CMDSN_HIGHER_THAN_EXP; | 303 | ret = CMDSN_HIGHER_THAN_EXP; |
304 | break; | 304 | break; |
305 | case CMDSN_LOWER_THAN_EXP: | 305 | case CMDSN_LOWER_THAN_EXP: |
306 | case CMDSN_MAXCMDSN_OVERRUN: | ||
307 | default: | ||
306 | cmd->i_state = ISTATE_REMOVE; | 308 | cmd->i_state = ISTATE_REMOVE; |
307 | iscsit_add_cmd_to_immediate_queue(cmd, conn, cmd->i_state); | 309 | iscsit_add_cmd_to_immediate_queue(cmd, conn, cmd->i_state); |
308 | ret = cmdsn_ret; | 310 | /* |
309 | break; | 311 | * Existing callers for iscsit_sequence_cmd() will silently |
310 | default: | 312 | * ignore commands with CMDSN_LOWER_THAN_EXP, so force this |
311 | reason = ISCSI_REASON_PROTOCOL_ERROR; | 313 | * return for CMDSN_MAXCMDSN_OVERRUN as well.. |
312 | reject = true; | 314 | */ |
313 | ret = cmdsn_ret; | 315 | ret = CMDSN_LOWER_THAN_EXP; |
314 | break; | 316 | break; |
315 | } | 317 | } |
316 | mutex_unlock(&conn->sess->cmdsn_mutex); | 318 | mutex_unlock(&conn->sess->cmdsn_mutex); |