[Stgt-devel] [PATCH 1/3] osd sense fixup

Pete Wyckoff pw
Thu Mar 15 19:57:04 CET 2007


OSD must use descriptor format sense data.  Support request sense and
report luns.  Add support for a couple more inquiry page codes.  Remove
list of actions; submit can deal with it.  They are obsolete anyway.

Signed-off-by: Pete Wyckoff <pw at osc.edu>
---

 usr/osd.c |  293 +++++++++++++++++++++++++++++++++++++++----------------------
 usr/osd.h |   33 -------
 2 files changed, 188 insertions(+), 138 deletions(-)

diff --git a/usr/osd.c b/usr/osd.c
index 9df1681..27c9b7d 100644
--- a/usr/osd.c
+++ b/usr/osd.c
@@ -1,7 +1,7 @@
 /*
  * SCSI object storage device command processing
  *
- * Copyright (C) 2006 Pete Wyckoff <pw at osc.edu>
+ * Copyright (C) 2006-2007 Pete Wyckoff <pw at osc.edu>
  *
  * Copyright (C) 2007 FUJITA Tomonori <tomof at acm.org>
  * Copyright (C) 2007 Mike Christie <michaelc at cs.wisc.edu>
@@ -13,6 +13,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <unistd.h>
 
 #include "list.h"
 #include "util.h"
@@ -21,19 +22,36 @@
 #include "driver.h"
 #include "scsi.h"
 #include "spc.h"
-#include "osd.h"
 
 #define PRODUCT_ID	"OSD"
 #define PRODUCT_REV	"0"
 
+/*
+ * Build a descriptor format sense header.  OSDs must return this,
+ * not fixed format.
+ */
+static void sense_descriptor_build(struct scsi_cmd *cmd, uint8_t key,
+				   uint8_t asc, uint8_t ascq)
+{
+	cmd->sense_buffer[0] = 0x72;  /* current, not deferred */
+	cmd->sense_buffer[1] = key;
+	cmd->sense_buffer[2] = asc;
+	cmd->sense_buffer[3] = ascq;
+	cmd->sense_len = 8;
+}
+
 static int osd_inquiry(int host_no, struct scsi_cmd *cmd)
 {
 	uint8_t *data, *scb = cmd->scb;
-	int len, ret = SAM_STAT_CHECK_CONDITION;
-	unsigned char key = ILLEGAL_REQUEST, asc = 0x25;
+	int evpd = scb[1] & 1;
+	uint8_t page_code = scb[2];
+	uint16_t alloc_len = (scb[3] << 8) | scb[4];
+	int len;
+	/* illegal field in CDB */
+	unsigned char key = ILLEGAL_REQUEST, asc = 0x24;
 
 	/* EVPD means need a page code */
-	if ((scb[1] & 0x3) == 0 && scb[2] != 0)
+	if ((scb[1] & 0x3) == 0 && page_code != 0)
 		goto sense;
 
 	data = valloc(pagesize);
@@ -44,13 +62,17 @@ static int osd_inquiry(int host_no, struct scsi_cmd *cmd)
 	}
 	memset(data, 0, pagesize);
 
-	dprintf("%x %x\n", scb[1], scb[2]);
+	dprintf("%x %x\n", scb[1], page_code);
 
 	data[0] = TYPE_OSD;
 	if (!cmd->dev)
 		data[0] = TYPE_NO_LUN;
 
-	if ((scb[1] & 0x1) == 0) {
+	if (evpd == 0) {
+		if (alloc_len < 5)
+			goto sense;
+		if (page_code != 0)
+			goto sense;
 		data[2] = 5;  /* modern version */
 		data[3] = 0x02;  /* modern response format */
 		data[7] = 0x02;  /* support command queueing */
@@ -72,55 +94,64 @@ static int osd_inquiry(int host_no, struct scsi_cmd *cmd)
 			len = 64;
 		}
 		data[4] = len - 5;  /* additional length */
-		ret = SAM_STAT_GOOD;
 	} else {
+		if (alloc_len < 4)
+			goto sense;
 		if (!cmd->dev)
 			goto sense;
-
-		data[1] = scb[2];
-		if (scb[2] == 0x0) {
+		data[1] = page_code;
+		if (page_code == 0x0) {
 			/* supported VPD pages */
 			data[3] = 3;
 			data[4] = 0x0;
 			data[5] = 0x80;
 			data[6] = 0x83;
 			len = 7;
-			ret = SAM_STAT_GOOD;
-		} else if (scb[2] == 0x80) {
-			/* unit serial number "    " */
-			data[3] = 4;
-			memset(data + 4, 0x20, 4);
-			len = 8;
-			ret = SAM_STAT_GOOD;
-		} else if (scb[2] == 0x83) {
+		} else if (page_code == 0x80) {
+			/* unit serial number */
+			char hostname[256];
+			gethostname(hostname, sizeof(hostname));
+			data[3] = strlen(hostname);
+			memcpy(data + 4, hostname, strlen(hostname)+1);
+			len = 4 + data[3];
+		} else if (page_code == 0x83) {
 			/* device identification */
 			data[3] = SCSI_ID_LEN + 4;
 			data[4] = 0x1;
 			data[5] = 0x1;
 			data[7] = SCSI_ID_LEN;
 			if (cmd->dev)
-				memcpy(data + 8, cmd->dev->scsi_id, SCSI_ID_LEN);
+				memcpy(data + 8, cmd->dev->scsi_id,
+				       SCSI_ID_LEN);
 			len = SCSI_ID_LEN + 8;
-			ret = SAM_STAT_GOOD;
+		} else if (page_code == 0xb0) {
+			/* osd information */
+			data[3] = 10-4; /* addl length */
+			data[4+3] = 2;
+			data[4+4] = 0;  /* nosec */
+			data[4+5] = 0;
+			len = 10;
+		} else if (page_code == 0xb1) {
+			data[3] = 20-4;  /* addl length */
+			memset(&data[4], 0xaa, 16);  /* random secy token */
+			len = 20;
 		}
 	}
 
-	if (ret != SAM_STAT_GOOD)
-		goto sense;
-
-	cmd->len = min_t(int, len, scb[4]);
-
+	cmd->uaddr = (uintptr_t) data;
+	cmd->len = min_t(int, len, alloc_len);
 	return SAM_STAT_GOOD;
+
 sense:
-	sense_data_build(cmd, key, asc, 0);
+	sense_descriptor_build(cmd, key, asc, 0);
 	cmd->len = 0;
 	return SAM_STAT_CHECK_CONDITION;
 }
 
-static int osd_varlen_cdb(int host_no, struct scsi_cmd *cmd)
+static int osd_varlen_cdb(int host_no __attribute__((unused)),
+			  struct scsi_cmd *cmd)
 {
 	int ret = SAM_STAT_GOOD;
-	uint16_t action;
 	unsigned char key = ILLEGAL_REQUEST, asc = 0x25;
 
 	dprintf("cdb[0] %x datalen %u\n", cmd->scb[0], cmd->len);
@@ -130,98 +161,150 @@ static int osd_varlen_cdb(int host_no, struct scsi_cmd *cmd)
 		goto sense;
 	}
 
-	action = (cmd->scb[8] << 8) | cmd->scb[9];
-
-	switch (action) {
-	case OSD_APPEND:
-	case OSD_CREATE:
-	case OSD_CREATE_AND_WRITE:
-	case OSD_CREATE_COLLECTION:
-	case OSD_CREATE_PARTITION:
-	case OSD_FLUSH:
-	case OSD_FLUSH_COLLECTION:
-	case OSD_FLUSH_OSD:
-	case OSD_FLUSH_PARTITION:
-	case OSD_FORMAT_OSD:
-	case OSD_GET_ATTRIBUTES:
-	case OSD_GET_MEMBER_ATTRIBUTES:
-	case OSD_LIST:
-	case OSD_LIST_COLLECTION:
-	case OSD_PERFORM_SCSI_COMMAND:
-	case OSD_PERFORM_TASK_MGMT_FUNC:
-	case OSD_QUERY:
-	case OSD_READ:
-	case OSD_REMOVE:
-	case OSD_REMOVE_COLLECTION:
-	case OSD_REMOVE_MEMBER_OBJECTS:
-	case OSD_REMOVE_PARTITION:
-	case OSD_SET_ATTRIBUTES:
-	case OSD_SET_KEY:
-	case OSD_SET_MASTER_KEY:
-	case OSD_SET_MEMBER_ATTRIBUTES:
-	case OSD_WRITE:
-		ret = cmd->c_target->bdt->bd_cmd_submit(cmd);
-		if (ret)
-			goto sense;
-		break;
-	default:
-		eprintf("unknown service action 0x%04x\n", action);
-		goto sense;
-	}
+	/* returns SAM status and fills sense */
+	ret = cmd->c_target->bdt->bd_cmd_submit(cmd);
+	return ret;
 
-	return SAM_STAT_GOOD;
 sense:
-	sense_data_build(cmd, key, asc, 0);
+	sense_descriptor_build(cmd, key, asc, 0);
+	cmd->len = 0;
+	return SAM_STAT_CHECK_CONDITION;
+}
+
+/*
+ * Return descriptor format, with asc/ascq 0x2400 "Illegal field in CDB".
+ */
+static int osd_illegal_op(int host_no, struct scsi_cmd *cmd)
+{
 	cmd->len = 0;
+	sense_descriptor_build(cmd, ILLEGAL_REQUEST, 0x24, 0);
 	return SAM_STAT_CHECK_CONDITION;
 }
 
+/*
+ * Many commands are duplicate from SPC because we must return different
+ * sense format.
+ */
+static int osd_test_unit(int host_no, struct scsi_cmd *cmd)
+{
+	int ret;
+
+	if (!cmd->dev)
+		ret = osd_illegal_op(host_no, cmd);
+	else
+		ret = spc_test_unit(host_no, cmd);
+	return ret;
+}
+
+
+static int osd_request_sense(int host_no, struct scsi_cmd *cmd)
+{
+	cmd->len = 0;
+	sense_descriptor_build(cmd, NO_SENSE, 0, 0);
+	return SAM_STAT_GOOD;
+}
+
+static int osd_report_luns(int host_no, struct scsi_cmd *cmd)
+{
+	int ret;
+
+	ret = spc_report_luns(host_no, cmd);
+	if (ret == SAM_STAT_CHECK_CONDITION) {
+		/*
+		 * Ick.  Translate descriptor format.
+		 */
+		uint8_t key = cmd->sense_buffer[2];
+		uint8_t asc = cmd->sense_buffer[12];
+		uint8_t ascq = cmd->sense_buffer[13];
+		sense_descriptor_build(cmd, key, asc, ascq);
+	}
+	return ret;
+}
+
 struct device_type_template osd_template = {
 	.type	= TYPE_OSD,
 	.name	= "osd",
 	.ops	= {
-		[0x00 ... 0x0f] = {spc_illegal_op},
+		/* 0x00 */
+		{osd_test_unit,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_request_sense,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
 
 		/* 0x10 */
-		{spc_illegal_op,},
-		{spc_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
 		{osd_inquiry,},
-		{spc_illegal_op,},
-		{spc_illegal_op,},
-		{spc_illegal_op,},
-		{spc_illegal_op,},
-		{spc_illegal_op,},
-
-		{spc_illegal_op,},
-		{spc_illegal_op,},
-		{spc_illegal_op,},
-		{spc_illegal_op,},
-		{spc_illegal_op,},
-		{spc_illegal_op,},
-		{spc_illegal_op,},
-		{spc_illegal_op,},
-
-		[0x20 ... 0x6f] = {spc_illegal_op},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+
+		[0x20 ... 0x6f] = {osd_illegal_op},
 
 		/* 0x70 */
-		{spc_illegal_op,},
-		{spc_illegal_op,},
-		{spc_illegal_op,},
-		{spc_illegal_op,},
-		{spc_illegal_op,},
-		{spc_illegal_op,},
-		{spc_illegal_op,},
-		{spc_illegal_op,},
-
-		{spc_illegal_op,},
-		{spc_illegal_op,},
-		{spc_illegal_op,},
-		{spc_illegal_op,},
-		{spc_illegal_op,},
-		{spc_illegal_op,},
-		{spc_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
 		{osd_varlen_cdb,},
 
-		[0x80 ... 0xff] = {spc_illegal_op},
+		[0x80 ... 0x9f] = {osd_illegal_op},
+
+		/* 0xA0 */
+		{osd_report_luns,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+		{osd_illegal_op,},
+
+		[0xb0 ... 0xff] = {osd_illegal_op},
 	}
 };
diff --git a/usr/osd.h b/usr/osd.h
deleted file mode 100644
index fe9f43c..0000000
--- a/usr/osd.h
+++ /dev/null
@@ -1,33 +0,0 @@
-#ifndef __OSD_H
-#define __OSD_H
-
-/* varlen cdb service actions for OSD-2 (before SNIA changes 17 jan 07) */
-#define OSD_APPEND			0x8807
-#define OSD_CREATE			0x8802
-#define OSD_CREATE_AND_WRITE		0x8812
-#define OSD_CREATE_COLLECTION		0x8815
-#define OSD_CREATE_PARTITION		0x880b
-#define OSD_FLUSH			0x8808
-#define OSD_FLUSH_COLLECTION		0x881a
-#define OSD_FLUSH_OSD			0x881c
-#define OSD_FLUSH_PARTITION		0x881b
-#define OSD_FORMAT_OSD			0x8801
-#define OSD_GET_ATTRIBUTES		0x880e
-#define OSD_GET_MEMBER_ATTRIBUTES	0x8822
-#define OSD_LIST			0x8803
-#define OSD_LIST_COLLECTION		0x8817
-#define OSD_PERFORM_SCSI_COMMAND	0x8f7e
-#define OSD_PERFORM_TASK_MGMT_FUNC	0x8f7f
-#define OSD_QUERY			0x8820
-#define OSD_READ			0x8805
-#define OSD_REMOVE			0x880a
-#define OSD_REMOVE_COLLECTION		0x8816
-#define OSD_REMOVE_MEMBER_OBJECTS	0x8821
-#define OSD_REMOVE_PARTITION		0x880c
-#define OSD_SET_ATTRIBUTES		0x880f
-#define OSD_SET_KEY			0x8818
-#define OSD_SET_MASTER_KEY		0x8819
-#define OSD_SET_MEMBER_ATTRIBUTES	0x8823
-#define OSD_WRITE			0x8806
-
-#endif



More information about the stgt mailing list