[Stgt-devel] [PATCH 4/4] OSD command parser
Pete Wyckoff
pw
Mon Jan 22 20:08:39 CET 2007
Add command parser for OSD commands.
Signed-off-by: Pete Wyckoff <pw at osc.edu>
---
usr/Makefile | 2 +-
usr/osd.c | 182 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
usr/scsi.c | 4 +
usr/scsi.h | 31 ++++++++++
usr/tgtd.h | 6 ++
5 files changed, 224 insertions(+), 1 deletions(-)
diff --git a/usr/Makefile b/usr/Makefile
index 7b828e0..181f0cc 100644
--- a/usr/Makefile
+++ b/usr/Makefile
@@ -45,7 +45,7 @@ INCLUDES += -I.
CFLAGS += -Wall -O2 -Wstrict-prototypes -fPIC -D_LARGEFILE64_SOURCE $(INCLUDES)
PROGRAMS += tgtd tgtadm
-TGTD_OBJS += tgtd.o mgmt.o target.o scsi.o sbc.o log.o driver.o util.o work.o
+TGTD_OBJS += tgtd.o mgmt.o target.o scsi.o sbc.o osd.o log.o driver.o util.o work.o
all: $(PROGRAMS)
diff --git a/usr/osd.c b/usr/osd.c
new file mode 100644
index 0000000..34a330f
--- /dev/null
+++ b/usr/osd.c
@@ -0,0 +1,182 @@
+/*
+ * Parse OSD command set, using functions in SPC as necessary.
+ *
+ * (C) 2006 Pete Wyckoff <pw at osc.edu>
+ */
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "list.h"
+#include "util.h"
+#include "tgtd.h"
+#include "scsi.h"
+
+#define VENDOR_ID "STGT"
+#define PRODUCT_ID "OSD"
+#define PRODUCT_REV "0"
+
+/*
+ * OSD-specific inquiry.
+ */
+int osd_inquiry(struct tgt_device *dev, int host_no, uint8_t *lun_buf,
+ uint8_t *scb, uint8_t *data, int *len)
+{
+ int result = SAM_STAT_CHECK_CONDITION;
+
+ /* EVPD means need a page code */
+ if ((scb[1] & 0x3) == 0 && scb[2] != 0)
+ return result;
+
+ dprintf("%x %x\n", scb[1], scb[2]);
+
+ data[0] = TYPE_OSD;
+ if (!dev)
+ data[0] = TYPE_NO_LUN;
+
+ if ((scb[1] & 0x1) == 0) {
+ /* evpd == 0, standard inquiry */
+ dprintf("standard inquiry\n");
+ data[2] = 5; /* modern version */
+ data[3] = 0x02; /* modern response format */
+ data[7] = 0x02; /* support command queueing */
+ memset(data + 8, 0x20, 28);
+ memcpy(data + 8,
+ VENDOR_ID, min_t(size_t, strlen(VENDOR_ID), 8));
+ memcpy(data + 16,
+ PRODUCT_ID, min_t(size_t, strlen(PRODUCT_ID), 16));
+ memcpy(data + 32,
+ PRODUCT_REV, min_t(size_t, strlen(PRODUCT_REV), 4));
+ *len = 36;
+ if (dev) {
+ data[58] = 0x03;
+ data[59] = 0x40; /* osd */
+ data[60] = 0x09;
+ data[61] = 0x60; /* iscsi */
+ data[62] = 0x03;
+ data[63] = 0x00; /* spc3 */
+ *len = 64;
+ }
+ data[4] = *len - 5; /* additional length */
+ result = SAM_STAT_GOOD;
+ } else {
+ /* request particular page code */
+ dprintf("page %x\n", scb[2]);
+ if (!dev)
+ return result;
+ data[1] = scb[2];
+ if (scb[2] == 0x0) {
+ /* supported VPD pages */
+ data[3] = 3;
+ data[4] = 0x0;
+ data[5] = 0x80;
+ data[6] = 0x83;
+ *len = 7;
+ result = SAM_STAT_GOOD;
+ } else if (scb[2] == 0x80) {
+ /* unit serial number " " */
+ data[3] = 4;
+ memset(data + 4, 0x20, 4);
+ *len = 8;
+ result = SAM_STAT_GOOD;
+ } else if (scb[2] == 0x83) {
+ /* device identification */
+ data[3] = SCSI_ID_LEN + 4;
+ data[4] = 0x1;
+ data[5] = 0x1;
+ data[7] = SCSI_ID_LEN;
+ if (dev)
+ memcpy(data + 8, dev->scsi_id, SCSI_ID_LEN);
+ *len = SCSI_ID_LEN + 8;
+ result = SAM_STAT_GOOD;
+ }
+ }
+
+ if (result != SAM_STAT_GOOD)
+ goto err;
+
+ *len = min_t(int, *len, scb[4]);
+
+ return SAM_STAT_GOOD;
+
+err:
+ *len = sense_data_build(data, 0x70, ILLEGAL_REQUEST,
+ 0x24, 0);
+ return SAM_STAT_CHECK_CONDITION;
+}
+
+int osd_cmd_perform(uint8_t *cdb, int *len, uint32_t datalen,
+ unsigned long *uaddr, uint8_t *rw, uint8_t *try_map,
+ uint64_t *offset, struct tgt_device *dev, int *async,
+ void *key, bkio_submit_t *submit)
+{
+ int ret = SAM_STAT_GOOD;
+ uint8_t *data = NULL;
+ uint16_t action;
+
+ switch (cdb[0]) {
+ /* there are other optional non-varlen commands */
+ case VARLEN_CDB:
+ dprintf("cdb[0] %x datalen %u\n", cdb[0], datalen);
+ if (cdb[7] != 200-8)
+ eprintf("request size %d wrong, should be 200\n",
+ cdb[7]+8);
+
+ action = (cdb[8] << 8) | cdb[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 = submit(dev, cdb, *rw, datalen, uaddr, *offset,
+ async, key);
+ if (ret == SAM_STAT_GOOD) {
+ *len = datalen;
+ } else {
+ data = get_zeroed_page();
+ *len = sense_data_build(data, 0x70,
+ ILLEGAL_REQUEST, 0x25,
+ 0);
+ }
+ break;
+ default:
+ eprintf("unknown service action 0x%04x\n", action);
+ }
+ break;
+ default:
+ eprintf("unknown command %x %u\n", cdb[0], datalen);
+ *len = 0;
+ break;
+ }
+
+ if (data)
+ *uaddr = (unsigned long) data;
+
+ return ret;
+}
+
diff --git a/usr/scsi.c b/usr/scsi.c
index 277924c..d102f5e 100644
--- a/usr/scsi.c
+++ b/usr/scsi.c
@@ -357,6 +357,10 @@ int scsi_cmd_perform(uint64_t nid, int lid, int host_no, uint8_t *scb,
result = block_cmd_perform(scb, len, datalen, uaddr, rw,
try_map, offset, dev, async, key,
submit);
+ else if (target_type == SCSI_TARGET_OSD)
+ result = osd_cmd_perform(scb, len, datalen, uaddr, rw,
+ try_map, offset, dev, async, key,
+ submit);
else
eprintf("unknown target type %d\n", target_type);
diff --git a/usr/scsi.h b/usr/scsi.h
index 154508d..20aa2a8 100644
--- a/usr/scsi.h
+++ b/usr/scsi.h
@@ -69,6 +69,7 @@
#define MODE_SENSE_10 0x5a
#define PERSISTENT_RESERVE_IN 0x5e
#define PERSISTENT_RESERVE_OUT 0x5f
+#define VARLEN_CDB 0x7f
#define REPORT_LUNS 0xa0
#define MOVE_MEDIUM 0xa5
#define EXCHANGE_MEDIUM 0xa6
@@ -87,6 +88,35 @@
#define SERVICE_ACTION_IN 0x9e
#define SAI_READ_CAPACITY_16 0x10
+/* 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
+
#define SAM_STAT_GOOD 0x00
#define SAM_STAT_CHECK_CONDITION 0x02
#define SAM_STAT_CONDITION_MET 0x04
@@ -127,6 +157,7 @@
#define TYPE_RAID 0x0c
#define TYPE_ENCLOSURE 0x0d
#define TYPE_RBC 0x0e
+#define TYPE_OSD 0x11
#define TYPE_NO_LUN 0x7f
#define MSG_SIMPLE_TAG 0x20
diff --git a/usr/tgtd.h b/usr/tgtd.h
index 262dc9c..3b75da3 100644
--- a/usr/tgtd.h
+++ b/usr/tgtd.h
@@ -125,6 +125,12 @@ int block_cmd_perform(uint8_t *scb, int *len, uint32_t datalen,
unsigned long *uaddr, uint8_t *rw, uint8_t *try_map,
uint64_t *offset, struct tgt_device *dev, int *async,
void *key, bkio_submit_t *submit);
+int osd_inquiry(struct tgt_device *dev, int host_no, uint8_t *lun_buf,
+ uint8_t *scb, uint8_t *data, int *len);
+int osd_cmd_perform(uint8_t *scb, int *len, uint32_t datalen,
+ unsigned long *uaddr, uint8_t *rw, uint8_t *try_map,
+ uint64_t *offset, struct tgt_device *dev, int *async,
+ void *key, bkio_submit_t *submit);
extern int sense_data_build(uint8_t *data, uint8_t res_code, uint8_t key,
uint8_t ascode, uint8_t ascodeq);
--
1.4.4.2
More information about the stgt
mailing list