Commit d473cc7f authored by Mike Christie's avatar Mike Christie Committed by James Bottomley

[SCSI] iscsi: Some fixes in preparation for bidirectional support - exp_datasn

This patch fixes handling of expected datasn/r2tsn as received from
target. It is done according to: T10 rfc3720 section 3.2.2.3. Data Sequencing.

. unify expected datasn/r2tsn into one counter
. calculate than check expected datasn/r2tsn. On error print a message
  and fail the request. (TODO use iscsi retransmits)
. remove the FIXME   ;)
. avoid zero length memset
Signed-off-by: default avatarBoaz Harrosh <bharrosh@panasas.com>
Signed-off-by: default avatarBenny Halevy <bhalevy@panasas.com>
Signed-off-by: default avatarMike Christie <michaelc@cs.wisc.edu>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@SteelEye.com>
parent 8ad5781a
...@@ -229,10 +229,13 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) ...@@ -229,10 +229,13 @@ iscsi_data_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
if (tcp_conn->in.datalen == 0) if (tcp_conn->in.datalen == 0)
return 0; return 0;
if (ctask->datasn != datasn) if (tcp_ctask->exp_datasn != datasn) {
debug_tcp("%s: ctask->exp_datasn(%d) != rhdr->datasn(%d)\n",
__FUNCTION__, tcp_ctask->exp_datasn, datasn);
return ISCSI_ERR_DATASN; return ISCSI_ERR_DATASN;
}
ctask->datasn++; tcp_ctask->exp_datasn++;
tcp_ctask->data_offset = be32_to_cpu(rhdr->offset); tcp_ctask->data_offset = be32_to_cpu(rhdr->offset);
if (tcp_ctask->data_offset + tcp_conn->in.datalen > ctask->total_length) if (tcp_ctask->data_offset + tcp_conn->in.datalen > ctask->total_length)
...@@ -365,15 +368,16 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) ...@@ -365,15 +368,16 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
return ISCSI_ERR_DATALEN; return ISCSI_ERR_DATALEN;
} }
if (tcp_ctask->exp_r2tsn && tcp_ctask->exp_r2tsn != r2tsn) if (tcp_ctask->exp_datasn != r2tsn){
debug_tcp("%s: ctask->exp_datasn(%d) != rhdr->r2tsn(%d)\n",
__FUNCTION__, tcp_ctask->exp_datasn, r2tsn);
return ISCSI_ERR_R2TSN; return ISCSI_ERR_R2TSN;
}
rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)rhdr); rc = iscsi_check_assign_cmdsn(session, (struct iscsi_nopin*)rhdr);
if (rc) if (rc)
return rc; return rc;
/* FIXME: use R2TSN to detect missing R2T */
/* fill-in new R2T associated with the task */ /* fill-in new R2T associated with the task */
spin_lock(&session->lock); spin_lock(&session->lock);
if (!ctask->sc || ctask->mtask || if (!ctask->sc || ctask->mtask ||
...@@ -414,7 +418,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask) ...@@ -414,7 +418,7 @@ iscsi_r2t_rsp(struct iscsi_conn *conn, struct iscsi_cmd_task *ctask)
iscsi_solicit_data_init(conn, ctask, r2t); iscsi_solicit_data_init(conn, ctask, r2t);
tcp_ctask->exp_r2tsn = r2tsn + 1; tcp_ctask->exp_datasn = r2tsn + 1;
__kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*)); __kfifo_put(tcp_ctask->r2tqueue, (void*)&r2t, sizeof(void*));
tcp_ctask->xmstate |= XMSTATE_SOL_HDR; tcp_ctask->xmstate |= XMSTATE_SOL_HDR;
list_move_tail(&ctask->running, &conn->xmitqueue); list_move_tail(&ctask->running, &conn->xmitqueue);
...@@ -1284,10 +1288,10 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask) ...@@ -1284,10 +1288,10 @@ iscsi_tcp_cmd_init(struct iscsi_cmd_task *ctask)
tcp_ctask->sent = 0; tcp_ctask->sent = 0;
tcp_ctask->sg_count = 0; tcp_ctask->sg_count = 0;
tcp_ctask->exp_datasn = 0;
if (sc->sc_data_direction == DMA_TO_DEVICE) { if (sc->sc_data_direction == DMA_TO_DEVICE) {
tcp_ctask->xmstate = XMSTATE_W_HDR; tcp_ctask->xmstate = XMSTATE_W_HDR;
tcp_ctask->exp_r2tsn = 0;
BUG_ON(ctask->total_length == 0); BUG_ON(ctask->total_length == 0);
if (sc->use_sg) { if (sc->use_sg) {
......
...@@ -152,7 +152,7 @@ struct iscsi_tcp_cmd_task { ...@@ -152,7 +152,7 @@ struct iscsi_tcp_cmd_task {
struct scatterlist *sg; /* per-cmd SG list */ struct scatterlist *sg; /* per-cmd SG list */
struct scatterlist *bad_sg; /* assert statement */ struct scatterlist *bad_sg; /* assert statement */
int sg_count; /* SG's to process */ int sg_count; /* SG's to process */
uint32_t exp_r2tsn; uint32_t exp_datasn; /* expected target's R2TSN/DataSN */
int data_offset; int data_offset;
struct iscsi_r2t_info *r2t; /* in progress R2T */ struct iscsi_r2t_info *r2t; /* in progress R2T */
struct iscsi_queue r2tpool; struct iscsi_queue r2tpool;
......
...@@ -120,7 +120,9 @@ static void iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask) ...@@ -120,7 +120,9 @@ static void iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
session->cmdsn++; session->cmdsn++;
hdr->exp_statsn = cpu_to_be32(conn->exp_statsn); hdr->exp_statsn = cpu_to_be32(conn->exp_statsn);
memcpy(hdr->cdb, sc->cmnd, sc->cmd_len); memcpy(hdr->cdb, sc->cmnd, sc->cmd_len);
memset(&hdr->cdb[sc->cmd_len], 0, MAX_COMMAND_SIZE - sc->cmd_len); if (sc->cmd_len < MAX_COMMAND_SIZE)
memset(&hdr->cdb[sc->cmd_len], 0,
MAX_COMMAND_SIZE - sc->cmd_len);
ctask->data_count = 0; ctask->data_count = 0;
if (sc->sc_data_direction == DMA_TO_DEVICE) { if (sc->sc_data_direction == DMA_TO_DEVICE) {
...@@ -165,7 +167,6 @@ static void iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask) ...@@ -165,7 +167,6 @@ static void iscsi_prep_scsi_cmd_pdu(struct iscsi_cmd_task *ctask)
/* No unsolicit Data-Out's */ /* No unsolicit Data-Out's */
ctask->hdr->flags |= ISCSI_FLAG_CMD_FINAL; ctask->hdr->flags |= ISCSI_FLAG_CMD_FINAL;
} else { } else {
ctask->datasn = 0;
hdr->flags |= ISCSI_FLAG_CMD_FINAL; hdr->flags |= ISCSI_FLAG_CMD_FINAL;
zero_data(hdr->dlength); zero_data(hdr->dlength);
......
...@@ -99,7 +99,6 @@ struct iscsi_cmd_task { ...@@ -99,7 +99,6 @@ struct iscsi_cmd_task {
*/ */
struct iscsi_cmd *hdr; struct iscsi_cmd *hdr;
int itt; /* this ITT */ int itt; /* this ITT */
int datasn; /* DataSN */
uint32_t unsol_datasn; uint32_t unsol_datasn;
int imm_count; /* imm-data (bytes) */ int imm_count; /* imm-data (bytes) */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment