[Stgt-devel] [PATCH 3/4] block/primary separation

Pete Wyckoff pw
Mon Jan 22 20:04:31 CET 2007


Separate block commands from primary commands.

Signed-off-by: Pete Wyckoff <pw at osc.edu>
---
 usr/Makefile |    2 +-
 usr/sbc.c    |  307 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 usr/scsi.c   |  339 ++++++++--------------------------------------------------
 usr/tgtd.h   |    5 +
 4 files changed, 359 insertions(+), 294 deletions(-)

diff --git a/usr/Makefile b/usr/Makefile
index 80b8f8f..7b828e0 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 log.o driver.o util.o work.o
+TGTD_OBJS += tgtd.o mgmt.o target.o scsi.o sbc.o log.o driver.o util.o work.o
 
 all: $(PROGRAMS)
 
diff --git a/usr/sbc.c b/usr/sbc.c
new file mode 100644
index 0000000..a727924
--- /dev/null
+++ b/usr/sbc.c
@@ -0,0 +1,307 @@
+/*
+ * SCSI block command processing
+ *
+ * (C) 2004 - 2005 FUJITA Tomonori <tomof at acm.org>
+ * (C) 2005 Mike Christie <michaelc at cs.wisc.edu>
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <syscall.h>
+#include <unistd.h>
+#include <linux/fs.h>
+
+#include "list.h"
+#include "util.h"
+#include "tgtd.h"
+#include "driver.h"
+#include "scsi.h"
+
+#define BLK_SHIFT	9
+
+static int insert_disconnect_pg(uint8_t *ptr)
+{
+	unsigned char disconnect_pg[] = {0x02, 0x0e, 0x80, 0x80, 0x00, 0x0a, 0x00, 0x00,
+                                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
+
+	memcpy(ptr, disconnect_pg, sizeof(disconnect_pg));
+	return sizeof(disconnect_pg);
+}
+
+static int insert_caching_pg(uint8_t *ptr)
+{
+	unsigned char caching_pg[] = {0x08, 0x12, 0x14, 0x00, 0xff, 0xff, 0x00, 0x00,
+				      0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0x00, 0x00,
+				      0x00, 0x00, 0x00, 0x00};
+
+	memcpy(ptr, caching_pg, sizeof(caching_pg));
+	return sizeof(caching_pg);
+}
+
+static int insert_ctrl_m_pg(uint8_t *ptr)
+{
+	unsigned char ctrl_m_pg[] = {0x0a, 0x0a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
+				     0x00, 0x00, 0x02, 0x4b};
+
+	memcpy(ptr, ctrl_m_pg, sizeof(ctrl_m_pg));
+	return sizeof(ctrl_m_pg);
+}
+
+static int insert_iec_m_pg(uint8_t *ptr)
+{
+	unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0x00, 0x00, 0x00, 0x00,
+				    0x00, 0x00, 0x00, 0x00, 0x00};
+
+	memcpy(ptr, iec_m_pg, sizeof(iec_m_pg));
+	return sizeof(iec_m_pg);
+}
+
+static int insert_format_m_pg(uint8_t *ptr)
+{
+	unsigned char format_m_pg[] = {0x03, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+				       0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00,
+				       0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00};
+	memcpy(ptr, format_m_pg, sizeof(format_m_pg));
+	return sizeof(format_m_pg);
+}
+
+static int insert_geo_m_pg(uint8_t *ptr, uint64_t sec)
+{
+	unsigned char geo_m_pg[] = {0x04, 0x16, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
+				    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+				    0x00, 0x00, 0x00, 0x00, 0x3a, 0x98, 0x00, 0x00};
+	uint32_t ncyl, *p;
+
+	/* assume 0xff heads, 15krpm. */
+	memcpy(ptr, geo_m_pg, sizeof(geo_m_pg));
+	ncyl = sec >> 14; /* 256 * 64 */
+	p = (uint32_t *)(ptr + 1);
+	*p = *p | __cpu_to_be32(ncyl);
+	return sizeof(geo_m_pg);
+}
+
+int mode_sense(struct tgt_device *dev, uint8_t *scb, uint8_t *data, int *len)
+{
+	int result = SAM_STAT_GOOD;
+	uint8_t pcode = scb[2] & 0x3f;
+	uint64_t size;
+
+	*len = 4;
+	size = dev->size >> BLK_SHIFT;
+
+	if ((scb[1] & 0x8))
+		data[3] = 0;
+	else {
+		data[3] = 8;
+		*len += 8;
+		*(uint32_t *)(data + 4) = (size >> 32) ?
+			__cpu_to_be32(0xffffffff) : __cpu_to_be32(size);
+		*(uint32_t *)(data + 8) = __cpu_to_be32(1 << BLK_SHIFT);
+	}
+
+	switch (pcode) {
+	case 0x0:
+		break;
+	case 0x2:
+		*len += insert_disconnect_pg(data + *len);
+		break;
+	case 0x3:
+		*len += insert_format_m_pg(data + *len);
+		break;
+	case 0x4:
+		*len += insert_geo_m_pg(data + *len, size);
+		break;
+	case 0x8:
+		*len += insert_caching_pg(data + *len);
+		break;
+	case 0xa:
+		*len += insert_ctrl_m_pg(data + *len);
+		break;
+	case 0x1c:
+		*len += insert_iec_m_pg(data + *len);
+		break;
+	case 0x3f:
+		*len += insert_disconnect_pg(data + *len);
+		*len += insert_format_m_pg(data + *len);
+		*len += insert_geo_m_pg(data + *len, size);
+		*len += insert_caching_pg(data + *len);
+		*len += insert_ctrl_m_pg(data + *len);
+		*len += insert_iec_m_pg(data + *len);
+		break;
+	default:
+		result = SAM_STAT_CHECK_CONDITION;
+		*len = sense_data_build(data, 0x70, ILLEGAL_REQUEST,
+					0x24, 0);
+	}
+
+	data[0] = *len - 1;
+
+	return result;
+}
+
+static int read_capacity(struct tgt_device *dev, uint8_t *scb, uint8_t *p, int *len)
+{
+	uint32_t *data = (uint32_t *) p;
+	uint64_t size;
+
+	if (!(scb[8] & 0x1) & (scb[2] | scb[3] | scb[4] | scb[5])) {
+		*len = sense_data_build(p, 0x70, ILLEGAL_REQUEST,
+					0x24, 0);
+		return SAM_STAT_CHECK_CONDITION;
+	}
+
+	size = dev->size >> BLK_SHIFT;
+
+	data[0] = (size >> 32) ?
+		__cpu_to_be32(0xffffffff) : __cpu_to_be32(size - 1);
+	data[1] = __cpu_to_be32(1U << BLK_SHIFT);
+	*len = 8;
+
+	return SAM_STAT_GOOD;
+}
+
+static int sync_cache(struct tgt_device *dev, uint8_t *data, int *len)
+{
+	int err;
+
+	err = fsync(dev->fd);
+
+	switch (err) {
+	case EROFS:
+	case EINVAL:
+	case EBADF:
+	case EIO:
+		/*
+		 * is this the right sense code?
+		 * what should I put for the asc/ascq?
+		 */
+		*len = sense_data_build(data, 0x70, ILLEGAL_REQUEST, 0, 0);
+		return SAM_STAT_CHECK_CONDITION;
+	default:
+		*len = 0;
+		return SAM_STAT_GOOD;
+	}
+}
+
+static int sevice_action(struct tgt_device *dev, uint8_t *scb, uint8_t *p, int *len)
+{
+	uint32_t *data = (uint32_t *) p;
+	uint64_t *data64, size;
+
+	size = dev->size >> BLK_SHIFT;
+
+	data64 = (uint64_t *) data;
+	data64[0] = __cpu_to_be64(size - 1);
+	data[2] = __cpu_to_be32(1UL << BLK_SHIFT);
+
+	*len = 12;
+
+	return SAM_STAT_GOOD;
+}
+
+static uint64_t scsi_cmd_data_offset(uint8_t *scb)
+{
+	uint64_t off;
+
+	switch (scb[0]) {
+	case READ_6:
+	case WRITE_6:
+		off = ((scb[1] & 0x1f) << 16) + (scb[2] << 8) + scb[3];
+		break;
+	case READ_10:
+	case WRITE_10:
+	case WRITE_VERIFY:
+		off = __be32_to_cpu(*(uint32_t *) &scb[2]);
+		break;
+	case READ_16:
+	case WRITE_16:
+		off = __be64_to_cpu(*(uint64_t *) &scb[2]);
+		break;
+	default:
+		off = 0;
+		break;
+	}
+
+	return off << BLK_SHIFT;
+}
+
+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 result = SAM_STAT_GOOD;
+	uint8_t *data = NULL;
+
+	switch (scb[0]) {
+	case READ_CAPACITY:
+		data = get_zeroed_page();
+		result = read_capacity(dev, scb, data, len);
+		break;
+	case MODE_SENSE:
+		data = get_zeroed_page();
+		result = mode_sense(dev, scb, data, len);
+		break;
+	case SERVICE_ACTION_IN:
+		data = get_zeroed_page();
+		result = sevice_action(dev, scb, data, len);
+		break;
+	case SYNCHRONIZE_CACHE:
+		data = get_zeroed_page();
+		result = sync_cache(dev, data, len);
+		break;
+	case START_STOP:
+	case VERIFY:
+		*len = 0;
+		break;
+	case READ_6:
+	case READ_10:
+	case READ_16:
+	case WRITE_6:
+	case WRITE_10:
+	case WRITE_16:
+	case WRITE_VERIFY:
+		switch (scb[0]) {
+		case READ_6:
+		case READ_10:
+		case READ_16:
+			*rw = READ;
+			break;
+		case WRITE_6:
+		case WRITE_10:
+		case WRITE_16:
+		case WRITE_VERIFY:
+			*rw = WRITE;
+			break;
+		}
+
+		*offset = scsi_cmd_data_offset(scb);
+		result = submit(dev, scb, *rw, datalen, uaddr, *offset, async, key);
+		if (result == SAM_STAT_GOOD) {
+			*len = datalen;
+			*try_map = 1;
+		} else {
+			*rw = READ;
+			*offset = 0;
+			data = get_zeroed_page();
+			*len = sense_data_build(data, 0x70, ILLEGAL_REQUEST,
+						0x25, 0);
+		}
+		break;
+	default:
+		eprintf("unknown command %x %u\n", scb[0], datalen);
+		*len = 0;
+		break;
+	}
+
+	if (data)
+		*uaddr = (unsigned long) data;
+
+	return result;
+}
+
diff --git a/usr/scsi.c b/usr/scsi.c
index 82ddb0d..277924c 100644
--- a/usr/scsi.c
+++ b/usr/scsi.c
@@ -43,126 +43,6 @@ int sense_data_build(uint8_t *data, uint8_t res_code, uint8_t key,
 	return len + 8;
 }
 
-static int insert_disconnect_pg(uint8_t *ptr)
-{
-	unsigned char disconnect_pg[] = {0x02, 0x0e, 0x80, 0x80, 0x00, 0x0a, 0x00, 0x00,
-                                         0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
-
-	memcpy(ptr, disconnect_pg, sizeof(disconnect_pg));
-	return sizeof(disconnect_pg);
-}
-
-static int insert_caching_pg(uint8_t *ptr)
-{
-	unsigned char caching_pg[] = {0x08, 0x12, 0x14, 0x00, 0xff, 0xff, 0x00, 0x00,
-				      0xff, 0xff, 0xff, 0xff, 0x80, 0x14, 0x00, 0x00,
-				      0x00, 0x00, 0x00, 0x00};
-
-	memcpy(ptr, caching_pg, sizeof(caching_pg));
-	return sizeof(caching_pg);
-}
-
-static int insert_ctrl_m_pg(uint8_t *ptr)
-{
-	unsigned char ctrl_m_pg[] = {0x0a, 0x0a, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
-				     0x00, 0x00, 0x02, 0x4b};
-
-	memcpy(ptr, ctrl_m_pg, sizeof(ctrl_m_pg));
-	return sizeof(ctrl_m_pg);
-}
-
-static int insert_iec_m_pg(uint8_t *ptr)
-{
-	unsigned char iec_m_pg[] = {0x1c, 0xa, 0x08, 0x00, 0x00, 0x00, 0x00,
-				    0x00, 0x00, 0x00, 0x00, 0x00};
-
-	memcpy(ptr, iec_m_pg, sizeof(iec_m_pg));
-	return sizeof(iec_m_pg);
-}
-
-static int insert_format_m_pg(uint8_t *ptr)
-{
-	unsigned char format_m_pg[] = {0x03, 0x16, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-				       0x00, 0x00, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00,
-				       0x00, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x00, 0x00};
-	memcpy(ptr, format_m_pg, sizeof(format_m_pg));
-	return sizeof(format_m_pg);
-}
-
-static int insert_geo_m_pg(uint8_t *ptr, uint64_t sec)
-{
-	unsigned char geo_m_pg[] = {0x04, 0x16, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00,
-				    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-				    0x00, 0x00, 0x00, 0x00, 0x3a, 0x98, 0x00, 0x00};
-	uint32_t ncyl, *p;
-
-	/* assume 0xff heads, 15krpm. */
-	memcpy(ptr, geo_m_pg, sizeof(geo_m_pg));
-	ncyl = sec >> 14; /* 256 * 64 */
-	p = (uint32_t *)(ptr + 1);
-	*p = *p | __cpu_to_be32(ncyl);
-	return sizeof(geo_m_pg);
-}
-
-static int mode_sense(struct tgt_device *dev, uint8_t *scb, uint8_t *data, int *len)
-{
-	int result = SAM_STAT_GOOD;
-	uint8_t pcode = scb[2] & 0x3f;
-	uint64_t size;
-
-	*len = 4;
-	size = dev->size >> BLK_SHIFT;
-
-	if ((scb[1] & 0x8))
-		data[3] = 0;
-	else {
-		data[3] = 8;
-		*len += 8;
-		*(uint32_t *)(data + 4) = (size >> 32) ?
-			__cpu_to_be32(0xffffffff) : __cpu_to_be32(size);
-		*(uint32_t *)(data + 8) = __cpu_to_be32(1 << BLK_SHIFT);
-	}
-
-	switch (pcode) {
-	case 0x0:
-		break;
-	case 0x2:
-		*len += insert_disconnect_pg(data + *len);
-		break;
-	case 0x3:
-		*len += insert_format_m_pg(data + *len);
-		break;
-	case 0x4:
-		*len += insert_geo_m_pg(data + *len, size);
-		break;
-	case 0x8:
-		*len += insert_caching_pg(data + *len);
-		break;
-	case 0xa:
-		*len += insert_ctrl_m_pg(data + *len);
-		break;
-	case 0x1c:
-		*len += insert_iec_m_pg(data + *len);
-		break;
-	case 0x3f:
-		*len += insert_disconnect_pg(data + *len);
-		*len += insert_format_m_pg(data + *len);
-		*len += insert_geo_m_pg(data + *len, size);
-		*len += insert_caching_pg(data + *len);
-		*len += insert_ctrl_m_pg(data + *len);
-		*len += insert_iec_m_pg(data + *len);
-		break;
-	default:
-		result = SAM_STAT_CHECK_CONDITION;
-		*len = sense_data_build(data, 0x70, ILLEGAL_REQUEST,
-					0x24, 0);
-	}
-
-	data[0] = *len - 1;
-
-	return result;
-}
-
 #define VENDOR_ID	"IET"
 #define PRODUCT_ID	"VIRTUAL-DISK"
 #define PRODUCT_REV	"0"
@@ -331,50 +211,6 @@ static int report_luns(int lid, struct list_head *dev_list, uint8_t *lun_buf,
 	return fn(dev_list, lun_buf, scb, p, len);
 }
 
-static int read_capacity(struct tgt_device *dev, uint8_t *scb, uint8_t *p, int *len)
-{
-	uint32_t *data = (uint32_t *) p;
-	uint64_t size;
-
-	if (!(scb[8] & 0x1) & (scb[2] | scb[3] | scb[4] | scb[5])) {
-		*len = sense_data_build(p, 0x70, ILLEGAL_REQUEST,
-					0x24, 0);
-		return SAM_STAT_CHECK_CONDITION;
-	}
-
-	size = dev->size >> BLK_SHIFT;
-
-	data[0] = (size >> 32) ?
-		__cpu_to_be32(0xffffffff) : __cpu_to_be32(size - 1);
-	data[1] = __cpu_to_be32(1U << BLK_SHIFT);
-	*len = 8;
-
-	return SAM_STAT_GOOD;
-}
-
-static int sync_cache(struct tgt_device *dev, uint8_t *data, int *len)
-{
-	int err;
-
-	err = fsync(dev->fd);
-
-	switch (err) {
-	case EROFS:
-	case EINVAL:
-	case EBADF:
-	case EIO:
-		/*
-		 * is this the right sense code?
-		 * what should I put for the asc/ascq?
-		 */
-		*len = sense_data_build(data, 0x70, ILLEGAL_REQUEST, 0, 0);
-		return SAM_STAT_CHECK_CONDITION;
-	default:
-		*len = 0;
-		return SAM_STAT_GOOD;
-	}
-}
-
 /*
  * TODO: We always assume autosense.
  */
@@ -385,70 +221,6 @@ static int request_sense(uint8_t *data, int* len)
 	return SAM_STAT_GOOD;
 }
 
-static int sevice_action(struct tgt_device *dev, uint8_t *scb, uint8_t *p, int *len)
-{
-	uint32_t *data = (uint32_t *) p;
-	uint64_t *data64, size;
-
-	size = dev->size >> BLK_SHIFT;
-
-	data64 = (uint64_t *) data;
-	data64[0] = __cpu_to_be64(size - 1);
-	data[2] = __cpu_to_be32(1UL << BLK_SHIFT);
-
-	*len = 12;
-
-	return SAM_STAT_GOOD;
-}
-
-static uint64_t scsi_cmd_data_offset(uint8_t *scb)
-{
-	uint64_t off;
-
-	switch (scb[0]) {
-	case READ_6:
-	case WRITE_6:
-		off = ((scb[1] & 0x1f) << 16) + (scb[2] << 8) + scb[3];
-		break;
-	case READ_10:
-	case WRITE_10:
-	case WRITE_VERIFY:
-		off = __be32_to_cpu(*(uint32_t *) &scb[2]);
-		break;
-	case READ_16:
-	case WRITE_16:
-		off = __be64_to_cpu(*(uint64_t *) &scb[2]);
-		break;
-	default:
-		off = 0;
-		break;
-	}
-
-	return off << BLK_SHIFT;
-}
-
-static int scsi_cmd_rw(uint8_t *scb, uint8_t *rw)
-{
-	int is_alloc = 0;
-
-	switch (scb[0]) {
-	case READ_6:
-	case READ_10:
-	case READ_16:
-		*rw = READ;
-		break;
-	case WRITE_6:
-	case WRITE_10:
-	case WRITE_16:
-	case WRITE_VERIFY:
-		*rw = WRITE;
-		break;
-	default:
-		is_alloc = 1;
-	}
-	return is_alloc;
-}
-
 #define        TGT_INVALID_DEV_ID      ~0ULL
 
 static uint64_t __scsi_get_devid(uint8_t *p)
@@ -478,22 +250,35 @@ uint64_t scsi_get_devid(int lid, uint8_t *p)
 	return fn(p);
 }
 
-int scsi_cmd_perform(uint64_t nid, int lid, int host_no, uint8_t *pdu,
+void *get_zeroed_page(void)
+{
+	int ret;
+	void *page;
+
+	ret = posix_memalign(&page, PAGE_SIZE, PAGE_SIZE);
+	if (ret) {
+		eprintf("out of memory");
+		exit(1);
+	}
+	memset(page, 0, PAGE_SIZE);
+	return page;
+}
+
+/*
+ * Handle generic SPC activities, and call to target type-specific handler.
+ */
+int scsi_cmd_perform(uint64_t nid, int lid, int host_no, uint8_t *scb,
 		     int *len, uint32_t datalen, unsigned long *uaddr, uint8_t *rw,
 		     uint8_t *try_map, uint64_t *offset, uint8_t *lun_buf,
 		     struct tgt_device *dev, struct list_head *dev_list, int *async,
 		     void *key, bkio_submit_t *submit, enum scsi_target_type target_type)
 {
 	int result = SAM_STAT_GOOD;
-	uint8_t *data = NULL, *scb = pdu;
+	uint8_t *data = NULL;
 
 	dprintf("%x %u\n", scb[0], datalen);
 
 	*async = *offset = 0;
-	if (scsi_cmd_rw(scb, rw)) {
-		data = valloc(PAGE_SIZE);
-		memset(data, 0, PAGE_SIZE);
-	}
 
 	if (!dev) {
 		switch (scb[0]) {
@@ -502,11 +287,7 @@ int scsi_cmd_perform(uint64_t nid, int lid, int host_no, uint8_t *pdu,
 		case REPORT_LUNS:
 			break;
 		default:
-			*offset = 0;
-			if (!data) {
-				data = valloc(PAGE_SIZE);
-				memset(data, 0, PAGE_SIZE);
-			}
+			data = get_zeroed_page();
 			*len = sense_data_build(data, 0x70, ILLEGAL_REQUEST,
 						0x25, 0);
 			result = SAM_STAT_CHECK_CONDITION;
@@ -526,91 +307,63 @@ int scsi_cmd_perform(uint64_t nid, int lid, int host_no, uint8_t *pdu,
 				/* these commands are always allowed. */
 				break;
 			default:
-			*offset = 0;
-			if (data) {
-				free(data);
-				data = NULL;
-			}
-
-			*len = 0;
-			result = SAM_STAT_RESERVATION_CONFLICT;
-			goto out;
+				*len = 0;
+				result = SAM_STAT_RESERVATION_CONFLICT;
+				goto out;
 			}
 		}
 	}
 
+	/*
+	 * Generic SPC commands
+	 */
 	switch (scb[0]) {
 	case INQUIRY:
+		data = get_zeroed_page();
 		result = inquiry(lid, dev, host_no, lun_buf, scb, data, len);
-		break;
+		goto out;
 	case REPORT_LUNS:
 		*len = datalen;
+		data = get_zeroed_page();
 		result = report_luns(lid, dev_list, lun_buf, scb, data, len);
-		break;
-	case READ_CAPACITY:
-		result = read_capacity(dev, scb, data, len);
-		break;
-	case MODE_SENSE:
-		result = mode_sense(dev, scb, data, len);
-		break;
+		goto out;
 	case REQUEST_SENSE:
+		data = get_zeroed_page();
 		result = request_sense(data, len);
-		break;
-	case SERVICE_ACTION_IN:
-		result = sevice_action(dev, scb, data, len);
-		break;
-	case SYNCHRONIZE_CACHE:
-		result = sync_cache(dev, data, len);
-		break;
-	case START_STOP:
+		goto out;
 	case TEST_UNIT_READY:
-	case VERIFY:
 		*len = 0;
-		break;
-	case READ_6:
-	case READ_10:
-	case READ_16:
-	case WRITE_6:
-	case WRITE_10:
-	case WRITE_16:
-	case WRITE_VERIFY:
-		*offset = scsi_cmd_data_offset(scb);
-		result = submit(dev, scb, *rw, datalen, uaddr, *offset, async, key);
-		if (result == SAM_STAT_GOOD) {
-			*len = datalen;
-			*try_map = 1;
-		} else {
-			*rw = READ;
-			*offset = 0;
-			if (!data)
-				data = valloc(PAGE_SIZE);
-			*len = sense_data_build(data, 0x70, ILLEGAL_REQUEST,
-						0x25, 0);
-		}
-		break;
+		goto out;
 	case RESERVE:
 	case RESERVE_10:
 		result = device_reserve(nid, dev->lun, nid);
 		if (result)
 			result = SAM_STAT_RESERVATION_CONFLICT;
 		*len = 0;
-		break;
+		goto out;
 	case RELEASE:
 	case RELEASE_10:
 		result = device_release(nid, dev->lun, host_no, 0);
 		if (result)
 			result = SAM_STAT_RESERVATION_CONFLICT;
 		*len = 0;
-		break;
-	default:
-		eprintf("unknown command %x %u\n", scb[0], datalen);
-		*len = 0;
-		break;
+		goto out;
 	}
 
+	/*
+	 * Specific device command set
+	 */
+	if (target_type == SCSI_TARGET_SBC)
+		result = block_cmd_perform(scb, len, datalen, uaddr, rw,
+		                           try_map, offset, dev, async, key,
+					   submit);
+	else
+		eprintf("unknown target type %d\n", target_type);
+
 out:
 	if (data)
 		*uaddr = (unsigned long) data;
 
 	return result;
 }
+
diff --git a/usr/tgtd.h b/usr/tgtd.h
index 090f84a..262dc9c 100644
--- a/usr/tgtd.h
+++ b/usr/tgtd.h
@@ -114,12 +114,17 @@ extern void target_mgmt_request(uint64_t nid, uint64_t req_id, int function,
 extern void target_cmd_io_done(void *key, int result);
 
 extern uint64_t scsi_get_devid(int lid, uint8_t *pdu);
+extern void *get_zeroed_page(void);
 extern int scsi_cmd_perform(uint64_t nid, int lid, int host_no, uint8_t *pdu, int *len,
 			    uint32_t datalen, unsigned long *uaddr, uint8_t *rw,
 			    uint8_t *try_map, uint64_t *offset, uint8_t *lun,
 			    struct tgt_device *dev, struct list_head *dev_list,
 			    int *async, void *key, bkio_submit_t *submit,
 			    enum scsi_target_type target_type);
+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);
 
 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