From b001d980ef8a93e916b0f877d8a94c20963e2f2c Mon Sep 17 00:00:00 2001 From: Ronnie Sahlberg Date: Tue, 17 Feb 2015 06:46:58 -0800 Subject: [PATCH] reconnect: we must re-queue any missing data-outs during reconnect If we have writes that do not have the Final bit set during reconnect we must send out any missing data-out PDU. Signed-off-by: Ronnie Sahlberg --- include/iscsi-private.h | 1 + lib/connect.c | 18 ++++++++++++++---- lib/iscsi-command.c | 2 +- lib/pdu.c | 1 + 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/include/iscsi-private.h b/include/iscsi-private.h index e69fdce..7d1ec75 100644 --- a/include/iscsi-private.h +++ b/include/iscsi-private.h @@ -245,6 +245,7 @@ struct iscsi_pdu { struct iscsi_scsi_cbdata scsi_cbdata; time_t scsi_timeout; + uint32_t expxferlen; }; struct iscsi_pdu *iscsi_allocate_pdu(struct iscsi_context *iscsi, diff --git a/lib/connect.c b/lib/connect.c index 485ab63..4f4e2d0 100644 --- a/lib/connect.c +++ b/lib/connect.c @@ -242,6 +242,10 @@ void iscsi_defer_reconnect(struct iscsi_context *iscsi) } } +int +iscsi_send_data_out(struct iscsi_context *iscsi, struct iscsi_pdu *cmd_pdu, + uint32_t ttt, uint32_t offset, uint32_t tot_len); + int iscsi_reconnect(struct iscsi_context *old_iscsi) { struct iscsi_context *iscsi; @@ -342,10 +346,8 @@ try_again: } if (pdu->flags & ISCSI_PDU_DROP_ON_RECONNECT) { - /* We don't want to requeue things like DATA-OUT since these guys - * will be reissued automatically anyway once the corresponding - * write command is replayed. - * Similarly we don't want to requeue NOPs. + /* + * We don't want to requeue NOPs. */ iscsi_free_pdu(old_iscsi, pdu); continue; @@ -365,6 +367,14 @@ try_again: pdu->outdata_written = 0; pdu->payload_written = 0; iscsi_queue_pdu(iscsi, pdu); + /* All PDUs that write data and do not have final set + * needs some additional data-out to be requeued. + */ + if ((pdu->outdata.data[1] & (ISCSI_PDU_SCSI_WRITE | ISCSI_PDU_SCSI_FINAL)) == ISCSI_PDU_SCSI_WRITE) { + iscsi_send_data_out(iscsi, pdu, 0xffffffff, + pdu->payload_len, + pdu->expxferlen - pdu->payload_len); + } } if (dup2(iscsi->fd, old_iscsi->fd) == -1) { diff --git a/lib/iscsi-command.c b/lib/iscsi-command.c index 8ceedf4..f49f150 100644 --- a/lib/iscsi-command.c +++ b/lib/iscsi-command.c @@ -67,7 +67,7 @@ iscsi_scsi_response_cb(struct iscsi_context *iscsi, int status, } } -static int +int iscsi_send_data_out(struct iscsi_context *iscsi, struct iscsi_pdu *cmd_pdu, uint32_t ttt, uint32_t offset, uint32_t tot_len) { diff --git a/lib/pdu.c b/lib/pdu.c index d7a4a4f..21b3549 100644 --- a/lib/pdu.c +++ b/lib/pdu.c @@ -670,5 +670,6 @@ iscsi_pdu_set_lun(struct iscsi_pdu *pdu, uint32_t lun) void iscsi_pdu_set_expxferlen(struct iscsi_pdu *pdu, uint32_t expxferlen) { + pdu->expxferlen = expxferlen; scsi_set_uint32(&pdu->outdata.data[20], expxferlen); }