[stgt] [PATCH] Add support for SBC GET_LBA_STATUS opcode

ronnie sahlberg ronniesahlberg at gmail.com
Sun Jun 3 02:09:21 CEST 2012


Tomo,

Please find attached an updated patch,

> Can you use put/get_unaligend_* helper functions? I don't replace the
> existing such code with the helper functions but I want to use the
> functions for new code.
>

Do you want me to prepare a patch that does this conversion for all
other places too ?


regards
ronnie sahlberg


On Sun, Jun 3, 2012 at 9:38 AM, FUJITA Tomonori
<fujita.tomonori at lab.ntt.co.jp> wrote:
> On Thu, 31 May 2012 17:00:45 +1000
> ronnie sahlberg <ronniesahlberg at gmail.com> wrote:
>
>> Tomo, please use this patch instead.
>>
>> It adds proper check for starting-lba so we return the right sense
>> code if it is out of range.
>>
>> It also adds proper service action handling so that we will report
>> that we support both varients (reacapacity16 and getlbastatus)
>> of opcoe 0x9e
>>
>>
>> That way sg_opcodes show them both properly, like this :
>> sg_opcodes iscsi://10.1.1.125/iqn.ronnie.test/1
>>   IET       VIRTUAL-DISK  0001
>>   Peripheral device type: disk
>>
>> Opcode  Service    CDB    Name
>> (hex)   action(h)  size
>> -----------------------------------------------
>>  00                  6    Test Unit Ready
>>  03                  6    Request Sense
>>  04                  6    Format Unit
>>  08                  6    Read(6)
>>  0a                  6    Write(6)
>>  12                  6    Inquiry
>>  15                  6    Mode select(6)
>>  16                  6    Reserve(6)
>>  17                  6    Release(6)
>>  1a                  6    Mode sense(6)
>>  1b                  6    Start stop unit
>>  1d                  6    Send diagnostic
>>  1e                  6    Prevent allow medium removal
>>  25                 10    Read capacity(10)
>>  28                 10    Read(10)
>>  2a                 10    Write(10)
>>  2f                 10    Verify(10)
>>  34                 10    Pre-fetch(10)
>>  35                 10    Synchronize cache(10)
>>  41                 10    Write same(10)
>>  42                 10    Unmap
>>  55                 10    Mode select(10)
>>  5a                 10    Mode sense(10)
>>  5e        0        10    Persistent reserve in, read keys
>>  5e        1        10    Persistent reserve in, read reservation
>>  5e        2        10    Persistent reserve in, report capabilities
>>  5f        0        10    Persistent reserve out, register
>>  5f        1        10    Persistent reserve out, reserve
>>  5f        2        10    Persistent reserve out, release
>>  5f        3        10    Persistent reserve out, clear
>>  5f        4        10    Persistent reserve out, preempt
>>  5f        6        10    Persistent reserve out, register and ignore
>> existing key
>>  5f        7        10    Persistent reserve out, register and move
>>  88                 16    Read(16)
>>  8a                 16    Write(16)
>>  8f                 16    Verify(16)
>>  90                 16    Pre-fetch(16)
>>  91                 16    Synchronize cache(16)
>>  93                 16    Write same(16)
>>  9e       10        16    Read capacity(16)
>>  9e       12        16    Get LBA status
>>  a0                 12    Report luns
>>  a3        c        12    Report supported operation codes
>>  a8                 12    Read(12)
>>  aa                 12    Write(12)
>>  af                 12    Verify(12)
>>
>> tgtd does support a pretty fair number of opcodes !
>
> Looks great. Thanks a lot.
>
> I have some minor comments.
>
>> Add GET_LBA_STATUS for thin provisioned luns if SEEK_DATA/SEEK_HOLE
>> is available.
>>
>> Update get lba status to return proper sense code if starting-lba
>> is out of range.
>>
>> Break readcapacity16 and getlbastatus that are both using opcode 0x9e into
>> using the service-handle mechanism.
>> This means that the sg_opcoes now also reports both these opcodes correctly.
>> They are both opcoe 0x9e but different service actions.
>>
>> Signed-off-by: Ronnie Sahlberg <ronniesahlberg at gmail.com>
>> ---
>>  usr/sbc.c  |  129 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
>>  usr/scsi.h |    1 +
>>  usr/spc.c  |    2 +-
>>  usr/tgtd.h |    4 ++
>>  4 files changed, 130 insertions(+), 6 deletions(-)
>>
>> diff --git a/usr/sbc.c b/usr/sbc.c
>> index cf2b609..a480a16 100644
>> --- a/usr/sbc.c
>> +++ b/usr/sbc.c
>> @@ -23,6 +23,9 @@
>>   * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
>>   * 02110-1301 USA
>>   */
>> +#define _FILE_OFFSET_BITS 64
>> +#define __USE_GNU
>> +
>>  #include <errno.h>
>>  #include <stdio.h>
>>  #include <stdlib.h>
>> @@ -30,6 +33,7 @@
>>  #include <stdint.h>
>>  #include <unistd.h>
>>  #include <linux/fs.h>
>> +#include <sys/types.h>
>>
>>  #include "list.h"
>>  #include "util.h"
>> @@ -45,6 +49,23 @@
>>
>>  static unsigned int blk_shift = DEFAULT_BLK_SHIFT;
>>
>> +static off_t find_next_data(struct scsi_lu *dev, off_t offset)
>> +{
>> +#ifdef SEEK_DATA
>> +     return lseek64(dev->fd, offset, SEEK_DATA);
>> +#else
>> +     return offset;
>> +#endif
>> +}
>> +static off_t find_next_hole(struct scsi_lu *dev, off_t offset)
>> +{
>> +#ifdef SEEK_HOLE
>> +     return lseek64(dev->fd, offset, SEEK_HOLE);
>> +#else
>> +     return dev->size;
>> +#endif
>> +}
>> +
>>  static int sbc_mode_page_update(struct scsi_cmd *cmd, uint8_t *data, int *changed)
>>  {
>>       uint8_t pcode = data[0] & 0x3f;
>> @@ -421,7 +442,7 @@ sense:
>>       return SAM_STAT_CHECK_CONDITION;
>>  }
>>
>> -static int sbc_service_action(int host_no, struct scsi_cmd *cmd)
>> +static int sbc_readcapacity16(int host_no, struct scsi_cmd *cmd)
>>  {
>>       uint32_t *data;
>>       unsigned int bshift;
>> @@ -437,9 +458,6 @@ static int sbc_service_action(int host_no, struct scsi_cmd *cmd)
>>               goto sense;
>>       }
>>
>> -     if (cmd->scb[1] != SAI_READ_CAPACITY_16)
>> -             goto sense;
>> -
>>       if (scsi_get_in_length(cmd) < 12)
>>               goto overflow;
>>
>> @@ -468,6 +486,107 @@ sense:
>>       return SAM_STAT_CHECK_CONDITION;
>>  }
>>
>> +static int sbc_getlbastatus(int host_no, struct scsi_cmd *cmd)
>> +{
>> +     int len = 32;
>> +     uint64_t offset;
>> +     uint32_t pdl;
>> +     int type;
>> +     char *buf;
>> +     unsigned char key = ILLEGAL_REQUEST;
>> +     uint16_t asc = ASC_INVALID_OP_CODE;
>> +
>> +     if (cmd->dev->attrs.removable && !cmd->dev->attrs.online) {
>> +             key = NOT_READY;
>> +             asc = ASC_MEDIUM_NOT_PRESENT;
>> +             goto sense;
>> +     }
>> +
>> +     if (scsi_get_in_length(cmd) < 24)
>> +             goto overflow;
>> +
>> +     len = scsi_get_in_length(cmd);
>> +     buf = scsi_get_in_buffer(cmd);
>> +     memset(buf, 0, len);
>> +
>> +     offset = __be64_to_cpu(*(uint64_t *)&cmd->scb[2])
>> +                     << cmd->dev->blk_shift;
>
> Can you use put/get_unaligend_* helper functions? I don't replace the
> existing such code with the helper functions but I want to use the
> functions for new code.
>
>
>> +     if (offset >= cmd->dev->size) {
>> +             key = ILLEGAL_REQUEST;
>> +             asc = ASC_LBA_OUT_OF_RANGE;
>> +             goto sense;
>> +     }
>> +
>> +     pdl = 4;
>> +     *(uint32_t *)&buf[0] = __cpu_to_be32(pdl);
>
> Ditto.
>
>> +     type = 0;
>> +     while (len >= 4 + pdl + 16) {
>> +             off_t next_offset;
>> +
>> +             *(uint32_t *)&buf[0] = __cpu_to_be32(pdl + 16);
>
> Ditto.
>
>> +             if (offset >= cmd->dev->size)
>> +                     break;
>> +
>> +             next_offset = (type == 0) ?
>> +                     find_next_hole(cmd->dev, offset) :
>> +                     find_next_data(cmd->dev, offset);
>> +             if (next_offset == offset) {
>> +                     type = 1 - type;
>> +                     continue;
>> +             }
>> +
>> +             *(uint64_t *)&buf[4 + pdl +  0] =
>> +                     __cpu_to_be64(offset >> cmd->dev->blk_shift);
>> +             *(uint64_t *)&buf[4 + pdl +  8] =
>> +                     __cpu_to_be32((next_offset - offset)
>> +                             >> cmd->dev->blk_shift);
>
> Ditto.
>
>> +             buf[4 + pdl + 12] = type;
>
> Ditto.
>
>> +             pdl += 16;
>> +             type = 1 - type;
>> +             offset = next_offset;
>> +     }
>> +     len = 4 + pdl;
>> +
>> +overflow:
>> +     scsi_set_in_resid_by_actual(cmd, len);
>> +     return SAM_STAT_GOOD;
>> +
>> +sense:
>> +     sense_data_build(cmd, key, asc);
>> +     return SAM_STAT_CHECK_CONDITION;
>> +}
>> +
>> +struct service_action sbc_service_actions[] = {
>> +     {0x10, sbc_readcapacity16},
>> +     {0x12, sbc_getlbastatus},
>
> better to use SAI_*?
>
>> +     {0, NULL}
>> +};
>> +
>> +
>> +static int sbc_service_action(int host_no, struct scsi_cmd *cmd)
>> +{
>> +     uint8_t action;
>> +     unsigned char op = cmd->scb[0];
>> +     struct service_action *service_action, *actions;
>> +
>> +     action = cmd->scb[1] & 0x1f;
>> +     actions = cmd->dev->dev_type_template.ops[op].service_actions;
>> +
>> +     service_action = find_service_action(actions, action);
>> +
>> +     if (!service_action) {
>> +             scsi_set_in_resid_by_actual(cmd, 0);
>> +             sense_data_build(cmd, ILLEGAL_REQUEST,
>> +                             ASC_INVALID_FIELD_IN_CDB);
>> +             return SAM_STAT_CHECK_CONDITION;
>> +     }
>> +
>> +     return service_action->cmd_perform(host_no, cmd);
>> +}
>> +
>>  static int sbc_sync_cache(int host_no, struct scsi_cmd *cmd)
>>  {
>>       int ret;
>> @@ -711,7 +830,7 @@ static struct device_type_template sbc_template = {
>>               {spc_illegal_op,},
>>               {spc_illegal_op,},
>>               {spc_illegal_op,},
>> -             {sbc_service_action,},
>> +             {sbc_service_action, sbc_service_actions,},
>>               {spc_illegal_op,},
>>
>>               /* 0xA0 */
>> diff --git a/usr/scsi.h b/usr/scsi.h
>> index 0a02c36..2b994f9 100644
>> --- a/usr/scsi.h
>> +++ b/usr/scsi.h
>> @@ -80,6 +80,7 @@
>>  #define WRITE_SAME_16         0x93
>>  #define SERVICE_ACTION_IN     0x9e
>>  #define      SAI_READ_CAPACITY_16  0x10
>> +#define      SAI_GET_LBA_STATUS    0x12
>>  #define REPORT_LUNS           0xa0
>>  #define MOVE_MEDIUM           0xa5
>>  #define EXCHANGE_MEDIUM       0xa6
>> diff --git a/usr/spc.c b/usr/spc.c
>> index a7f9a36..117c9f3 100644
>> --- a/usr/spc.c
>> +++ b/usr/spc.c
>> @@ -794,7 +794,7 @@ struct service_action maint_in_service_actions[] = {
>>       {0, NULL}
>>  };
>>
>> -static struct service_action *
>> +struct service_action *
>>  find_service_action(struct service_action *service_action, uint32_t action)
>>  {
>>       while (service_action->cmd_perform) {
>> diff --git a/usr/tgtd.h b/usr/tgtd.h
>> index b303e21..aa9b9d5 100644
>> --- a/usr/tgtd.h
>> +++ b/usr/tgtd.h
>> @@ -353,4 +353,8 @@ int call_program(const char *cmd,
>>
>>  void update_lbppbe(struct scsi_lu *lu, int blksize);
>>
>> +struct service_action *
>> +find_service_action(struct service_action *service_action,
>> +                 uint32_t action);
>> +
>>  #endif
>> --
>> 1.7.3.1
>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-SBC-Add-GET_LBA_STATUS-command.patch.gz
Type: application/x-gzip
Size: 2348 bytes
Desc: not available
URL: <http://lists.wpkg.org/pipermail/stgt/attachments/20120603/f047710c/attachment-0002.bin>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: 0001-SBC-Add-GET_LBA_STATUS-command.patch
Type: application/octet-stream
Size: 6093 bytes
Desc: not available
URL: <http://lists.wpkg.org/pipermail/stgt/attachments/20120603/f047710c/attachment-0002.obj>


More information about the stgt mailing list