Re: [PATCH] SBC READ6/10/12/16: Add handling of residual overflow/underflow.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Linux SCSI]     [Linux RAID]     [Linux Clusters]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]

  Powered by Linux