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 <ronniesahlberg@gmail.com>
This commit is contained in:
@@ -245,6 +245,7 @@ struct iscsi_pdu {
|
|||||||
|
|
||||||
struct iscsi_scsi_cbdata scsi_cbdata;
|
struct iscsi_scsi_cbdata scsi_cbdata;
|
||||||
time_t scsi_timeout;
|
time_t scsi_timeout;
|
||||||
|
uint32_t expxferlen;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct iscsi_pdu *iscsi_allocate_pdu(struct iscsi_context *iscsi,
|
struct iscsi_pdu *iscsi_allocate_pdu(struct iscsi_context *iscsi,
|
||||||
|
|||||||
@@ -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)
|
int iscsi_reconnect(struct iscsi_context *old_iscsi)
|
||||||
{
|
{
|
||||||
struct iscsi_context *iscsi;
|
struct iscsi_context *iscsi;
|
||||||
@@ -342,10 +346,8 @@ try_again:
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (pdu->flags & ISCSI_PDU_DROP_ON_RECONNECT) {
|
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
|
* We don't want to requeue NOPs.
|
||||||
* write command is replayed.
|
|
||||||
* Similarly we don't want to requeue NOPs.
|
|
||||||
*/
|
*/
|
||||||
iscsi_free_pdu(old_iscsi, pdu);
|
iscsi_free_pdu(old_iscsi, pdu);
|
||||||
continue;
|
continue;
|
||||||
@@ -365,6 +367,14 @@ try_again:
|
|||||||
pdu->outdata_written = 0;
|
pdu->outdata_written = 0;
|
||||||
pdu->payload_written = 0;
|
pdu->payload_written = 0;
|
||||||
iscsi_queue_pdu(iscsi, pdu);
|
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) {
|
if (dup2(iscsi->fd, old_iscsi->fd) == -1) {
|
||||||
|
|||||||
@@ -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,
|
iscsi_send_data_out(struct iscsi_context *iscsi, struct iscsi_pdu *cmd_pdu,
|
||||||
uint32_t ttt, uint32_t offset, uint32_t tot_len)
|
uint32_t ttt, uint32_t offset, uint32_t tot_len)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -670,5 +670,6 @@ iscsi_pdu_set_lun(struct iscsi_pdu *pdu, uint32_t lun)
|
|||||||
void
|
void
|
||||||
iscsi_pdu_set_expxferlen(struct iscsi_pdu *pdu, uint32_t expxferlen)
|
iscsi_pdu_set_expxferlen(struct iscsi_pdu *pdu, uint32_t expxferlen)
|
||||||
{
|
{
|
||||||
|
pdu->expxferlen = expxferlen;
|
||||||
scsi_set_uint32(&pdu->outdata.data[20], expxferlen);
|
scsi_set_uint32(&pdu->outdata.data[20], expxferlen);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user