iscsi-command.c: Use common function to write unsolicited data-out pdus.

We write unsolicited data-out PDUs from two places;
when we originally write the command in iscsi_scsi_command_async()
but also when we re-queue the PDUs during a session reconnect.

The re-queuing during the session re-connect was recently (almost) fixed
but was still buggy in that it did not correctly clamp the amount of written
data as per first burst length restriction.
This attempts to fix that.

Signed-off-by: Ronnie Sahlberg <ronniesahlberg@gmail.com>
This commit is contained in:
Ronnie Sahlberg
2015-02-20 20:51:14 -08:00
parent 831ecb3656
commit 2f5d21b09c
3 changed files with 24 additions and 19 deletions

View File

@@ -271,7 +271,8 @@ void iscsi_pdu_set_datasn(struct iscsi_pdu *pdu, uint32_t datasn);
void iscsi_pdu_set_bufferoffset(struct iscsi_pdu *pdu, uint32_t bufferoffset);
int iscsi_pdu_add_data(struct iscsi_context *iscsi, struct iscsi_pdu *pdu,
unsigned char *dptr, int dsize);
EXTERN int iscsi_queue_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu);
int iscsi_queue_pdu(struct iscsi_context *iscsi, struct iscsi_pdu *pdu);
int iscsi_send_unsolicited_data_out(struct iscsi_context *iscsi, struct iscsi_pdu *pdu);
int iscsi_add_data(struct iscsi_context *iscsi, struct iscsi_data *data,
unsigned char *dptr, int dsize, int pdualignment);

View File

@@ -242,10 +242,6 @@ 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;
@@ -347,7 +343,11 @@ try_again:
if (pdu->flags & ISCSI_PDU_DROP_ON_RECONNECT) {
/*
* We don't want to requeue NOPs.
* We don't want to requeue NOPs or DATA-OUT PDUs.
* In case of DATA-OUT PDUs that are part of the
* initial unsolicited data we have to regenerate
* them forther down so that we end the re-queued
* WRITE + DATA-OUT train with a PDU with the F bit.
*/
iscsi_free_pdu(old_iscsi, pdu);
continue;
@@ -367,13 +367,12 @@ 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.
/* Requeue any unsolicited data-out for the command PDU we
* just re-queued. These are commands that write data to the
* device but does not have the F bit set.
*/
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);
iscsi_send_unsolicited_data_out(iscsi, pdu);
}
}

View File

@@ -67,7 +67,7 @@ iscsi_scsi_response_cb(struct iscsi_context *iscsi, int status,
}
}
int
static int
iscsi_send_data_out(struct iscsi_context *iscsi, struct iscsi_pdu *cmd_pdu,
uint32_t ttt, uint32_t offset, uint32_t tot_len)
{
@@ -190,6 +190,17 @@ iscsi_timeout_scan(struct iscsi_context *iscsi)
}
}
int
iscsi_send_unsolicited_data_out(struct iscsi_context *iscsi, struct iscsi_pdu *pdu)
{
uint32_t len = pdu->expxferlen - pdu->payload_len;
if (len > iscsi->first_burst_length) {
len = iscsi->first_burst_length;
}
return iscsi_send_data_out(iscsi, pdu, 0xffffffff,
pdu->payload_len, len);
}
/* Using 'struct iscsi_data *d' for data-out is optional
* and will be converted into a one element data-out iovector.
@@ -326,13 +337,7 @@ iscsi_scsi_command_async(struct iscsi_context *iscsi, int lun,
* subtract from first_burst_length.
*/
if (!(flags & ISCSI_PDU_SCSI_FINAL)) {
uint32_t len = pdu->expxferlen - pdu->payload_len;
if (len > iscsi->first_burst_length) {
len = iscsi->first_burst_length;
}
iscsi_send_data_out(iscsi, pdu, 0xffffffff,
pdu->payload_len, len);
iscsi_send_unsolicited_data_out(iscsi, pdu);
}
/* remember cmdsn and itt so we can use task management */