This patch adds proper residual handling and reporting for the WRITE and WRITEVERIFY commands. In addition to setting the residual, for the case of underflow we have to clamp the DATA-IN buffer so that the bs-backends will not write more than what is specified in the SCSI TL. Tests for these conditions are availabel in the libiscsi testsuite. Test for WRITE10 follows : $ ./bin/iscsi-test-cu -t "TestWrite10.testWrite10Residuals" iscsi://127.0.0.1/iqn.ronnie.test/1 -V --dataloss CUnit - A Unit testing framework for C - Version 2.1-0 http://cunit.sourceforge.net/ Suite: TestWrite10 Test: testWrite10Residuals ... Test WRITE10 commands with residuals Block size is 512 Try writing 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 writing one block but with iSCSI expected transfer length==10000 Verify that the target returned SUCCESS Verify residual underflow flag is set Verify we got 9488 bytes of residual underflow Try writing one block but with iSCSI expected transfer length==200 Verify that the target returned SUCCESS Verify residual overflow flag is set Verify we got 312 bytes of residual overflow Try writing two blocks but iSCSI expected transfer length==512 (==one block) Verify that the target returned SUCCESS Verify residual overflow flag is set Verify we got one block of residual overflow Verify that if iSCSI EDTL > SCSI TL then we only write SCSI TL amount of data Write two blocks of 'a' Send WRITE10 LBA:0 blocks:2 wrprotect:0 dpo:0 fua:0 fua_nv:0 group:0 [OK] WRITE10 returned SUCCESS. Write one block of 'b' but set iSCSI EDTL to 2 blocks. Verify that the target returned SUCCESS Verify residual underflow flag is set Verify we got one block of residual underflow Read the two blocks Send READ10 LBA:0 blocks:2 rdprotect:0 dpo:0 fua:0 fua_nv:0 group:0 [OK] READ10 returned SUCCESS. Verify that the first block was changed to 'b' Verify that the second block was NOT overwritten and still contains 'a' Verify that if iSCSI EDTL < SCSI TL then we only write iSCSI EDTL amount of data Write two blocks of 'a' Send WRITE10 LBA:0 blocks:2 wrprotect:0 dpo:0 fua:0 fua_nv:0 group:0 [OK] WRITE10 returned SUCCESS. Write two blocks of 'b' but set iSCSI EDTL to 1 blocks. Verify that the target returned SUCCESS Verify residual overflow flag is set Verify we got one block of residual overflow Read the two blocks Send READ10 LBA:0 blocks:2 rdprotect:0 dpo:0 fua:0 fua_nv:0 group:0 [OK] READ10 returned SUCCESS. Verify that the first block was changed to 'b' Verify that the second block was NOT overwritten and still contains 'a' passed --Run Summary: Type Total Ran Passed Failed suites 1 1 n/a 0 tests 1 1 1 0 asserts 35 35 35 0 Tests completed with return value: 0 Signed-off-by: Ronnie Sahlberg <ronniesahlberg@xxxxxxxxx> --- usr/sbc.c | 19 +++++++++++++++++++ 1 files changed, 19 insertions(+), 0 deletions(-) diff --git a/usr/sbc.c b/usr/sbc.c index 12808fd..1f50191 100644 --- a/usr/sbc.c +++ b/usr/sbc.c @@ -344,6 +344,25 @@ static int sbc_rw(int host_no, struct scsi_cmd *cmd) if (cmd->tl != scsi_get_in_length(cmd)) scsi_set_in_resid_by_actual(cmd, cmd->tl); break; + case WRITE_6: + case WRITE_10: + case WRITE_12: + case WRITE_16: + case WRITE_VERIFY: + case WRITE_VERIFY_12: + case WRITE_VERIFY_16: + if (cmd->tl != scsi_get_out_length(cmd)) { + scsi_set_out_resid_by_actual(cmd, cmd->tl); + + /* We need to clamp the size of the in-buffer + * so that we dont try to write > cmd->tl in the + * backend store. + */ + if (cmd->tl < scsi_get_out_length(cmd)) { + scsi_set_out_length(cmd, cmd->tl); + } + } + break; } ret = cmd->dev->bst->bs_cmd_submit(cmd); -- 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