[stgt] [PATCH] Initial SANITIZE support

ronnie sahlberg ronniesahlberg at gmail.com
Tue Jul 23 15:28:03 CEST 2013


On Tue, Jul 23, 2013 at 12:27 AM, Dan Mick <dan.mick at inktank.com> wrote:
> Seems like this ought to apply to bs_rbd.c as well, unless the sanitize code
> can be moved out of the backend into the common code...do you need a hand
> with that?

Yes, please do.
Lets get the initial patch in first, then great if you can merge it
into RDB too.


>
>
> On 07/21/2013 11:34 AM, Ronnie Sahlberg wrote:
>>
>> Add support for the SANITIZE opcode and implement
>> BLOCK_ERASE (similar to UNMAP) OVERWRITE and EXIT_FAILURE_MODE
>> service actions.
>>
>> All commands except INQUIRY, REPORT_LUNS and REQUEST SENSE are failed
>> with NOT_READY/SANITIZE_IN_PGROGRESS while a sanitize is
>> active or a SANITIZE has failed but not yet been cleared.
>>
>> Signed-off-by: Ronnie Sahlberg <ronniesahlberg at gmail.com>
>> ---
>>   usr/bs_rdwr.c |  181
>> ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>   usr/sbc.c     |  188
>> +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
>>   usr/scsi.c    |    5 ++
>>   usr/scsi.h    |    8 +++
>>   usr/spc.c     |   48 +++++++++++++++
>>   usr/spc.h     |    5 +-
>>   usr/target.c  |    6 ++
>>   usr/tgtd.h    |    9 +++
>>   8 files changed, 444 insertions(+), 6 deletions(-)
>>
>> diff --git a/usr/bs_rdwr.c b/usr/bs_rdwr.c
>> index 47d2d99..148fc72 100644
>> --- a/usr/bs_rdwr.c
>> +++ b/usr/bs_rdwr.c
>> @@ -58,6 +58,170 @@ static void bs_sync_sync_range(struct scsi_cmd *cmd,
>> uint32_t length,
>>                 set_medium_error(result, key, asc);
>>   }
>>
>> +static void sanitize_write_buffer(struct scsi_cmd *cmd,
>> +               int buf_size, const char *buf,
>> +               int *result, uint8_t *key, uint16_t *asc)
>> +{
>> +       uint64_t offset = 0;
>> +
>> +       while (offset != cmd->dev->size) {
>> +               size_t count, pos;
>> +
>> +               if (cmd->dev->size - offset > buf_size)
>> +                       count = buf_size;
>> +               else
>> +                       count = cmd->dev->size - offset;
>> +
>> +               pos = 0;
>> +               while (pos != count) {
>> +                       size_t written;
>> +
>> +                       written = pwrite64(cmd->dev->fd,
>> +                                       buf + pos, count - pos, offset +
>> pos);
>> +                       if (written == -1) {
>> +                               eprintf("Write failed during sanitize\n");
>> +                               *result = SAM_STAT_CHECK_CONDITION;
>> +                               *key = MEDIUM_ERROR;
>> +                               *asc = ASC_WRITE_ERROR;
>> +                               return;
>> +                       }
>> +                       pos += written;
>> +                       fdatasync(cmd->dev->fd);
>> +               }
>> +               offset += count;
>> +       }
>> +}
>> +
>> +static void sanitize_block_erase(struct scsi_cmd *cmd,
>> +               int *result, uint8_t *key, uint16_t *asc)
>> +{
>> +       int fd = cmd->dev->fd;
>> +
>> +       cmd->dev->sanitize_state = LU_SANITIZE_RUNNING;
>> +       if (unmap_file_region(fd, 0, cmd->dev->size) != 0) {
>> +               eprintf("Failed to punch hole for"
>> +                       " SANITIZE"
>> +                       " length:%" PRIu64 "\n",
>> +                       cmd->dev->size);
>> +               *result = SAM_STAT_CHECK_CONDITION;
>> +               *key = HARDWARE_ERROR;
>> +               *asc = ASC_INTERNAL_TGT_FAILURE;
>> +               cmd->dev->sanitize_state = LU_SANITIZE_FAILURE;
>> +               return;
>> +       }
>> +       cmd->dev->sanitize_state = LU_SANITIZE_NONE;
>> +}
>> +
>> +#define SANITIZE_BATCHSIZE 16384
>> +
>> +static void sanitize_overwrite(struct scsi_cmd *cmd,
>> +               int *result, uint8_t *key, uint16_t *asc)
>> +{
>> +       int blocksize = 1 << cmd->dev->blk_shift;
>> +       char *buf;
>> +       int param_len;
>> +       char *param = scsi_get_out_buffer(cmd);
>> +       int invert, ocount, pattern_len;
>> +       int i, offset;
>> +
>> +       param_len = scsi_get_out_length(cmd);
>> +       if (param_len <= 4 || param_len >= blocksize + 5) {
>> +               eprintf("Invalid data-out size for sanitize
>> overwrite:%d\n",
>> +                       param_len);
>> +
>> +               *result = SAM_STAT_CHECK_CONDITION;
>> +               *key = ILLEGAL_REQUEST;
>> +               *asc = ASC_INVALID_FIELD_IN_CDB;
>> +               return;
>> +       }
>> +
>> +       invert = !!(param[0] & 0x80);
>> +       ocount = param[0] & 0x1f;
>> +       pattern_len = get_unaligned_be16(&param[2]);
>> +
>> +       if (!ocount) {
>> +               eprintf("Invalid overwrite count for sanitize
>> overwrite:%d\n",
>> +                       ocount);
>> +
>> +               *result = SAM_STAT_CHECK_CONDITION;
>> +               *key = ILLEGAL_REQUEST;
>> +               *asc = ASC_INVALID_FIELD_IN_CDB;
>> +               return;
>> +       }
>> +
>> +       if (!pattern_len) {
>> +               eprintf("Initialization pattern length was 0\n");
>> +
>> +               *result = SAM_STAT_CHECK_CONDITION;
>> +               *key = ILLEGAL_REQUEST;
>> +               *asc = ASC_INVALID_FIELD_IN_CDB;
>> +               return;
>> +       }
>> +
>> +       if (pattern_len > blocksize) {
>> +               eprintf("Initialization pattern length was > blocksize. "
>> \
>> +                       "%d > %d\n", pattern_len, blocksize);
>> +
>> +               *result = SAM_STAT_CHECK_CONDITION;
>> +               *key = ILLEGAL_REQUEST;
>> +               *asc = ASC_INVALID_FIELD_IN_CDB;
>> +               return;
>> +       }
>> +
>> +       if (pattern_len + 4 != param_len) {
>> +               eprintf("Initialization pattern length does not match"
>> +                       " data-out size. %d but data-out is %d\n",
>> +                       pattern_len, param_len);
>> +
>> +               *result = SAM_STAT_CHECK_CONDITION;
>> +               *key = ILLEGAL_REQUEST;
>> +               *asc = ASC_INVALID_FIELD_IN_CDB;
>> +               return;
>> +       }
>> +
>> +
>> +       cmd->dev->sanitize_state = LU_SANITIZE_RUNNING;
>> +
>> +       /* allocate a bunch of blocks so we can batch
>> +        * writes to the medium.
>> +        */
>> +       buf = malloc(blocksize * SANITIZE_BATCHSIZE);
>> +
>> +       /* and fill it with the initialization pattern */
>> +       offset = 0;
>> +       while (offset != blocksize * SANITIZE_BATCHSIZE) {
>> +               int count;
>> +
>> +               count = blocksize * SANITIZE_BATCHSIZE - offset;
>> +               if (count > pattern_len)
>> +                       count = pattern_len;
>> +
>> +               memcpy(buf + offset, param + 4, count);
>> +               offset += count;
>> +       }
>> +
>> +       if (invert && !(ocount & 0x01)) {
>> +               int j;
>> +               for (j = 0; j < blocksize * SANITIZE_BATCHSIZE; j++)
>> +                       buf[j] = ~buf[j];
>> +       }
>> +
>> +       for (i = 0; i < ocount; i++) {
>> +               sanitize_write_buffer(cmd, blocksize * SANITIZE_BATCHSIZE,
>> +                       buf,
>> +                       result, key, asc);
>> +
>> +               if (invert) {
>> +                       int j;
>> +                       for (j = 0; j < blocksize * SANITIZE_BATCHSIZE;
>> j++)
>> +                               buf[j] = ~buf[j];
>> +               }
>> +       }
>> +
>> +       free(buf);
>> +       cmd->dev->sanitize_state = LU_SANITIZE_NONE;
>> +}
>> +
>>   static void bs_rdwr_request(struct scsi_cmd *cmd)
>>   {
>>         int ret, fd = cmd->dev->fd;
>> @@ -357,6 +521,23 @@ verify:
>>                         tmpbuf += 16;
>>                 }
>>                 break;
>> +       case SANITIZE:
>> +               switch (cmd->scb[1] & 0x1f) {
>> +               case SA_BLOCK_ERASE:
>> +                       sanitize_block_erase(cmd, &result, &key, &asc);
>> +                       break;
>> +               case SA_OVERWRITE:
>> +                       sanitize_overwrite(cmd, &result, &key, &asc);
>> +                       break;
>> +               default:
>> +                       eprintf("Invalid sanitize service action %d",
>> +                               cmd->scb[1] & 0x1f);
>> +
>> +                       result = SAM_STAT_CHECK_CONDITION;
>> +                       key = ILLEGAL_REQUEST;
>> +                       asc = ASC_INVALID_FIELD_IN_CDB;
>> +               }
>> +               break;
>>         default:
>>                 break;
>>         }
>> diff --git a/usr/sbc.c b/usr/sbc.c
>> index c4f012c..1a2af48 100644
>> --- a/usr/sbc.c
>> +++ b/usr/sbc.c
>> @@ -66,6 +66,118 @@ static off_t find_next_hole(struct scsi_lu *dev, off_t
>> offset)
>>   #endif
>>   }
>>
>> +static int sbc_sanitize_overwrite(int host_no, struct scsi_cmd *cmd)
>> +{
>> +       int ret;
>> +       uint16_t param_len;
>> +       uint16_t asc = ASC_INVALID_FIELD_IN_CDB;
>> +       uint8_t key = ILLEGAL_REQUEST;
>> +
>> +       ret = device_reserved(cmd);
>> +       if (ret)
>> +               return SAM_STAT_RESERVATION_CONFLICT;
>> +
>> +       if (!cmd->dev->attrs.online) {
>> +               key = NOT_READY;
>> +               asc = ASC_MEDIUM_NOT_PRESENT;
>> +               goto sense;
>> +       }
>> +
>> +       if (cmd->dev->attrs.readonly || cmd->dev->attrs.swp) {
>> +               key = DATA_PROTECT;
>> +               asc = ASC_WRITE_PROTECT;
>> +               goto sense;
>> +       }
>> +
>> +       if (cmd->scb[1] & 0x40
>> +           || cmd->scb[2]
>> +           || cmd->scb[3]
>> +           || cmd->scb[4]
>> +           || cmd->scb[5]
>> +           || cmd->scb[6])
>> +               goto sense;
>> +
>> +       param_len = (uint16_t)get_unaligned_be16(&cmd->scb[7]);
>> +       if (param_len <= 4)
>> +               goto sense;
>> +       if (param_len >=  (1 << cmd->dev->blk_shift) + 5)
>> +               goto sense;
>> +
>> +       if (scsi_get_out_length(cmd) != param_len)
>> +               goto sense;
>> +
>> +       scsi_set_out_resid_by_actual(cmd, param_len);
>> +
>> +       ret = cmd->dev->bst->bs_cmd_submit(cmd);
>> +       if (ret) {
>> +               key = HARDWARE_ERROR;
>> +               asc = ASC_INTERNAL_TGT_FAILURE;
>> +       } else
>> +               return SAM_STAT_GOOD;
>> +
>> +sense:
>> +       scsi_set_in_resid_by_actual(cmd, 0);
>> +       sense_data_build(cmd, key, asc);
>> +       return SAM_STAT_CHECK_CONDITION;
>> +}
>> +
>> +static int sbc_sanitize_block_erase(int host_no, struct scsi_cmd *cmd)
>> +{
>> +       int ret;
>> +       uint16_t param_len;
>> +       uint16_t asc = ASC_INVALID_FIELD_IN_CDB;
>> +       uint8_t key = ILLEGAL_REQUEST;
>> +
>> +       ret = device_reserved(cmd);
>> +       if (ret)
>> +               return SAM_STAT_RESERVATION_CONFLICT;
>> +
>> +       if (!cmd->dev->attrs.online) {
>> +               key = NOT_READY;
>> +               asc = ASC_MEDIUM_NOT_PRESENT;
>> +               goto sense;
>> +       }
>> +
>> +       if (cmd->scb[1] & 0x40
>> +           || cmd->scb[2]
>> +           || cmd->scb[3]
>> +           || cmd->scb[4]
>> +           || cmd->scb[5]
>> +           || cmd->scb[6])
>> +               goto sense;
>> +
>> +       if (cmd->dev->attrs.readonly || cmd->dev->attrs.swp) {
>> +               key = DATA_PROTECT;
>> +               asc = ASC_WRITE_PROTECT;
>> +               goto sense;
>> +       }
>> +
>> +       param_len = (uint16_t)get_unaligned_be16(&cmd->scb[7]);
>> +       if (param_len != 0)
>> +               goto sense;
>> +
>> +       if (scsi_get_in_length(cmd) != param_len)
>> +               goto sense;
>> +
>> +       ret = cmd->dev->bst->bs_cmd_submit(cmd);
>> +       if (ret) {
>> +               key = HARDWARE_ERROR;
>> +               asc = ASC_INTERNAL_TGT_FAILURE;
>> +       } else
>> +               return SAM_STAT_GOOD;
>> +
>> +sense:
>> +       scsi_set_in_resid_by_actual(cmd, 0);
>> +       sense_data_build(cmd, key, asc);
>> +       return SAM_STAT_CHECK_CONDITION;
>> +}
>> +
>> +struct service_action sanitize_actions[] = {
>> +       {SA_OVERWRITE, sbc_sanitize_overwrite},
>> +       {SA_BLOCK_ERASE, sbc_sanitize_block_erase},
>> +       {0, NULL},
>> +};
>> +
>>   static int sbc_mode_page_update(struct scsi_cmd *cmd, uint8_t *data, int
>> *changed)
>>   {
>>         uint8_t pcode = data[0] & 0x3f;
>> @@ -114,6 +226,11 @@ static int sbc_mode_page_update(struct scsi_cmd *cmd,
>> uint8_t *data, int *change
>>
>>   static int sbc_mode_select(int host_no, struct scsi_cmd *cmd)
>>   {
>> +       if (cmd->dev->sanitize_state != LU_SANITIZE_NONE) {
>> +               sense_data_build(cmd, NOT_READY,
>> ASC_SANITIZE_IN_PROGRESS);
>> +               return SAM_STAT_CHECK_CONDITION;
>> +       }
>> +
>>         return spc_mode_select(host_no, cmd, sbc_mode_page_update);
>>   }
>>
>> @@ -121,6 +238,11 @@ static int sbc_mode_sense(int host_no, struct
>> scsi_cmd *cmd)
>>   {
>>         int ret;
>>
>> +       if (cmd->dev->sanitize_state != LU_SANITIZE_NONE) {
>> +               sense_data_build(cmd, NOT_READY,
>> ASC_SANITIZE_IN_PROGRESS);
>> +               return SAM_STAT_CHECK_CONDITION;
>> +       }
>> +
>>         ret = spc_mode_sense(host_no, cmd);
>>
>>         /*
>> @@ -149,6 +271,11 @@ static int sbc_format_unit(int host_no, struct
>> scsi_cmd *cmd)
>>         uint16_t asc = ASC_INVALID_FIELD_IN_CDB;
>>         int ret;
>>
>> +       if (cmd->dev->sanitize_state != LU_SANITIZE_NONE) {
>> +               sense_data_build(cmd, NOT_READY,
>> ASC_SANITIZE_IN_PROGRESS);
>> +               return SAM_STAT_CHECK_CONDITION;
>> +       }
>> +
>>         ret = device_reserved(cmd);
>>         if (ret)
>>                 return SAM_STAT_RESERVATION_CONFLICT;
>> @@ -193,6 +320,11 @@ static int sbc_unmap(int host_no, struct scsi_cmd
>> *cmd)
>>         struct scsi_lu *lu = cmd->dev;
>>         int anchor;
>>
>> +       if (cmd->dev->sanitize_state != LU_SANITIZE_NONE) {
>> +               sense_data_build(cmd, NOT_READY,
>> ASC_SANITIZE_IN_PROGRESS);
>> +               return SAM_STAT_CHECK_CONDITION;
>> +       }
>> +
>>         ret = device_reserved(cmd);
>>         if (ret)
>>                 return SAM_STAT_RESERVATION_CONFLICT;
>> @@ -248,6 +380,11 @@ static int sbc_rw(int host_no, struct scsi_cmd *cmd)
>>         uint16_t asc = ASC_LUN_NOT_SUPPORTED;
>>         struct scsi_lu *lu = cmd->dev;
>>
>> +       if (cmd->dev->sanitize_state != LU_SANITIZE_NONE) {
>> +               sense_data_build(cmd, NOT_READY,
>> ASC_SANITIZE_IN_PROGRESS);
>> +               return SAM_STAT_CHECK_CONDITION;
>> +       }
>> +
>>         ret = device_reserved(cmd);
>>         if (ret)
>>                 return SAM_STAT_RESERVATION_CONFLICT;
>> @@ -401,6 +538,11 @@ sense:
>>
>>   static int sbc_reserve(int host_no, struct scsi_cmd *cmd)
>>   {
>> +       if (cmd->dev->sanitize_state != LU_SANITIZE_NONE) {
>> +               sense_data_build(cmd, NOT_READY,
>> ASC_SANITIZE_IN_PROGRESS);
>> +               return SAM_STAT_CHECK_CONDITION;
>> +       }
>> +
>>         if (device_reserve(cmd))
>>                 return SAM_STAT_RESERVATION_CONFLICT ;
>>         else
>> @@ -411,6 +553,11 @@ static int sbc_release(int host_no, struct scsi_cmd
>> *cmd)
>>   {
>>         int ret;
>>
>> +       if (cmd->dev->sanitize_state != LU_SANITIZE_NONE) {
>> +               sense_data_build(cmd, NOT_READY,
>> ASC_SANITIZE_IN_PROGRESS);
>> +               return SAM_STAT_CHECK_CONDITION;
>> +       }
>> +
>>         ret = device_release(cmd->c_target->tid, cmd->cmd_itn_id,
>>                              cmd->dev->lun, 0);
>>
>> @@ -426,6 +573,11 @@ static int sbc_read_capacity(int host_no, struct
>> scsi_cmd *cmd)
>>         unsigned char key = ILLEGAL_REQUEST;
>>         uint16_t asc = ASC_LUN_NOT_SUPPORTED;
>>
>> +       if (cmd->dev->sanitize_state != LU_SANITIZE_NONE) {
>> +               sense_data_build(cmd, NOT_READY,
>> ASC_SANITIZE_IN_PROGRESS);
>> +               return SAM_STAT_CHECK_CONDITION;
>> +       }
>> +
>>         if (cmd->dev->attrs.removable && !cmd->dev->attrs.online) {
>>                 key = NOT_READY;
>>                 asc = ASC_MEDIUM_NOT_PRESENT;
>> @@ -466,6 +618,11 @@ static int sbc_verify(int host_no, struct scsi_cmd
>> *cmd)
>>         uint64_t lba;
>>         uint32_t tl;
>>
>> +       if (cmd->dev->sanitize_state != LU_SANITIZE_NONE) {
>> +               sense_data_build(cmd, NOT_READY,
>> ASC_SANITIZE_IN_PROGRESS);
>> +               return SAM_STAT_CHECK_CONDITION;
>> +       }
>> +
>>         if (cmd->dev->attrs.removable && !cmd->dev->attrs.online) {
>>                 key = NOT_READY;
>>                 asc = ASC_MEDIUM_NOT_PRESENT;
>> @@ -661,6 +818,24 @@ static int sbc_service_action(int host_no, struct
>> scsi_cmd *cmd)
>>         struct service_action *service_action, *actions;
>>
>>         action = cmd->scb[1] & 0x1f;
>> +
>> +       /* Active or failed sanitize operation */
>> +       if (cmd->dev->sanitize_state != LU_SANITIZE_NONE) {
>> +               /* Allow SANITIZE/EXIT_FAILURE_MODE to clear a failure
>> +                * but fail everything else.
>> +                */
>> +               if (cmd->dev->sanitize_state == LU_SANITIZE_FAILURE
>> +               && op == SANITIZE && action == SA_EXIT_FAILURE_MODE) {
>> +                       cmd->dev->sanitize_state = LU_SANITIZE_NONE;
>> +                       return SAM_STAT_GOOD;
>> +               } else {
>> +                       sense_data_build(cmd, NOT_READY,
>> +                               ASC_SANITIZE_IN_PROGRESS);
>> +                       return SAM_STAT_CHECK_CONDITION;
>> +               }
>> +       }
>> +
>> +
>>         actions = cmd->dev->dev_type_template.ops[op].service_actions;
>>
>>         service_action = find_service_action(actions, action);
>> @@ -681,6 +856,11 @@ static int sbc_sync_cache(int host_no, struct
>> scsi_cmd *cmd)
>>         uint8_t key = ILLEGAL_REQUEST;
>>         uint16_t asc = ASC_LUN_NOT_SUPPORTED;
>>
>> +       if (cmd->dev->sanitize_state != LU_SANITIZE_NONE) {
>> +               sense_data_build(cmd, NOT_READY,
>> ASC_SANITIZE_IN_PROGRESS);
>> +               return SAM_STAT_CHECK_CONDITION;
>> +       }
>> +
>>         if (device_reserved(cmd))
>>                 return SAM_STAT_RESERVATION_CONFLICT;
>>
>> @@ -864,7 +1044,7 @@ static struct device_type_template sbc_template = {
>>                 {spc_illegal_op,},
>>                 {spc_illegal_op,},
>>
>> -               {spc_illegal_op,},
>> +               {sbc_service_action, sanitize_actions,},
>>                 {spc_illegal_op,},
>>                 {spc_illegal_op,},
>>                 {spc_illegal_op,},
>> @@ -889,8 +1069,8 @@ static struct device_type_template sbc_template = {
>>                 {spc_illegal_op,},
>>                 {spc_illegal_op,},
>>                 {spc_illegal_op,},
>> -               {spc_service_action, persistent_reserve_in_actions,},
>> -               {spc_service_action, persistent_reserve_out_actions,},
>> +               {sbc_service_action, persistent_reserve_in_actions,},
>> +               {sbc_service_action, persistent_reserve_out_actions,},
>>
>>                 [0x60 ... 0x7f] = {spc_illegal_op,},
>>
>> @@ -937,7 +1117,7 @@ static struct device_type_template sbc_template = {
>>                 {spc_report_luns,},
>>                 {spc_illegal_op,},
>>                 {spc_illegal_op,},
>> -               {spc_service_action, maint_in_service_actions,},
>> +               {sbc_service_action, maint_in_service_actions,},
>>                 {spc_illegal_op,},
>>                 {spc_illegal_op,},
>>                 {spc_illegal_op,},
>> diff --git a/usr/scsi.c b/usr/scsi.c
>> index 2636a5c..78701be 100644
>> --- a/usr/scsi.c
>> +++ b/usr/scsi.c
>> @@ -119,6 +119,9 @@ const unsigned char *get_scsi_cdb_usage_data(unsigned
>> char op, unsigned char sa)
>>         static const unsigned char read_capacity[] = {
>>                0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
>>                0x00, 0x07};
>> +       static const unsigned char sanitize[] = {
>> +              0xff, 0xbf, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
>> +              0xff, 0x07};
>>
>>         static const unsigned char verify_12[] = {
>>                0xff, 0xf2, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
>> @@ -165,6 +168,8 @@ const unsigned char *get_scsi_cdb_usage_data(unsigned
>> char op, unsigned char sa)
>>                0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x07};
>>
>>         switch (op) {
>> +       case SANITIZE:
>> +               return sanitize;
>>         case TEST_UNIT_READY:
>>                 return test_unit_ready;
>>         case REQUEST_SENSE:
>> diff --git a/usr/scsi.h b/usr/scsi.h
>> index 1edcfd7..9dbd9f3 100644
>> --- a/usr/scsi.h
>> +++ b/usr/scsi.h
>> @@ -62,6 +62,7 @@
>>   #define WRITE_SAME            0x41
>>   #define UNMAP               0x42
>>   #define READ_TOC              0x43
>> +#define SANITIZE              0x48
>>   #define LOG_SELECT            0x4c
>>   #define LOG_SENSE             0x4d
>>   #define MODE_SELECT_10        0x55
>> @@ -178,6 +179,7 @@
>>   #define ASC_CAUSE_NOT_REPORTABLE              0x0400
>>   #define ASC_BECOMING_READY                    0x0401
>>   #define ASC_INITIALIZING_REQUIRED             0x0402
>> +#define ASC_SANITIZE_IN_PROGRESS               0x041b
>>   #define ASC_CLEANING_CART_INSTALLED           0x3003
>>   #define ASC_CLEANING_FAILURE                  0x3007
>>   #define ASC_MEDIUM_NOT_PRESENT                        0x3a00
>> @@ -270,4 +272,10 @@
>>   #define PR_TYPE_WRITE_EXCLUSIVE_ALLREG                0x07
>>   #define PR_TYPE_EXCLUSIVE_ACCESS_ALLREG               0x08
>>
>> +/* Sanitize service actions */
>> +#define SA_OVERWRITE                           0x01
>> +#define SA_BLOCK_ERASE                         0x02
>> +#define SA_CRYPTO_ERASE                                0x03
>> +#define SA_EXIT_FAILURE_MODE                   0x1f
>> +
>>   #endif
>> diff --git a/usr/spc.c b/usr/spc.c
>> index 15077ca..8551ea2 100644
>> --- a/usr/spc.c
>> +++ b/usr/spc.c
>> @@ -180,6 +180,26 @@ static void update_vpd_b2(struct scsi_lu *lu, void
>> *id)
>>         }
>>   }
>>
>> +static void update_vpd_b1(struct scsi_lu *lu, void *id)
>> +{
>> +       struct vpd *vpd_pg = lu->attrs.lu_vpd[PCODE_OFFSET(0xb1)];
>> +       uint8_t *data = vpd_pg->data;
>> +
>> +       /* medium rotation rate */
>> +       data[0] = 0;
>> +       data[1] = 0;
>> +
>> +       /* product type */
>> +       data[2] = 0;
>> +
>> +       /* wabereq == 01b */
>> +       data[3] = 0x40;
>> +
>> +       /* fuab == 1  vbuls == 1 */
>> +       data[4] = 0x03;
>> +
>> +}
>> +
>>   static void update_vpd_b0(struct scsi_lu *lu, void *id)
>>   {
>>         struct vpd *vpd_pg = lu->attrs.lu_vpd[PCODE_OFFSET(0xb0)];
>> @@ -373,6 +393,11 @@ int spc_start_stop(int host_no, struct scsi_cmd *cmd)
>>         uint8_t *scb = cmd->scb;
>>         int start, loej, pwrcnd;
>>
>> +       if (cmd->dev->sanitize_state != LU_SANITIZE_NONE) {
>> +               sense_data_build(cmd, NOT_READY,
>> ASC_SANITIZE_IN_PROGRESS);
>> +               return SAM_STAT_CHECK_CONDITION;
>> +       }
>> +
>>         scsi_set_in_resid_by_actual(cmd, 0);
>>
>>         if (device_reserved(cmd))
>> @@ -410,6 +435,10 @@ int spc_test_unit(int host_no, struct scsi_cmd *cmd)
>>   {
>>         /* how should we test a backing-storage file? */
>>
>> +       if (cmd->dev->sanitize_state != LU_SANITIZE_NONE) {
>> +               sense_data_build(cmd, NOT_READY,
>> ASC_SANITIZE_IN_PROGRESS);
>> +               return SAM_STAT_CHECK_CONDITION;
>> +       }
>>         if (device_reserved(cmd))
>>                 return SAM_STAT_RESERVATION_CONFLICT;
>>         if (cmd->dev->attrs.online)
>> @@ -427,6 +456,11 @@ int spc_prevent_allow_media_removal(int host_no,
>> struct scsi_cmd *cmd)
>>         uint8_t *scb = cmd->scb;
>>         struct it_nexus_lu_info *itn_lu_info = cmd->itn_lu_info;
>>
>> +       if (cmd->dev->sanitize_state != LU_SANITIZE_NONE) {
>> +               sense_data_build(cmd, NOT_READY,
>> ASC_SANITIZE_IN_PROGRESS);
>> +               return SAM_STAT_CHECK_CONDITION;
>> +       }
>> +
>>         if (device_reserved(cmd))
>>                 return SAM_STAT_RESERVATION_CONFLICT;
>>
>> @@ -934,6 +968,12 @@ int spc_send_diagnostics(int host_no, struct scsi_cmd
>> *cmd)
>>         uint16_t asc = ASC_INVALID_FIELD_IN_CDB;
>>         uint8_t key = ILLEGAL_REQUEST;
>>
>> +       if (cmd->dev->sanitize_state != LU_SANITIZE_NONE) {
>> +               key = NOT_READY;
>> +               asc = ASC_SANITIZE_IN_PROGRESS;
>> +               goto sense;
>> +       }
>> +
>>         /* we only support SELF-TEST==1 */
>>         if (!(cmd->scb[1] & 0x04))
>>                 goto sense;
>> @@ -2067,6 +2107,14 @@ int spc_lu_init(struct scsi_lu *lu)
>>         lu_vpd[pg]->vpd_update = update_vpd_b0;
>>         lu_vpd[pg]->vpd_update(lu, NULL);
>>
>> +       /* VPD page 0xb1 BLOCK DEVICE CHARACTERISTICS*/
>> +       pg = PCODE_OFFSET(0xb1);
>> +       lu_vpd[pg] = alloc_vpd(BDC_VPD_LEN);
>> +       if (!lu_vpd[pg])
>> +               return -ENOMEM;
>> +       lu_vpd[pg]->vpd_update = update_vpd_b1;
>> +       lu_vpd[pg]->vpd_update(lu, NULL);
>> +
>>         /* VPD page 0xb2 LOGICAL BLOCK PROVISIONING*/
>>         pg = PCODE_OFFSET(0xb2);
>>         lu_vpd[pg] = alloc_vpd(LBP_VPD_LEN);
>> diff --git a/usr/spc.h b/usr/spc.h
>> index 0c537e1..43d4ac6 100644
>> --- a/usr/spc.h
>> +++ b/usr/spc.h
>> @@ -1,8 +1,9 @@
>>   #ifndef __SPC_H
>>   #define __SPC_H
>>
>> -extern struct service_action maint_in_service_actions[],
>> -       persistent_reserve_in_actions[], persistent_reserve_out_actions[];
>> +extern struct service_action maint_in_service_actions[];
>> +extern struct service_action persistent_reserve_in_actions[];
>> +extern struct service_action persistent_reserve_out_actions[];
>>
>>   extern int spc_service_action(int host_no, struct scsi_cmd *cmd);
>>   extern int spc_inquiry(int host_no, struct scsi_cmd *cmd);
>> diff --git a/usr/target.c b/usr/target.c
>> index b1729b3..c7d210b 100644
>> --- a/usr/target.c
>> +++ b/usr/target.c
>> @@ -588,6 +588,12 @@ tgtadm_err tgt_device_create(int tid, int dev_type,
>> uint64_t lun, char *params,
>>         lu->prgeneration = 0;
>>         lu->pr_holder = NULL;
>>
>> +       /* TODO: Here we should really read this from stable storage since
>> +        * active/failed sanitize state are supposed to survive across
>> +        * target resets/reboots.
>> +        */
>> +       lu->sanitize_state = LU_SANITIZE_NONE;
>> +
>>         lu->cmd_perform = &target_cmd_perform;
>>         lu->cmd_done = &__cmd_done;
>>
>> diff --git a/usr/tgtd.h b/usr/tgtd.h
>> index 484e6e9..2b795a5 100644
>> --- a/usr/tgtd.h
>> +++ b/usr/tgtd.h
>> @@ -14,6 +14,7 @@ struct concat_buf;
>>   #define PRODUCT_ID_LEN                16
>>   #define PRODUCT_REV_LEN               4
>>   #define BLOCK_LIMITS_VPD_LEN  0x3C
>> +#define BDC_VPD_LEN            0x3C
>>   #define LBP_VPD_LEN           4
>>
>>   #define PCODE_SHIFT           7
>> @@ -187,6 +188,12 @@ struct registration {
>>         uint8_t pr_type;
>>   };
>>
>> +enum lu_sanitize_state {
>> +     LU_SANITIZE_NONE = 1,
>> +     LU_SANITIZE_RUNNING,
>> +     LU_SANITIZE_FAILURE,
>> +};
>> +
>>   struct scsi_lu {
>>         int fd;
>>         uint64_t addr; /* persistent mapped address */
>> @@ -217,6 +224,8 @@ struct scsi_lu {
>>
>>         struct lu_phy_attr attrs;
>>
>> +       enum lu_sanitize_state sanitize_state;
>> +
>>         struct list_head registration_list;
>>         uint32_t prgeneration;
>>         struct registration *pr_holder;
>>
>
--
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