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@xxxxxxxxx> --- 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(¶m[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; -- 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