Initial support for WRITE_SAME command. Basic support but not yet support for unmapping of blocks. WRITE_SAME support only implemented for the bs_rdwr.c backend and errors will be returned for the bs_aio.c backend. At a later stage we can add WRITE_SAME support for bs_aio.c too. Signed-off-by: Ronnie Sahlberg <ronniesahlberg@xxxxxxxxx> --- usr/bs_aio.c | 4 ++++ usr/bs_rdwr.c | 24 ++++++++++++++++++++++++ usr/sbc.c | 17 ++++++++++++++++- usr/scsi.c | 2 ++ 4 files changed, 46 insertions(+), 1 deletions(-) diff --git a/usr/bs_aio.c b/usr/bs_aio.c index 75ae66f..d69c6a1 100644 --- a/usr/bs_aio.c +++ b/usr/bs_aio.c @@ -206,6 +206,10 @@ static int bs_aio_cmd_submit(struct scsi_cmd *cmd) case READ_16: break; + case WRITE_SAME: + eprintf("WRITE_SAME not yet supported for AIO backend.\n"); + return -1; + case SYNCHRONIZE_CACHE: case SYNCHRONIZE_CACHE_16: default: diff --git a/usr/bs_rdwr.c b/usr/bs_rdwr.c index 31f4441..5110a90 100644 --- a/usr/bs_rdwr.c +++ b/usr/bs_rdwr.c @@ -65,6 +65,7 @@ static void bs_rdwr_request(struct scsi_cmd *cmd) uint8_t key; uint16_t asc; char *tmpbuf; + size_t blocksize; uint64_t offset = cmd->offset; uint32_t tl = cmd->tl; @@ -111,6 +112,29 @@ static void bs_rdwr_request(struct scsi_cmd *cmd) POSIX_FADV_NOREUSE); break; + case WRITE_SAME: + while (tl > 0) { + blocksize = 1 << cmd->dev->blk_shift; + tmpbuf = scsi_get_out_buffer(cmd); + + switch(cmd->scb[1] & 0x06) { + case 0x02: /* PBDATA==0 LBDATA==1 */ + put_unaligned_be32(offset, tmpbuf); + break; + case 0x04: /* PBDATA==1 LBDATA==0 */ + /* physical sector format */ + put_unaligned_be64(offset, tmpbuf); + break; + } + + ret = pwrite64(fd, tmpbuf, blocksize, offset); + if (ret != blocksize) + set_medium_error(&result, &key, &asc); + + offset += blocksize; + tl -= blocksize; + } + break; case READ_6: case READ_10: case READ_12: diff --git a/usr/sbc.c b/usr/sbc.c index 55145cf..cf72e65 100644 --- a/usr/sbc.c +++ b/usr/sbc.c @@ -228,6 +228,20 @@ static int sbc_rw(int host_no, struct scsi_cmd *cmd) goto sense; } break; + case WRITE_SAME: + /* We only support protection information type 0 */ + if (cmd->scb[1] & 0xe0) { + key = ILLEGAL_REQUEST; + asc = ASC_INVALID_FIELD_IN_CDB; + goto sense; + } + /* LBDATA and PBDATA can not both be set */ + if ((cmd->scb[1] & 0x06) == 0x06) { + key = ILLEGAL_REQUEST; + asc = ASC_INVALID_FIELD_IN_CDB; + goto sense; + } + break; } if (lu->attrs.readonly) { @@ -236,6 +250,7 @@ static int sbc_rw(int host_no, struct scsi_cmd *cmd) case WRITE_10: case WRITE_12: case WRITE_16: + case WRITE_SAME: case PRE_FETCH_10: case PRE_FETCH_16: key = DATA_PROTECT; @@ -607,7 +622,7 @@ static struct device_type_template sbc_template = { /* 0x40 */ {spc_illegal_op,}, - {spc_illegal_op,}, + {sbc_rw,}, /* WRITE_SAME10 */ {sbc_unmap,}, {spc_illegal_op,}, {spc_illegal_op,}, diff --git a/usr/scsi.c b/usr/scsi.c index 7802ba1..c46753e 100644 --- a/usr/scsi.c +++ b/usr/scsi.c @@ -119,6 +119,7 @@ uint64_t scsi_rw_offset(uint8_t *scb) case WRITE_10: case VERIFY_10: case WRITE_VERIFY: + case WRITE_SAME: case SYNCHRONIZE_CACHE: case READ_12: case WRITE_12: @@ -162,6 +163,7 @@ uint32_t scsi_rw_count(uint8_t *scb) case WRITE_10: case VERIFY_10: case WRITE_VERIFY: + case WRITE_SAME: case SYNCHRONIZE_CACHE: cnt = (uint16_t)scb[7] << 8 | (uint16_t)scb[8]; break; -- 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