[PATCH 11/13] sbc: fix data-in buffer generation for READ_CAPACITY(16)

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

 



From: Alexander Nezhinsky <nezhinsky@xxxxxxxxx>

READ_CAPACITY(16) is an SBC command behaving in SPC-like manner.
Generate data-in in a separate buffer and safe-copy it to the command buffer
taking into account the allocation length.
Set the actual transfer len correctly.

Signed-off-by: Alexander Nezhinsky <nezhinsky@xxxxxxxxx>
---
 usr/sbc.c |   33 ++++++++++++++++++---------------
 1 file changed, 18 insertions(+), 15 deletions(-)

diff --git a/usr/sbc.c b/usr/sbc.c
index c059c37..7fb1ea8 100644
--- a/usr/sbc.c
+++ b/usr/sbc.c
@@ -477,13 +477,14 @@ sense:
 
 static int sbc_readcapacity16(int host_no, struct scsi_cmd *cmd)
 {
-	uint32_t *data;
+	uint32_t alloc_len, avail_len, actual_len;
+	uint8_t *data;
+	uint8_t buf[32];
 	unsigned int bshift;
 	uint64_t size;
-	int len = 32;
-	int val;
+	uint32_t val;
+	uint16_t asc = ASC_INVALID_FIELD_IN_CDB;
 	unsigned char key = ILLEGAL_REQUEST;
-	uint16_t asc = ASC_INVALID_OP_CODE;
 
 	if (cmd->dev->attrs.removable && !cmd->dev->attrs.online) {
 		key = NOT_READY;
@@ -491,27 +492,29 @@ static int sbc_readcapacity16(int host_no, struct scsi_cmd *cmd)
 		goto sense;
 	}
 
-	if (scsi_get_in_length(cmd) < 12)
-		goto overflow;
-
-	len = min_t(int, len, scsi_get_in_length(cmd));
+	alloc_len = get_unaligned_be32(&cmd->scb[10]);
+	if (scsi_get_in_length(cmd) < alloc_len)
+		goto sense;
 
-	data = scsi_get_in_buffer(cmd);
-	memset(data, 0, len);
+	data = buf;
+	memset(data, 0, 32);
+	avail_len = 32;
 
 	bshift = cmd->dev->blk_shift;
 	size = cmd->dev->size >> bshift;
 
-	*((uint64_t *)(data)) = __cpu_to_be64(size - 1);
-	data[2] = __cpu_to_be32(1UL << bshift);
+	put_unaligned_be64(size - 1, &data[0]);
+	put_unaligned_be32(1UL << bshift, &data[8]);
 
 	val = (cmd->dev->attrs.lbppbe << 16) | cmd->dev->attrs.la_lba;
 	if (cmd->dev->attrs.thinprovisioning)
 		val |= (3 << 14); /* set LBPME and LBPRZ */
-	data[3] = __cpu_to_be32(val);
+	put_unaligned_be32(val, &data[12]);
+
+	actual_len = spc_memcpy(scsi_get_in_buffer(cmd), &alloc_len,
+				data, avail_len);
+	scsi_set_in_resid_by_actual(cmd, actual_len);
 
-overflow:
-	scsi_set_in_resid_by_actual(cmd, len);
 	return SAM_STAT_GOOD;
 
 sense:
-- 
1.7.9.6

--
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