Fix sending of unsolicited data in the first burst

When deciding if to generate a data out queue for the first sequence
the test was wrong.
We should not check if INITIAL_R2T is NO and IMMEDIATE_DATA=NO.
Immediate data does not matter here.

What we should check is IF we have more data we need to send and IF
INITIAL_R2T allows us to send more data, then we generate a train of DATA-OUT.

If MaxRecvDataSegmentLength is less than FirstBurstLength we will often have
to send unsolicited data as both ImmediateData and also as unsolicited
DATA-OUT PDUs.

Example:
Assume Target has responded :
MaxRecvDataSegmentLength = 8k
FirstBurstLength = 64k
ImmediateData=YES
InitialR2T=NO

Then this should generate the following sequence :
I->T   ISCSI_COMMAND + 8K of immediate data. F-Bit is not set.
I->T   DATA-OUT 8K
I->T   DATA-OUT 8K
I->T   DATA-OUT 8K
I->T   DATA-OUT 8K
I->T   DATA-OUT 8K
I->T   DATA-OUT 8K
I->T   DATA-OUT 8K. Final PDU in sequence   so F-bit is set.
T->I   R2T
...
This commit is contained in:
Ronnie Sahlberg
2012-12-02 09:55:07 -08:00
parent 564fc9963a
commit a3ce92c93c

View File

@@ -265,14 +265,15 @@ iscsi_scsi_command_async(struct iscsi_context *iscsi, int lun,
return -1; return -1;
} }
/* Can we send some unsolicited data ? */ /* Can we send more data that did not fit as immediate data ? */
if (task->xfer_dir == SCSI_XFER_WRITE if (task->xfer_dir == SCSI_XFER_WRITE
&& iscsi->use_initial_r2t == ISCSI_INITIAL_R2T_NO && iscsi->use_initial_r2t == ISCSI_INITIAL_R2T_NO
&& iscsi->use_immediate_data == ISCSI_IMMEDIATE_DATA_NO) { && pdu->out_len < (uint32_t)task->expxferlen
&& pdu->out_len < iscsi->first_burst_length) {
uint32_t len = task->expxferlen; uint32_t len = task->expxferlen;
if (len > iscsi->first_burst_length) { if (len + pdu->out_len > iscsi->first_burst_length) {
len = iscsi->first_burst_length; len = iscsi->first_burst_length - pdu->out_len;
} }
iscsi_send_data_out(iscsi, pdu, 0xffffffff, iscsi_send_data_out(iscsi, pdu, 0xffffffff,
pdu->out_offset, len); pdu->out_offset, len);