[PATCH] bind device type to LUN

Hannes Reinecke hare
Fri Jun 15 06:22:44 CEST 2007


The device type should be bound to the LUN, not the target.
This way we can easily support different LUN types on the
same target.

Signed-off-by: Hannes Reinecke <hare at suse.de>
---
 usr/mgmt.c   |    2 +-
 usr/mmc.c    |    2 +-
 usr/osd.c    |    2 +-
 usr/sbc.c    |    4 +-
 usr/scsi.c   |    7 +++-
 usr/spc.c    |   11 ++++--
 usr/spt.c    |    5 ++-
 usr/target.c |  111 ++++++++++++++++++++++++++++++++++++++++------------------
 usr/target.h |    3 --
 usr/tgtd.h   |   60 ++++++++++++++++++-------------
 usr/tgtif.c  |    2 +-
 11 files changed, 135 insertions(+), 74 deletions(-)

diff --git a/usr/mgmt.c b/usr/mgmt.c
index 9cda2fa..19ab738 100644
--- a/usr/mgmt.c
+++ b/usr/mgmt.c
@@ -167,7 +167,7 @@ static int device_mgmt(int lld_no, struc
 
 	switch (req->op) {
 	case OP_NEW:
-		err = tgt_device_create(req->tid, req->lun, params);
+		err = tgt_device_create(req->tid, req->lun, params, req->target_type);
 		break;
 	case OP_DELETE:
 		err = tgt_device_destroy(req->tid, req->lun);
diff --git a/usr/mmc.c b/usr/mmc.c
index a8aced5..ea0bd02 100644
--- a/usr/mmc.c
+++ b/usr/mmc.c
@@ -49,7 +49,7 @@ static int mmc_rw(int host_no, struct sc
 	int ret;
 
 	cmd->offset = (scsi_rw_offset(cmd->scb) << MMC_BLK_SHIFT);
-	ret = cmd->c_target->bst->bs_cmd_submit(cmd);
+	ret = cmd->dev->bst->bs_cmd_submit(cmd);
 	if (ret) {
 		cmd->offset = 0;
 		cmd->len = 0;
diff --git a/usr/osd.c b/usr/osd.c
index ac33168..d09af60 100644
--- a/usr/osd.c
+++ b/usr/osd.c
@@ -48,7 +48,7 @@ static int osd_varlen_cdb(int host_no, s
 	}
 
 /* 	return SAM_STAT_GOOD; */
-	return cmd->c_target->bst->bs_cmd_submit(cmd);
+	return cmd->dev->bst->bs_cmd_submit(cmd);
 }
 
 static int osd_lu_init(struct scsi_lu *lu)
diff --git a/usr/sbc.c b/usr/sbc.c
index 2924cc6..dcf4799 100644
--- a/usr/sbc.c
+++ b/usr/sbc.c
@@ -67,7 +67,7 @@ static int sbc_rw(int host_no, struct sc
 	}
 
 	cmd->offset = (scsi_rw_offset(cmd->scb) << BLK_SHIFT);
-	ret = cmd->c_target->bst->bs_cmd_submit(cmd);
+	ret = cmd->dev->bst->bs_cmd_submit(cmd);
 	if (ret) {
 		key = HARDWARE_ERROR;
 		asc = 0;
@@ -173,7 +173,7 @@ static int sbc_sync_cache(int host_no, s
 		goto sense;
 	}
 
-	ret = cmd->c_target->bst->bs_cmd_submit(cmd);
+	ret = cmd->dev->bst->bs_cmd_submit(cmd);
 	switch (ret) {
 	case EROFS:
 	case EINVAL:
diff --git a/usr/scsi.c b/usr/scsi.c
index 50e2080..6f1b23b 100644
--- a/usr/scsi.c
+++ b/usr/scsi.c
@@ -119,6 +119,11 @@ uint64_t scsi_rw_offset(uint8_t *scb)
 int scsi_cmd_perform(int host_no, struct scsi_cmd *cmd)
 {
 	unsigned char op = cmd->scb[0];
-	return cmd->c_target->dev_type_template.ops[op].cmd_perform(host_no, cmd);
+	if (!cmd->dev) {
+		cmd->len = 0;
+		sense_data_build(cmd, NOT_READY, 0x44, 0); /* Internal target failure */
+		return SAM_STAT_CHECK_CONDITION;
+	}
+	return cmd->dev->dev_type_template.ops[op].cmd_perform(host_no, cmd);
 }
 
diff --git a/usr/spc.c b/usr/spc.c
index 99a7df3..6028969 100644
--- a/usr/spc.c
+++ b/usr/spc.c
@@ -43,8 +43,8 @@ int spc_inquiry(int host_no, struct scsi
 	int len, ret = SAM_STAT_CHECK_CONDITION;
 	uint8_t *data;
 	uint8_t *scb = cmd->scb;
-	unsigned char device_type = cmd->c_target->dev_type_template.type;
 	unsigned char key = ILLEGAL_REQUEST, asc = 0x24;
+	uint8_t devtype = 0;
 
 	if (((scb[1] & 0x3) == 0x3) || (!(scb[1] & 0x3) && scb[2]))
 		goto sense;
@@ -59,11 +59,16 @@ int spc_inquiry(int host_no, struct scsi
 
 	dprintf("%x %x\n", scb[1], scb[2]);
 
+	if (cmd->dev) {
+		devtype = (cmd->dev->attrs->qualifier & 0x7 ) << 5;
+		devtype |= (cmd->dev->attrs->device_type & 0x1f);
+	}
+
 	if (!(scb[1] & 0x3) && cmd->dev) {
 		int i;
 		uint16_t *desc;
 
-		data[0] = device_type;
+		data[0] = devtype;
 		data[1] = (cmd->dev->attrs->is_removable) ? 0x80 : 0;
 		data[2] = 5;	/* SPC-3 */
 		data[3] = 0x42;
@@ -91,7 +96,7 @@ int spc_inquiry(int host_no, struct scsi
 	} else if (scb[1] & 0x1) {
 		/* EVPD bit set */
 		if (scb[2] == 0x0) {
-			data[0] = device_type;
+			data[0] = devtype;
 			data[1] = 0x0;
 			data[3] = 3;
 			data[4] = 0x0;
diff --git a/usr/spt.c b/usr/spt.c
index fe2a848..561d7d4 100644
--- a/usr/spt.c
+++ b/usr/spt.c
@@ -67,8 +67,9 @@ static int spt_cmd_perform(int host_no,
 	struct device_type_operations *ops;
 
 	if (!cmd->dev) {
-		ops = cmd->c_target->dev_type_template.ops;
-		return ops[cmd->scb[0]].cmd_perform(host_no, cmd);
+		cmd->len = 0;
+		sense_data_build(cmd, NOT_READY, 0x44, 0); /* Internal target failure */
+		return SAM_STAT_CHECK_CONDITION;
 	}
 
 	ret = spt_sg_perform(cmd);
diff --git a/usr/target.c b/usr/target.c
index 5b74be1..6f8feb0 100644
--- a/usr/target.c
+++ b/usr/target.c
@@ -174,7 +174,7 @@ static int tgt_device_path_update(struct
 	if (!path)
 		return TGTADM_NOMEM;
 
-	err = target->bst->bs_open(lu, path, &dev_fd, &size);
+	err = lu->bst->bs_open(lu, path, &dev_fd, &size);
 	if (err) {
 		free(path);
 		return TGTADM_INVALID_REQUEST;
@@ -206,7 +206,7 @@ __device_lookup(int tid, uint64_t lun, s
 	return lu;
 }
 
-int tgt_device_create(int tid, uint64_t lun, char *args)
+int tgt_device_create(int tid, uint64_t lun, char *args, int l_type)
 {
 	char *p;
 	int err;
@@ -233,10 +233,37 @@ int tgt_device_create(int tid, uint64_t
 		return TGTADM_INVALID_REQUEST;
 	p++;
 
-	lu = zalloc(sizeof(*lu) + target->bst->bs_datasize);
+	if (l_type == TYPE_SPT)
+		lu = zalloc(sizeof(*lu) + sg_bst.bs_datasize);
+	else
+		lu = zalloc(sizeof(*lu) + target->bst->bs_datasize);
+
 	if (!lu)
 		return TGTADM_NOMEM;
 
+	switch (l_type) {
+	case TYPE_DISK:
+		lu->dev_type_template = sbc_template;
+		lu->bst = target->bst;
+		break;
+	case TYPE_ROM:
+		lu->dev_type_template = mmc_template;
+		lu->bst = target->bst;
+		break;
+	case TYPE_OSD:
+		lu->dev_type_template = osd_template;
+		lu->bst = target->bst;
+		break;
+	case TYPE_SPT:
+		lu->dev_type_template = spt_template;
+		lu->bst = &sg_bst;
+		break;
+	default:
+		dprintf("Unknown device type %d\n", l_type);
+		free(lu);
+		return TGTADM_INVALID_REQUEST;
+	}
+
 	err = tgt_device_path_update(target, lu, p);
 	if (err) {
 		free(lu);
@@ -248,14 +275,17 @@ int tgt_device_create(int tid, uint64_t
 
 	tgt_cmd_queue_init(&lu->cmd_queue);
 
-	if (target->dev_type_template.lu_init)
-		err = target->dev_type_template.lu_init(lu);
+	if (lu->dev_type_template.lu_init)
+		err = lu->dev_type_template.lu_init(lu);
 
 	if (!err) {
 		snprintf(lu->attrs->scsi_id, sizeof(lu->attrs->scsi_id),
 			 "deadbeaf%d:%" PRIu64, tid, lun);
 		snprintf(lu->attrs->scsi_sn, sizeof(lu->attrs->scsi_sn),
 			 "beaf%d%" PRIu64, tid, lun);
+
+ 		lu->attrs->device_type = l_type;
+ 		lu->attrs->qualifier = 0x0;
 	}
 
 	list_for_each_entry(pos, &target->device_list, device_siblings) {
@@ -285,12 +315,12 @@ int tgt_device_destroy(int tid, uint64_t
 	if (!list_empty(&lu->cmd_queue.queue) || lu->cmd_queue.active_cmd)
 		return TGTADM_LUN_ACTIVE;
 
-	err = target->dev_type_template.lu_exit(lu);
+	err = lu->dev_type_template.lu_exit(lu);
 
 	free(lu->path);
 	list_del(&lu->device_siblings);
 
-	target->bst->bs_close(lu);
+	lu->bst->bs_close(lu);
 	free(lu);
 	return err;
 }
@@ -361,8 +391,8 @@ int tgt_device_update(int tid, uint64_t
 		return TGTADM_NO_LUN;
 	}
 
-	if (target->dev_type_template.lu_config)
-		err = target->dev_type_template.lu_config(lu, params);
+	if (lu->dev_type_template.lu_config)
+		err = lu->dev_type_template.lu_config(lu, params);
 
 	return err;
 }
@@ -1087,6 +1117,41 @@ static char *print_disksize(uint64_t siz
 	return buf;
 }
 
+static struct {
+	int value;
+	char *name;
+} disk_type_names[] = {
+	{ TYPE_DISK, "disk" },
+	{ TYPE_TAPE, "tape" },
+	{ TYPE_PRINTER, "printer" },
+	{ TYPE_PROCESSOR, "processor" },
+	{ TYPE_WORM, "worm" },
+	{ TYPE_SCANNER, "scanner" },
+	{ TYPE_MOD, "optical" },
+	{ TYPE_MEDIUM_CHANGER, "changer" },
+	{ TYPE_COMM, "comm" },
+	{ TYPE_RAID, "raid" },
+	{ TYPE_ENCLOSURE, "enc" },
+	{ TYPE_RBC, "rbc" },
+	{ TYPE_OSD, "osd" },
+	{ TYPE_NO_LUN, "No LUN" }
+};
+
+static char *print_type(int type)
+{
+	int i;
+	char *name = NULL;
+
+	for (i = 0; i < ARRAY_SIZE(disk_type_names); i++) {
+		if (disk_type_names[i].value == type) {
+			name = disk_type_names[i].name;
+			break;
+		}
+	}
+	return name;
+}
+
+
 int tgt_target_show_all(char *buf, int rest)
 {
 	int total = 0, max = rest;
@@ -1099,12 +1164,10 @@ int tgt_target_show_all(char *buf, int r
 		shprintf(total, buf, rest,
 			 "Target %d: %s\n"
 			 _TAB1 "System information:\n"
-			 _TAB2 "Type: %s\n"
 			 _TAB2 "Driver: %s\n"
 			 _TAB2 "Status: %s\n",
 			 target->tid,
 			 target->name,
-			 target->dev_type_template.name,
 			 tgt_drivers[target->lid]->name,
 			 target_state_name(target->target_state));
 
@@ -1121,11 +1184,13 @@ int tgt_target_show_all(char *buf, int r
 		list_for_each_entry(lu, &target->device_list, device_siblings)
 			shprintf(total, buf, rest,
 				 _TAB2 "LUN: %" PRIu64 "\n"
+ 				 _TAB3 "Type: %s\n"
 				 _TAB3 "SCSI ID: %s\n"
 				 _TAB3 "SCSI SN: %s\n"
 				 _TAB3 "Size: %s\n"
 				 _TAB3 "Backing store: %s\n",
 				 lu->lun,
+ 				 print_type(lu->attrs->device_type),
 				 lu->attrs->scsi_id,
 				 lu->attrs->scsi_sn,
 				 print_disksize(lu->size),
@@ -1204,24 +1269,6 @@ int tgt_target_create(int lld, int tid,
 	if (!target)
 		return TGTADM_NOMEM;
 
-	switch (t_type) {
-	case TYPE_DISK:
-		target->dev_type_template = sbc_template;
-		break;
-	case TYPE_ROM:
-		target->dev_type_template = mmc_template;
-		break;
-	case TYPE_OSD:
-		target->dev_type_template = osd_template;
-		break;
-	case TYPE_SPT:
-		target->dev_type_template = spt_template;
-		break;
-	default:
-		free(target);
-		return TGTADM_INVALID_REQUEST;
-	}
-
 	target->name = strdup(targetname);
 	if (!target->name) {
 		free(target);
@@ -1240,11 +1287,7 @@ int tgt_target_create(int lld, int tid,
 
 	INIT_LIST_HEAD(&target->device_list);
 
-	/* FIXME */
-	if (t_type == TYPE_SPT)
-		target->bst = &sg_bst;
-	else
-		target->bst = tgt_drivers[lld]->default_bst;
+	target->bst = tgt_drivers[lld]->default_bst;
 
 	target->target_state = SCSI_TARGET_RUNNING;
 	target->lid = lld;
diff --git a/usr/target.h b/usr/target.h
index a5f1faa..688f0e6 100644
--- a/usr/target.h
+++ b/usr/target.h
@@ -41,9 +41,6 @@ struct target {
 	struct list_head acl_list;
 
 	struct tgt_account account;
-
-	/* we don't use a pointer because a lld could change this. */
-	struct device_type_template dev_type_template;
 };
 
 struct it_nexus {
diff --git a/usr/tgtd.h b/usr/tgtd.h
index 7b64655..9412da1 100644
--- a/usr/tgtd.h
+++ b/usr/tgtd.h
@@ -40,12 +40,41 @@ struct lu_phy_attr {
 	char product_rev[5];
 	uint16_t version_desc[VERSION_DESCRIPTOR_LEN];
 
+	char device_type;	/* Peripheral device type */
+	char qualifier;		/* Peripheral Qualifier */
 	char is_removable;	/* Removable media */
 	char online;		/* Logical Unit online ? */
 	char reset;		/* Power-on or reset has occured */
 	char sense_format;	/* Descrptor format sense data supported */
 };
 
+struct scsi_lu;
+struct scsi_cmd;
+
+struct device_type_operations {
+	int (*cmd_perform)(int host_no, struct scsi_cmd *cmd);
+};
+
+struct device_type_template {
+	unsigned char type;
+	char *name;
+	char *pid;
+
+	int (*lu_init)(struct scsi_lu *lu);
+	int (*lu_exit)(struct scsi_lu *lu);
+	int (*lu_config)(struct scsi_lu *lu, char *arg);
+
+	struct device_type_operations ops[256];
+};
+
+struct backingstore_template {
+	int bs_datasize;
+	int (*bs_open)(struct scsi_lu *dev, char *path, int *fd, uint64_t *size);
+	void (*bs_close)(struct scsi_lu *dev);
+	int (*bs_cmd_submit)(struct scsi_cmd *cmd);
+	int (*bs_cmd_done) (struct scsi_cmd *cmd);
+};
+
 struct scsi_lu {
 	int fd;
 	uint64_t addr; /* persistent mapped address */
@@ -62,6 +91,11 @@ struct scsi_lu {
 
 	uint64_t reserve_id;
 
+	/* we don't use a pointer because a lld could change this. */
+	struct device_type_template dev_type_template;
+
+	struct backingstore_template *bst;
+
 	/* TODO: needs a structure for lots of device parameters */
 	struct lu_phy_attr *attrs;
 };
@@ -110,14 +144,6 @@ struct mgmt_req {
 	uint64_t itn_id;
 };
 
-struct backingstore_template {
-	int bs_datasize;
-	int (*bs_open)(struct scsi_lu *dev, char *path, int *fd, uint64_t *size);
-	void (*bs_close)(struct scsi_lu *dev);
-	int (*bs_cmd_submit)(struct scsi_cmd *cmd);
-	int (*bs_cmd_done) (struct scsi_cmd *cmd);
-};
-
 #ifdef USE_KERNEL
 extern int kreq_init(void);
 #else
@@ -127,27 +153,11 @@ static inline int kreq_init(void)	\
 }
 #endif
 
-struct device_type_operations {
-	int (*cmd_perform)(int host_no, struct scsi_cmd *cmd);
-};
-
-struct device_type_template {
-	unsigned char type;
-	char *name;
-	char *pid;
-
-	int (*lu_init)(struct scsi_lu *lu);
-	int (*lu_exit)(struct scsi_lu *lu);
-	int (*lu_config)(struct scsi_lu *lu, char *arg);
-
-	struct device_type_operations ops[256];
-};
-
 extern int kspace_send_tsk_mgmt_res(struct mgmt_req *mreq);
 extern int kspace_send_cmd_res(uint64_t nid, int result, struct scsi_cmd *);
 
 extern int ipc_init(void);
-extern int tgt_device_create(int tid, uint64_t lun, char *args);
+extern int tgt_device_create(int tid, uint64_t lun, char *args, int l_type);
 extern int tgt_device_destroy(int tid, uint64_t lun);
 extern int tgt_device_update(int tid, uint64_t dev_id, char *name);
 extern int device_reserve(struct scsi_cmd *cmd);
diff --git a/usr/tgtif.c b/usr/tgtif.c
index caa0eeb..c8c9817 100644
--- a/usr/tgtif.c
+++ b/usr/tgtif.c
@@ -162,7 +162,7 @@ static void kern_queue_cmd(struct tgt_ev
 	kcmd->host_no = ev->p.cmd_req.host_no;
 	cmd = &kcmd->scmd;
 	cmd->cmd_itn_id = ev->p.cmd_req.itn_id;
-	cmd->scb = (char *)cmd + sizeof(*cmd);
+	cmd->scb = (unsigned char *)cmd + sizeof(*cmd);
 	memcpy(cmd->scb, ev->p.cmd_req.scb, scb_len);
 	cmd->scb_len = scb_len;
 	memcpy(cmd->lun, ev->p.cmd_req.lun, sizeof(cmd->lun));
-- 
1.4.3.2




More information about the stgt mailing list