[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