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 -- To unsubscribe from this list: send the line "unsubscribe stgt" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html