Please find attached a pcap file showing TGTD with this patch applied correctly responding to the different over/under-flow conditions. On Sat, Mar 23, 2013 at 2:16 PM, Ronnie Sahlberg <ronniesahlberg@xxxxxxxxx> wrote: > This patch adds support to return overflow/underflow residuals > for the cases where the transport layer (iSCSI, ...) specifies > an EDTL that is not matching the SCSI transdfer length. > > Additionally, in case of residual underflow it will also clamp the size of > returned DATA-IN to the amount of data that was actually read and not the > EDTL that was requested. > > This is from RFC 3720, 10.4.1 : > bit 6 - (U) set for Residual Underflow. In this case, the Residual > Count indicates the number of bytes that were not transferred out > of the number of bytes that were expected to be transferred. For > a bidirectional operation, the Residual Count contains the > residual for the write operation. > > I have added a specific test for this condition to the testsute in > libiscsi : > > ./bin/iscsi-test-cu -t "TestRead10.testRead10Residuals" \ > iscsi://127.0.0.1/iqn.ronnie.test/1 -V > > Suite: TestRead10 > Test: testRead10Residuals ... > Test invalid READ10 commands > Block size is 512 > Try reading one block but with iSCSI expected transfer length==0 > Verify that the target returned SUCCESS > Verify residual overflow flag is set > Verify we got 512 bytes of residual overflow > Try reading one block but with iSCSI expected transfer length==10000 > Verify that the target returned SUCCESS > Verify we got one whole block back from the target > Verify residual underflow flag is set > Verify we got 9488 bytes of residual underflow > Try reading one block but with iSCSI expected transfer length==200 > Verify that the target returned SUCCESS > Verify we got 200 bytes back from the target > Verify residual overflow flag is set > Verify we got 312 bytes of residual overflow > Try reading two blocks but iSCSI expected transfer length==512 (==one block) > Verify that the target returned SUCCESS > Verify we got one whole block back from the target > Verify residual overflow flag is set > Verify we got one block of residual overflow > passed > > --Run Summary: Type Total Ran Passed Failed > suites 1 1 n/a 0 > tests 1 1 1 0 > asserts 24 24 24 0 > > Signed-off-by: Ronnie Sahlberg <ronniesahlberg@xxxxxxxxx> > --- > usr/sbc.c | 30 ++++++++++++++++++++++++++++-- > 1 files changed, 28 insertions(+), 2 deletions(-) > > diff --git a/usr/sbc.c b/usr/sbc.c > index 48dab04..26cceb1 100644 > --- a/usr/sbc.c > +++ b/usr/sbc.c > @@ -226,6 +226,8 @@ static int sbc_rw(int host_no, struct scsi_cmd *cmd) > int ret; > uint64_t lba; > uint32_t tl; > + long residual = 0; > + long length; > unsigned char key = ILLEGAL_REQUEST; > uint16_t asc = ASC_LUN_NOT_SUPPORTED; > struct scsi_lu *lu = cmd->dev; > @@ -335,12 +337,36 @@ static int sbc_rw(int host_no, struct scsi_cmd *cmd) > cmd->offset = lba << cmd->dev->blk_shift; > cmd->tl = tl << cmd->dev->blk_shift; > > + /* Handle residuals */ > + switch (cmd->scb[0]) { > + case READ_6: > + case READ_10: > + case READ_12: > + case READ_16: > + length = scsi_get_in_length(cmd); > + if (length != cmd->tl) { > + residual = length - cmd->tl; > + > + if (length > cmd->tl) { > + length = cmd->tl; > + scsi_set_in_transfer_len(cmd, cmd->tl); > + scsi_set_in_length(cmd, cmd->tl); > + } > + } > + break; > + } > + > ret = cmd->dev->bst->bs_cmd_submit(cmd); > if (ret) { > key = HARDWARE_ERROR; > asc = ASC_INTERNAL_TGT_FAILURE; > - } else > - return SAM_STAT_GOOD; > + goto sense; > + } > + > + if (residual) > + scsi_set_in_resid(cmd, residual); > + > + return SAM_STAT_GOOD; > > sense: > cmd->offset = 0; > -- > 1.7.3.1 >
Attachment:
read10-residuals-test.pcapng
Description: Binary data