[stgt] [PATCH 12/15] ssc: add variable-length block read support

Mark Harvey markh794 at gmail.com
Wed Nov 26 11:01:43 CET 2008


FUJITA Tomonori wrote:
> On Wed, 26 Nov 2008 17:46:38 +1100
> "Mark Harvey" <markh794 at gmail.com> wrote:
> 
>>>> An attempt to read 128k from a 256k block results with an error message:
>>>> # dd if=/dev/st1 bs=128k count=1 of=/tmp/block0
>>>> dd: reading `/dev/st1': Cannot allocate memory
>>>> 0+0 records in
>>>> 0+0 records out
>>>> 0 bytes (0 B) copied, 0.01287 seconds, 0.0 kB/s
>>>>
>>>> And /var/log/messages:
>>>> kernel: st1: Failed to read 262144 byte block with 131072 byte transfer.
>>> I think that this is a kernel message that st driver gives when the
>>> INFORMATION field has a negative value. In this case, the INFORMATION
>>> field had -128K.
>>>
>>> I've attached a new patch. The difference from the previous one is
>>> just one line, it sets a negative value to the INFORMATION field when
>>> the requested transfer length is smaller than the actual logical block
>>> length.
>>>
>>>
>>>> Disclaimer...
>>>> I'm 99.99% positive, last time I tried this I received a different
>>>> message and did in fact read 128k of data. This may be an
>>>> implementation of dd used..
>>> With the same tape drive?
>> Yeah, same tape drive.
>>
>> I need to get hold of the 'other' linux box (Ubuntu x86_64bit I think)
>> - where the above was from an SLES-10
> 
> I see. Please let me know if you see a different message.

OK, re-tested using Ubuntu - Same message as above - 'Can not allocate memory'..

Must be my faulty memory at play ;)

> 
> 
>>>> # rpm -qf `which dd`
>>>> coreutils-5.93-22.14
>>>> # uname -a
>>>> Linux dpg-markh 2.6.16.46-0.12-smp #1 SMP Thu May 17 14:00:09 UTC 2007
>>>> i686 i686 i386 GNU/Linux
>>>>
>>>>>
>>>>>>>> Now test if we can read in a more then a block (this fails returning
>>>>>>>> no data - we should have read in the 256k)
>>>>>>>> # dd if=/dev/st0 of=/tmp/block0 bs=512k count=1
>>>>>>>> dd: reading `/dev/st0': Input/output error
>>>>>>>> 0+0 records in
>>>>>>>> 0+0 records out
>>>>>>>> 0 bytes (0 B) copied, 0.00705821 s, 0.0 kB/s
>>>>>>> stgt should return the whole first block without sense, right?
>>>>>>>
>>>>>> The amount of data successfully read should be returned. In this example, 128k.
>>>>>>
>>>>>> The sense returned should be :NO SENSE | VALID | ILI (Illegal Length
>>>>>> Indicator) and the amount of data NOT successfully returned -> filled
>>>>>> in sense_buffer[3] -> sense_buffer[7]
>>>>> With the patch, stgt returns CHECK CONDITION with a sense (NO SENSE |
>>>>> VALID | ILI ) and the information field sets to 256K.
>>>>>
>>>>> nemo:/home/fujita# dd if=/dev/st0 of=/tmp/block0 bs=512k count=1
>>>>> 0+1 records in
>>>>> 0+1 records out
>>>>> 262144 bytes (262 kB) copied, 0.019265 seconds, 13.6 MB/s
>>>>>
>>>>> This is the right response?
>>>> This is the correct response...
>>>>
>>>>
>>>> Many thanks for having a look at this.
>>> No problem at all. Thanks!
>>>
>>>
>>> diff --git a/usr/bs_ssc.c b/usr/bs_ssc.c
>>> index 0b9fedb..9ed9e65 100644
>>> --- a/usr/bs_ssc.c
>>> +++ b/usr/bs_ssc.c
>>> @@ -317,15 +317,27 @@ static int resp_var_read(struct scsi_cmd *cmd, uint8_t *buf, uint32_t length,
>>>        *transferred = 0;
>>>
>>>        if (length != h->blk_sz) {
>>> +               uint8_t info[4];
>>> +               int val = length - h->blk_sz;
>>> +
>>> +               put_unaligned_be32(val, info);
>>> +
>>>                if (h->blk_type == BLK_EOD)
>>>                        sense_data_build(cmd, 0x40 | BLANK_CHECK,
>>>                                         NO_ADDITIONAL_SENSE);
>>>                else
>>> -                       sense_data_build(cmd, NO_SENSE, NO_ADDITIONAL_SENSE);
>>> +                       ssc_sense_data_build(cmd, NO_SENSE | 0x20,
>>> +                                            NO_ADDITIONAL_SENSE,
>>> +                                            info, sizeof(info));
>>> +
>>> +               if (length > h->blk_sz)
>>> +                       scsi_set_in_resid_by_actual(cmd, length - h->blk_sz);
>>> +               else
>>> +                       scsi_set_in_resid_by_actual(cmd, 0);
>>>
>>>                length = min(length, h->blk_sz);
>>> +
>>>                result = SAM_STAT_CHECK_CONDITION;
>>> -               scsi_set_in_resid_by_actual(cmd, length);
>>>
>>>                if (!length)
>>>                        goto out;
>>>
>> Success with above patch :)
>>
>> Write 2 x 128k blocks to tape...
>> # dd if=/dev/zero of=/dev/st8 bs=128k count=2
>> 2+0 records in
>> 2+0 records out
>> 262144 bytes (262 kB) copied, 0.138255 seconds, 1.9 MB/s
>>
>> Attempt to read a single 256k block. (correctly returns complete 128k block)..
>> # dd if=/dev/st8 bs=256k count=1 of=/tmp/b1
>> 0+1 records in
>> 0+1 records out
>> 131072 bytes (131 kB) copied, 0.017385 seconds, 7.5 MB/s
> 
> With this patch, I think that if the requested transfer length is
> smaller than the actual logical block length, you get the same 'Cannot
> allocate memory' message. As we have done so far, the following
> commands give the same message with this patch:
> 
> # dd if=/dev/zero of=/dev/st0 bs=256k count=1
> # dd if=/dev/st0 of=/tmp/block0 bs=128k count=1
> 
> 
> Anyway, seems that this patch does the correct thing, right?
> 
Yes, this patch is doing the right thing.


Cheers
Mark
--
To unsubscribe from this list: send the line "unsubscribe stgt" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html



More information about the stgt mailing list