[PATCH 2/5] SBC: Initial WRITE_SAME support

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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


[Index of Archives]     [Linux SCSI]     [Linux RAID]     [Linux Clusters]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]

  Powered by Linux