[stgt] [PATCH] Initial SANITIZE support
FUJITA Tomonori
fujita.tomonori at lab.ntt.co.jp
Thu Aug 1 00:23:39 CEST 2013
On Sun, 21 Jul 2013 11:34:21 -0700
Ronnie Sahlberg <ronniesahlberg at gmail.com> 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(¶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;
> +}
Instead of adding new functions to usr/bs_rdwr.c, can we use the
existing functions for write/sync usr/bs_rdwr.c? With such way,
SANITIZE can be implemented easily with other backing store code.
--
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