summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/cam/ctl/ctl.c196
-rw-r--r--sys/cam/ctl/ctl_frontend.c47
-rw-r--r--sys/cam/ctl/ctl_frontend.h4
-rw-r--r--sys/cam/ctl/ctl_frontend_cam_sim.c3
-rw-r--r--sys/cam/ctl/ctl_frontend_iscsi.c236
-rw-r--r--sys/cam/ctl/ctl_private.h6
-rw-r--r--sys/cam/ctl/scsi_ctl.c14
-rw-r--r--usr.sbin/ctladm/ctladm.82
-rw-r--r--usr.sbin/ctld/kernel.c28
9 files changed, 196 insertions, 340 deletions
diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c
index 22da757..16a4793 100644
--- a/sys/cam/ctl/ctl.c
+++ b/sys/cam/ctl/ctl.c
@@ -4295,7 +4295,11 @@ ctl_alloc_lun(struct ctl_softc *ctl_softc, struct ctl_lun *ctl_lun,
{
struct ctl_lun *nlun, *lun;
struct ctl_port *port;
+ struct scsi_vpd_id_descriptor *desc;
+ struct scsi_vpd_id_t10 *t10id;
+ const char *scsiname, *vendor;
int lun_number, i, lun_malloced;
+ int devidlen, idlen1, idlen2, len;
if (be_lun == NULL)
return (EINVAL);
@@ -4327,6 +4331,43 @@ ctl_alloc_lun(struct ctl_softc *ctl_softc, struct ctl_lun *ctl_lun,
if (lun_malloced)
lun->flags = CTL_LUN_MALLOCED;
+ /* Generate LUN ID. */
+ devidlen = max(CTL_DEVID_MIN_LEN,
+ strnlen(be_lun->device_id, CTL_DEVID_LEN));
+ idlen1 = sizeof(*t10id) + devidlen;
+ len = sizeof(struct scsi_vpd_id_descriptor) + idlen1;
+ scsiname = ctl_get_opt(&be_lun->options, "scsiname");
+ if (scsiname != NULL) {
+ idlen2 = roundup2(strlen(scsiname) + 1, 4);
+ len += sizeof(struct scsi_vpd_id_descriptor) + idlen2;
+ }
+ lun->lun_devid = malloc(sizeof(struct ctl_devid) + len,
+ M_CTL, M_WAITOK | M_ZERO);
+ lun->lun_devid->len = len;
+ desc = (struct scsi_vpd_id_descriptor *)lun->lun_devid->data;
+ desc->proto_codeset = SVPD_ID_CODESET_ASCII;
+ desc->id_type = SVPD_ID_PIV | SVPD_ID_ASSOC_LUN | SVPD_ID_TYPE_T10;
+ desc->length = idlen1;
+ t10id = (struct scsi_vpd_id_t10 *)&desc->identifier[0];
+ memset(t10id->vendor, ' ', sizeof(t10id->vendor));
+ if ((vendor = ctl_get_opt(&be_lun->options, "vendor")) == NULL) {
+ strncpy((char *)t10id->vendor, CTL_VENDOR, sizeof(t10id->vendor));
+ } else {
+ strncpy(t10id->vendor, vendor,
+ min(sizeof(t10id->vendor), strlen(vendor)));
+ }
+ strncpy((char *)t10id->vendor_spec_id,
+ (char *)be_lun->device_id, devidlen);
+ if (scsiname != NULL) {
+ desc = (struct scsi_vpd_id_descriptor *)(&desc->identifier[0] +
+ desc->length);
+ desc->proto_codeset = SVPD_ID_CODESET_UTF8;
+ desc->id_type = SVPD_ID_PIV | SVPD_ID_ASSOC_LUN |
+ SVPD_ID_TYPE_SCSI_NAME;
+ desc->length = idlen2;
+ strlcpy(desc->identifier, scsiname, idlen2);
+ }
+
mtx_lock(&ctl_softc->ctl_lock);
/*
* See if the caller requested a particular LUN number. If so, see
@@ -4548,6 +4589,7 @@ ctl_free_lun(struct ctl_lun *lun)
lun->be_lun->lun_shutdown(lun->be_lun->be_lun);
mtx_destroy(&lun->lun_lock);
+ free(lun->lun_devid, M_CTL);
if (lun->flags & CTL_LUN_MALLOCED)
free(lun, M_CTL);
@@ -9626,39 +9668,29 @@ static int
ctl_inquiry_evpd_devid(struct ctl_scsiio *ctsio, int alloc_len)
{
struct scsi_vpd_device_id *devid_ptr;
- struct scsi_vpd_id_descriptor *desc, *desc1;
- struct scsi_vpd_id_descriptor *desc2, *desc3; /* for types 4h and 5h */
- struct scsi_vpd_id_t10 *t10id;
+ struct scsi_vpd_id_descriptor *desc;
struct ctl_softc *ctl_softc;
struct ctl_lun *lun;
struct ctl_port *port;
- char *val;
- int data_len, devid_len;
+ int data_len;
+ uint8_t proto;
ctl_softc = control_softc;
port = ctl_softc->ctl_ports[ctl_port_idx(ctsio->io_hdr.nexus.targ_port)];
-
- if (port->devid != NULL)
- return ((port->devid)(ctsio, alloc_len));
-
lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
- if (lun == NULL) {
- devid_len = CTL_DEVID_MIN_LEN;
- } else {
- devid_len = max(CTL_DEVID_MIN_LEN,
- strnlen(lun->be_lun->device_id, CTL_DEVID_LEN));
- }
-
data_len = sizeof(struct scsi_vpd_device_id) +
- sizeof(struct scsi_vpd_id_descriptor) +
- sizeof(struct scsi_vpd_id_t10) + devid_len +
- sizeof(struct scsi_vpd_id_descriptor) + CTL_WWPN_LEN +
- sizeof(struct scsi_vpd_id_descriptor) +
+ sizeof(struct scsi_vpd_id_descriptor) +
sizeof(struct scsi_vpd_id_rel_trgt_port_id) +
- sizeof(struct scsi_vpd_id_descriptor) +
+ sizeof(struct scsi_vpd_id_descriptor) +
sizeof(struct scsi_vpd_id_trgt_port_grp_id);
+ if (lun && lun->lun_devid)
+ data_len += lun->lun_devid->len;
+ if (port->port_devid)
+ data_len += port->port_devid->len;
+ if (port->target_devid)
+ data_len += port->target_devid->len;
ctsio->kern_data_ptr = malloc(data_len, M_CTL, M_WAITOK | M_ZERO);
devid_ptr = (struct scsi_vpd_device_id *)ctsio->kern_data_ptr;
@@ -9677,15 +9709,6 @@ ctl_inquiry_evpd_devid(struct ctl_scsiio *ctsio, int alloc_len)
ctsio->kern_rel_offset = 0;
ctsio->kern_sg_entries = 0;
- desc = (struct scsi_vpd_id_descriptor *)devid_ptr->desc_list;
- t10id = (struct scsi_vpd_id_t10 *)&desc->identifier[0];
- desc1 = (struct scsi_vpd_id_descriptor *)(&desc->identifier[0] +
- sizeof(struct scsi_vpd_id_t10) + devid_len);
- desc2 = (struct scsi_vpd_id_descriptor *)(&desc1->identifier[0] +
- CTL_WWPN_LEN);
- desc3 = (struct scsi_vpd_id_descriptor *)(&desc2->identifier[0] +
- sizeof(struct scsi_vpd_id_rel_trgt_port_id));
-
/*
* The control device is always connected. The disk device, on the
* other hand, may not be online all the time.
@@ -9695,112 +9718,69 @@ ctl_inquiry_evpd_devid(struct ctl_scsiio *ctsio, int alloc_len)
lun->be_lun->lun_type;
else
devid_ptr->device = (SID_QUAL_LU_OFFLINE << 5) | T_DIRECT;
-
devid_ptr->page_code = SVPD_DEVICE_ID;
-
scsi_ulto2b(data_len - 4, devid_ptr->length);
- /*
- * For Fibre channel,
- */
if (port->port_type == CTL_PORT_FC)
- {
- desc->proto_codeset = (SCSI_PROTO_FC << 4) |
- SVPD_ID_CODESET_ASCII;
- desc1->proto_codeset = (SCSI_PROTO_FC << 4) |
- SVPD_ID_CODESET_BINARY;
- }
+ proto = SCSI_PROTO_FC << 4;
+ else if (port->port_type == CTL_PORT_ISCSI)
+ proto = SCSI_PROTO_ISCSI << 4;
else
- {
- desc->proto_codeset = (SCSI_PROTO_SPI << 4) |
- SVPD_ID_CODESET_ASCII;
- desc1->proto_codeset = (SCSI_PROTO_SPI << 4) |
- SVPD_ID_CODESET_BINARY;
- }
- desc2->proto_codeset = desc3->proto_codeset = desc1->proto_codeset;
+ proto = SCSI_PROTO_SPI << 4;
+ desc = (struct scsi_vpd_id_descriptor *)devid_ptr->desc_list;
/*
* We're using a LUN association here. i.e., this device ID is a
* per-LUN identifier.
*/
- desc->id_type = SVPD_ID_PIV | SVPD_ID_ASSOC_LUN | SVPD_ID_TYPE_T10;
- desc->length = sizeof(*t10id) + devid_len;
- if (lun == NULL || (val = ctl_get_opt(&lun->be_lun->options,
- "vendor")) == NULL) {
- strncpy((char *)t10id->vendor, CTL_VENDOR, sizeof(t10id->vendor));
- } else {
- memset(t10id->vendor, ' ', sizeof(t10id->vendor));
- strncpy(t10id->vendor, val,
- min(sizeof(t10id->vendor), strlen(val)));
+ if (lun && lun->lun_devid) {
+ memcpy(desc, lun->lun_devid->data, lun->lun_devid->len);
+ desc = (struct scsi_vpd_id_descriptor *)((uint8_t *)desc +
+ lun->lun_devid->len);
}
/*
- * desc1 is for the WWPN which is a port asscociation.
+ * This is for the WWPN which is a port association.
*/
- desc1->id_type = SVPD_ID_PIV | SVPD_ID_ASSOC_PORT | SVPD_ID_TYPE_NAA;
- desc1->length = CTL_WWPN_LEN;
- /* XXX Call Reggie's get_WWNN func here then add port # to the end */
- /* For testing just create the WWPN */
-#if 0
- ddb_GetWWNN((char *)desc1->identifier);
-
- /* NOTE: if the port is 0 or 8 we don't want to subtract 1 */
- /* This is so Copancontrol will return something sane */
- if (ctsio->io_hdr.nexus.targ_port!=0 &&
- ctsio->io_hdr.nexus.targ_port!=8)
- desc1->identifier[7] += ctsio->io_hdr.nexus.targ_port-1;
- else
- desc1->identifier[7] += ctsio->io_hdr.nexus.targ_port;
-#endif
-
- be64enc(desc1->identifier, port->wwpn);
+ if (port->port_devid) {
+ memcpy(desc, port->port_devid->data, port->port_devid->len);
+ desc = (struct scsi_vpd_id_descriptor *)((uint8_t *)desc +
+ port->port_devid->len);
+ }
/*
- * desc2 is for the Relative Target Port(type 4h) identifier
+ * This is for the Relative Target Port(type 4h) identifier
*/
- desc2->id_type = SVPD_ID_PIV | SVPD_ID_ASSOC_PORT
- | SVPD_ID_TYPE_RELTARG;
- desc2->length = 4;
-//#if 0
- /* NOTE: if the port is 0 or 8 we don't want to subtract 1 */
- /* This is so Copancontrol will return something sane */
- if (ctsio->io_hdr.nexus.targ_port!=0 &&
- ctsio->io_hdr.nexus.targ_port!=8)
- desc2->identifier[3] = ctsio->io_hdr.nexus.targ_port - 1;
- else
- desc2->identifier[3] = ctsio->io_hdr.nexus.targ_port;
-//#endif
+ desc->proto_codeset = proto | SVPD_ID_CODESET_BINARY;
+ desc->id_type = SVPD_ID_PIV | SVPD_ID_ASSOC_PORT |
+ SVPD_ID_TYPE_RELTARG;
+ desc->length = 4;
+ scsi_ulto2b(ctsio->io_hdr.nexus.targ_port, &desc->identifier[2]);
+ desc = (struct scsi_vpd_id_descriptor *)(&desc->identifier[0] +
+ sizeof(struct scsi_vpd_id_rel_trgt_port_id));
/*
- * desc3 is for the Target Port Group(type 5h) identifier
+ * This is for the Target Port Group(type 5h) identifier
*/
- desc3->id_type = SVPD_ID_PIV | SVPD_ID_ASSOC_PORT
- | SVPD_ID_TYPE_TPORTGRP;
- desc3->length = 4;
+ desc->proto_codeset = proto | SVPD_ID_CODESET_BINARY;
+ desc->id_type = SVPD_ID_PIV | SVPD_ID_ASSOC_PORT |
+ SVPD_ID_TYPE_TPORTGRP;
+ desc->length = 4;
if (ctsio->io_hdr.nexus.targ_port < CTL_MAX_PORTS || ctl_is_single)
- desc3->identifier[3] = 1;
+ scsi_ulto2b(1, &desc->identifier[2]);
else
- desc3->identifier[3] = 2;
+ scsi_ulto2b(2, &desc->identifier[2]);
+ desc = (struct scsi_vpd_id_descriptor *)(&desc->identifier[0] +
+ sizeof(struct scsi_vpd_id_trgt_port_grp_id));
/*
- * If we've actually got a backend, copy the device id from the
- * per-LUN data. Otherwise, set it to all spaces.
+ * This is for the Target identifier
*/
- if (lun != NULL) {
- /*
- * Copy the backend's LUN ID.
- */
- strncpy((char *)t10id->vendor_spec_id,
- (char *)lun->be_lun->device_id, devid_len);
- } else {
- /*
- * No backend, set this to spaces.
- */
- memset(t10id->vendor_spec_id, 0x20, devid_len);
+ if (port->target_devid) {
+ memcpy(desc, port->target_devid->data, port->target_devid->len);
}
ctsio->scsi_status = SCSI_STATUS_OK;
-
ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
ctsio->be_move_done = ctl_config_move_done;
ctl_datamove((union ctl_io *)ctsio);
diff --git a/sys/cam/ctl/ctl_frontend.c b/sys/cam/ctl/ctl_frontend.c
index 210a85f..7af7a71 100644
--- a/sys/cam/ctl/ctl_frontend.c
+++ b/sys/cam/ctl/ctl_frontend.c
@@ -219,6 +219,11 @@ ctl_port_deregister(struct ctl_port *port)
ctl_pool_free(pool);
ctl_free_opts(&port->options);
+ free(port->port_devid, M_CTL);
+ port->port_devid = NULL;
+ free(port->target_devid, M_CTL);
+ port->target_devid = NULL;
+
bailout:
return (retval);
}
@@ -227,11 +232,49 @@ void
ctl_port_set_wwns(struct ctl_port *port, int wwnn_valid, uint64_t wwnn,
int wwpn_valid, uint64_t wwpn)
{
- if (wwnn_valid)
+ struct scsi_vpd_id_descriptor *desc;
+ int len, proto;
+
+ if (port->port_type == CTL_PORT_FC)
+ proto = SCSI_PROTO_FC << 4;
+ else if (port->port_type == CTL_PORT_ISCSI)
+ proto = SCSI_PROTO_ISCSI << 4;
+ else
+ proto = SCSI_PROTO_SPI << 4;
+
+ if (wwnn_valid) {
port->wwnn = wwnn;
- if (wwpn_valid)
+ free(port->target_devid, M_CTL);
+
+ len = sizeof(struct scsi_vpd_device_id) + CTL_WWPN_LEN;
+ port->target_devid = malloc(sizeof(struct ctl_devid) + len,
+ M_CTL, M_WAITOK | M_ZERO);
+ port->target_devid->len = len;
+ desc = (struct scsi_vpd_id_descriptor *)port->target_devid->data;
+ desc->proto_codeset = proto | SVPD_ID_CODESET_BINARY;
+ desc->id_type = SVPD_ID_PIV | SVPD_ID_ASSOC_TARGET |
+ SVPD_ID_TYPE_NAA;
+ desc->length = CTL_WWPN_LEN;
+ scsi_u64to8b(port->wwnn, desc->identifier);
+ }
+
+ if (wwpn_valid) {
port->wwpn = wwpn;
+
+ free(port->port_devid, M_CTL);
+
+ len = sizeof(struct scsi_vpd_device_id) + CTL_WWPN_LEN;
+ port->port_devid = malloc(sizeof(struct ctl_devid) + len,
+ M_CTL, M_WAITOK | M_ZERO);
+ port->port_devid->len = len;
+ desc = (struct scsi_vpd_id_descriptor *)port->port_devid->data;
+ desc->proto_codeset = proto | SVPD_ID_CODESET_BINARY;
+ desc->id_type = SVPD_ID_PIV | SVPD_ID_ASSOC_PORT |
+ SVPD_ID_TYPE_NAA;
+ desc->length = CTL_WWPN_LEN;
+ scsi_u64to8b(port->wwpn, desc->identifier);
+ }
}
void
diff --git a/sys/cam/ctl/ctl_frontend.h b/sys/cam/ctl/ctl_frontend.h
index dae9ce8..b246a22 100644
--- a/sys/cam/ctl/ctl_frontend.h
+++ b/sys/cam/ctl/ctl_frontend.h
@@ -53,7 +53,6 @@ typedef int (*targ_func_t)(void *arg, struct ctl_id targ_id);
typedef int (*lun_func_t)(void *arg, struct ctl_id targ_id, int lun_id);
typedef int (*fe_ioctl_t)(struct cdev *dev, u_long cmd, caddr_t addr, int flag,
struct thread *td);
-typedef int (*fe_devid_t)(struct ctl_scsiio *ctsio, int alloc_len);
#define CTL_FRONTEND_DECLARE(name, driver) \
static int name ## _modevent(module_t mod, int type, void *data) \
@@ -218,7 +217,6 @@ struct ctl_port {
void *onoff_arg; /* passed to CTL */
lun_func_t lun_enable; /* passed to CTL */
lun_func_t lun_disable; /* passed to CTL */
- fe_devid_t devid; /* passed to CTL */
void *targ_lun_arg; /* passed to CTL */
void (*fe_datamove)(union ctl_io *io); /* passed to CTL */
void (*fe_done)(union ctl_io *io); /* passed to CTL */
@@ -231,6 +229,8 @@ struct ctl_port {
uint64_t wwpn; /* set by CTL before online */
ctl_port_status status; /* used by CTL */
ctl_options_t options; /* passed to CTL */
+ struct ctl_devid *port_devid; /* passed to CTL */
+ struct ctl_devid *target_devid; /* passed to CTL */
STAILQ_ENTRY(ctl_port) fe_links; /* used by CTL */
STAILQ_ENTRY(ctl_port) links; /* used by CTL */
};
diff --git a/sys/cam/ctl/ctl_frontend_cam_sim.c b/sys/cam/ctl/ctl_frontend_cam_sim.c
index f72487c..72f8dd8 100644
--- a/sys/cam/ctl/ctl_frontend_cam_sim.c
+++ b/sys/cam/ctl/ctl_frontend_cam_sim.c
@@ -193,8 +193,7 @@ cfcs_init(void)
/* Company ID */ 0x5000000000000000ULL |
/* NL-Port */ 0x0300;
softc->wwpn = softc->wwnn + port->targ_port + 1;
- port->wwnn = softc->wwnn;
- port->wwpn = softc->wwpn;
+ ctl_port_set_wwns(port, true, softc->wwnn, true, softc->wwpn);
} else {
softc->wwnn = port->wwnn;
softc->wwpn = port->wwpn;
diff --git a/sys/cam/ctl/ctl_frontend_iscsi.c b/sys/cam/ctl/ctl_frontend_iscsi.c
index 6e4cdb3..c1a503c 100644
--- a/sys/cam/ctl/ctl_frontend_iscsi.c
+++ b/sys/cam/ctl/ctl_frontend_iscsi.c
@@ -155,7 +155,6 @@ static int cfiscsi_lun_disable(void *arg,
struct ctl_id target_id, int lun_id);
static int cfiscsi_ioctl(struct cdev *dev,
u_long cmd, caddr_t addr, int flag, struct thread *td);
-static int cfiscsi_devid(struct ctl_scsiio *ctsio, int alloc_len);
static void cfiscsi_datamove(union ctl_io *io);
static void cfiscsi_done(union ctl_io *io);
static uint32_t cfiscsi_map_lun(void *arg, uint32_t lun);
@@ -1952,8 +1951,9 @@ cfiscsi_ioctl_port_create(struct ctl_req *req)
struct cfiscsi_target *ct;
struct ctl_port *port;
const char *target, *alias, *tag;
+ struct scsi_vpd_id_descriptor *desc;
ctl_options_t opts;
- int retval;
+ int retval, len, idlen;
ctl_init_opts(&opts, req->num_args, req->kern_args);
target = ctl_get_opt(&opts, "cfiscsi_target");
@@ -1998,7 +1998,6 @@ cfiscsi_ioctl_port_create(struct ctl_req *req)
port->lun_enable = cfiscsi_lun_enable;
port->lun_disable = cfiscsi_lun_disable;
port->targ_lun_arg = ct;
- port->devid = cfiscsi_devid;
port->fe_datamove = cfiscsi_datamove;
port->fe_done = cfiscsi_done;
@@ -2010,10 +2009,41 @@ cfiscsi_ioctl_port_create(struct ctl_req *req)
port->options = opts;
STAILQ_INIT(&opts);
+ /* Generate Port ID. */
+ idlen = strlen(target) + strlen(",t,0x0001") + 1;
+ idlen = roundup2(idlen, 4);
+ len = sizeof(struct scsi_vpd_device_id) + idlen;
+ port->port_devid = malloc(sizeof(struct ctl_devid) + len,
+ M_CTL, M_WAITOK | M_ZERO);
+ port->port_devid->len = len;
+ desc = (struct scsi_vpd_id_descriptor *)port->port_devid->data;
+ desc->proto_codeset = (SCSI_PROTO_ISCSI << 4) | SVPD_ID_CODESET_UTF8;
+ desc->id_type = SVPD_ID_PIV | SVPD_ID_ASSOC_PORT |
+ SVPD_ID_TYPE_SCSI_NAME;
+ desc->length = idlen;
+ snprintf(desc->identifier, idlen, "%s,t,0x%4.4x",
+ target, port->virtual_port);
+
+ /* Generate Target ID. */
+ idlen = strlen(target) + 1;
+ idlen = roundup2(idlen, 4);
+ len = sizeof(struct scsi_vpd_device_id) + idlen;
+ port->target_devid = malloc(sizeof(struct ctl_devid) + len,
+ M_CTL, M_WAITOK | M_ZERO);
+ port->target_devid->len = len;
+ desc = (struct scsi_vpd_id_descriptor *)port->target_devid->data;
+ desc->proto_codeset = (SCSI_PROTO_ISCSI << 4) | SVPD_ID_CODESET_UTF8;
+ desc->id_type = SVPD_ID_PIV | SVPD_ID_ASSOC_TARGET |
+ SVPD_ID_TYPE_SCSI_NAME;
+ desc->length = idlen;
+ strlcpy(desc->identifier, target, idlen);
+
retval = ctl_port_register(port, /*master_SC*/ 1);
if (retval != 0) {
ctl_free_opts(&port->options);
cfiscsi_target_release(ct);
+ free(port->port_devid, M_CFISCSI);
+ free(port->target_devid, M_CFISCSI);
req->status = CTL_LUN_ERROR;
snprintf(req->error_str, sizeof(req->error_str),
"ctl_frontend_register() failed with error %d", retval);
@@ -2140,206 +2170,6 @@ cfiscsi_ioctl(struct cdev *dev,
return (0);
}
-static int
-cfiscsi_devid(struct ctl_scsiio *ctsio, int alloc_len)
-{
- struct cfiscsi_session *cs;
- struct scsi_vpd_device_id *devid_ptr;
- struct scsi_vpd_id_descriptor *desc, *desc1, *desc2, *desc3, *desc4;
- struct scsi_vpd_id_descriptor *desc5;
- struct scsi_vpd_id_t10 *t10id;
- struct ctl_lun *lun;
- const struct icl_pdu *request;
- int i, ret;
- char *val;
- size_t data_len, devid_len, wwnn_len, wwpn_len, lun_name_len;
-
- lun = (struct ctl_lun *)ctsio->io_hdr.ctl_private[CTL_PRIV_LUN].ptr;
- request = ctsio->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr;
- cs = PDU_SESSION(request);
-
- wwpn_len = strlen(cs->cs_target->ct_name);
- wwpn_len += strlen(",t,0x0001");
- wwpn_len += 1; /* '\0' */
- if ((wwpn_len % 4) != 0)
- wwpn_len += (4 - (wwpn_len % 4));
-
- wwnn_len = strlen(cs->cs_target->ct_name);
- wwnn_len += 1; /* '\0' */
- if ((wwnn_len % 4) != 0)
- wwnn_len += (4 - (wwnn_len % 4));
-
- if (lun == NULL) {
- devid_len = CTL_DEVID_MIN_LEN;
- lun_name_len = 0;
- } else {
- devid_len = max(CTL_DEVID_MIN_LEN,
- strnlen(lun->be_lun->device_id, CTL_DEVID_LEN));
- lun_name_len = strlen(cs->cs_target->ct_name);
- lun_name_len += strlen(",lun,XXXXXXXX");
- lun_name_len += 1; /* '\0' */
- if ((lun_name_len % 4) != 0)
- lun_name_len += (4 - (lun_name_len % 4));
- }
-
- data_len = sizeof(struct scsi_vpd_device_id) +
- sizeof(struct scsi_vpd_id_descriptor) +
- sizeof(struct scsi_vpd_id_t10) + devid_len +
- sizeof(struct scsi_vpd_id_descriptor) + lun_name_len +
- sizeof(struct scsi_vpd_id_descriptor) + wwnn_len +
- sizeof(struct scsi_vpd_id_descriptor) + wwpn_len +
- sizeof(struct scsi_vpd_id_descriptor) +
- sizeof(struct scsi_vpd_id_rel_trgt_port_id) +
- sizeof(struct scsi_vpd_id_descriptor) +
- sizeof(struct scsi_vpd_id_trgt_port_grp_id);
-
- ctsio->kern_data_ptr = malloc(data_len, M_CTL, M_WAITOK | M_ZERO);
- devid_ptr = (struct scsi_vpd_device_id *)ctsio->kern_data_ptr;
- ctsio->kern_sg_entries = 0;
-
- if (data_len < alloc_len) {
- ctsio->residual = alloc_len - data_len;
- ctsio->kern_data_len = data_len;
- ctsio->kern_total_len = data_len;
- } else {
- ctsio->residual = 0;
- ctsio->kern_data_len = alloc_len;
- ctsio->kern_total_len = alloc_len;
- }
- ctsio->kern_data_resid = 0;
- ctsio->kern_rel_offset = 0;
- ctsio->kern_sg_entries = 0;
-
- desc = (struct scsi_vpd_id_descriptor *)devid_ptr->desc_list;
- t10id = (struct scsi_vpd_id_t10 *)&desc->identifier[0];
- desc1 = (struct scsi_vpd_id_descriptor *)(&desc->identifier[0] +
- sizeof(struct scsi_vpd_id_t10) + devid_len);
- desc2 = (struct scsi_vpd_id_descriptor *)(&desc1->identifier[0] +
- lun_name_len);
- desc3 = (struct scsi_vpd_id_descriptor *)(&desc2->identifier[0] +
- wwnn_len);
- desc4 = (struct scsi_vpd_id_descriptor *)(&desc3->identifier[0] +
- wwpn_len);
- desc5 = (struct scsi_vpd_id_descriptor *)(&desc4->identifier[0] +
- sizeof(struct scsi_vpd_id_rel_trgt_port_id));
-
- if (lun != NULL)
- devid_ptr->device = (SID_QUAL_LU_CONNECTED << 5) |
- lun->be_lun->lun_type;
- else
- devid_ptr->device = (SID_QUAL_LU_OFFLINE << 5) | T_DIRECT;
-
- devid_ptr->page_code = SVPD_DEVICE_ID;
-
- scsi_ulto2b(data_len - 4, devid_ptr->length);
-
- /*
- * We're using a LUN association here. i.e., this device ID is a
- * per-LUN identifier.
- */
- desc->proto_codeset = (SCSI_PROTO_ISCSI << 4) | SVPD_ID_CODESET_ASCII;
- desc->id_type = SVPD_ID_PIV | SVPD_ID_ASSOC_LUN | SVPD_ID_TYPE_T10;
- desc->length = sizeof(*t10id) + devid_len;
- if (lun == NULL || (val = ctl_get_opt(&lun->be_lun->options,
- "vendor")) == NULL) {
- strncpy((char *)t10id->vendor, CTL_VENDOR, sizeof(t10id->vendor));
- } else {
- memset(t10id->vendor, ' ', sizeof(t10id->vendor));
- strncpy(t10id->vendor, val,
- min(sizeof(t10id->vendor), strlen(val)));
- }
-
- /*
- * If we've actually got a backend, copy the device id from the
- * per-LUN data. Otherwise, set it to all spaces.
- */
- if (lun != NULL) {
- /*
- * Copy the backend's LUN ID.
- */
- strncpy((char *)t10id->vendor_spec_id,
- (char *)lun->be_lun->device_id, devid_len);
- } else {
- /*
- * No backend, set this to spaces.
- */
- memset(t10id->vendor_spec_id, 0x20, devid_len);
- }
-
- /*
- * desc1 is for the unique LUN name.
- *
- * XXX: According to SPC-3, LUN must report the same ID through
- * all the ports. The code below, however, reports the
- * ID only via iSCSI.
- */
- desc1->proto_codeset = (SCSI_PROTO_ISCSI << 4) | SVPD_ID_CODESET_UTF8;
- desc1->id_type = SVPD_ID_PIV | SVPD_ID_ASSOC_LUN |
- SVPD_ID_TYPE_SCSI_NAME;
- desc1->length = lun_name_len;
- if (lun != NULL) {
- /*
- * Find the per-target LUN number.
- */
- for (i = 0; i < CTL_MAX_LUNS; i++) {
- if (cs->cs_target->ct_luns[i] == lun->lun)
- break;
- }
- KASSERT(i < CTL_MAX_LUNS,
- ("lun %jd not found", (uintmax_t)lun->lun));
- ret = snprintf(desc1->identifier, lun_name_len, "%s,lun,%d",
- cs->cs_target->ct_name, i);
- KASSERT(ret > 0 && ret <= lun_name_len, ("bad snprintf"));
- } else {
- KASSERT(lun_name_len == 0, ("no lun, but lun_name_len != 0"));
- }
-
- /*
- * desc2 is for the Target Name.
- */
- desc2->proto_codeset = (SCSI_PROTO_ISCSI << 4) | SVPD_ID_CODESET_UTF8;
- desc2->id_type = SVPD_ID_PIV | SVPD_ID_ASSOC_TARGET |
- SVPD_ID_TYPE_SCSI_NAME;
- desc2->length = wwnn_len;
- snprintf(desc2->identifier, wwnn_len, "%s", cs->cs_target->ct_name);
-
- /*
- * desc3 is for the WWPN which is a port asscociation.
- */
- desc3->proto_codeset = (SCSI_PROTO_ISCSI << 4) | SVPD_ID_CODESET_UTF8;
- desc3->id_type = SVPD_ID_PIV | SVPD_ID_ASSOC_PORT |
- SVPD_ID_TYPE_SCSI_NAME;
- desc3->length = wwpn_len;
- snprintf(desc3->identifier, wwpn_len, "%s,t,0x%4.4x",
- cs->cs_target->ct_name, cs->cs_portal_group_tag);
-
- /*
- * desc3 is for the Relative Target Port(type 4h) identifier
- */
- desc4->proto_codeset = (SCSI_PROTO_ISCSI << 4) | SVPD_ID_CODESET_BINARY;
- desc4->id_type = SVPD_ID_PIV | SVPD_ID_ASSOC_PORT |
- SVPD_ID_TYPE_RELTARG;
- desc4->length = 4;
- desc4->identifier[3] = 1;
-
- /*
- * desc4 is for the Target Port Group(type 5h) identifier
- */
- desc5->proto_codeset = (SCSI_PROTO_ISCSI << 4) | SVPD_ID_CODESET_BINARY;
- desc5->id_type = SVPD_ID_PIV | SVPD_ID_ASSOC_PORT |
- SVPD_ID_TYPE_TPORTGRP;
- desc5->length = 4;
- desc5->identifier[3] = 1;
-
- ctsio->scsi_status = SCSI_STATUS_OK;
-
- ctsio->io_hdr.flags |= CTL_FLAG_ALLOCATED;
- ctsio->be_move_done = ctl_config_move_done;
- ctl_datamove((union ctl_io *)ctsio);
-
- return (CTL_RETVAL_COMPLETE);
-}
-
static void
cfiscsi_target_hold(struct cfiscsi_target *ct)
{
diff --git a/sys/cam/ctl/ctl_private.h b/sys/cam/ctl/ctl_private.h
index 3b2069f..fff05e7 100644
--- a/sys/cam/ctl/ctl_private.h
+++ b/sys/cam/ctl/ctl_private.h
@@ -367,6 +367,11 @@ struct ctl_per_res_info {
#define CTL_PR_ALL_REGISTRANTS 0xFFFF
#define CTL_PR_NO_RESERVATION 0xFFF0
+struct ctl_devid {
+ int len;
+ uint8_t data[];
+};
+
/*
* For report target port groups.
*/
@@ -402,6 +407,7 @@ struct ctl_lun {
uint16_t pr_res_idx;
uint8_t res_type;
uint8_t write_buffer[524288];
+ struct ctl_devid *lun_devid;
};
typedef enum {
diff --git a/sys/cam/ctl/scsi_ctl.c b/sys/cam/ctl/scsi_ctl.c
index 4a81abf..8d38b02 100644
--- a/sys/cam/ctl/scsi_ctl.c
+++ b/sys/cam/ctl/scsi_ctl.c
@@ -1732,10 +1732,9 @@ ctlfe_onoffline(void *arg, int online)
* using with the frontend code so it's reported
* accurately.
*/
- bus_softc->port.wwnn =
- ccb->knob.xport_specific.fc.wwnn;
- bus_softc->port.wwpn =
- ccb->knob.xport_specific.fc.wwpn;
+ ctl_port_set_wwns(&bus_softc->port,
+ true, ccb->knob.xport_specific.fc.wwnn,
+ true, ccb->knob.xport_specific.fc.wwpn);
set_wwnn = 1;
#else /* RANDOM_WWNN */
/*
@@ -1751,10 +1750,9 @@ ctlfe_onoffline(void *arg, int online)
bus_softc->port.wwpn;
set_wwnn = 1;
} else {
- bus_softc->port.wwnn =
- ccb->knob.xport_specific.fc.wwnn;
- bus_softc->port.wwpn =
- ccb->knob.xport_specific.fc.wwpn;
+ ctl_port_set_wwns(&bus_softc->port,
+ true, ccb->knob.xport_specific.fc.wwnn,
+ true, ccb->knob.xport_specific.fc.wwpn);
}
#endif /* RANDOM_WWNN */
diff --git a/usr.sbin/ctladm/ctladm.8 b/usr.sbin/ctladm/ctladm.8
index 1699022..a832dbb 100644
--- a/usr.sbin/ctladm/ctladm.8
+++ b/usr.sbin/ctladm/ctladm.8
@@ -945,6 +945,8 @@ Specifies LUN vendor string up to 8 chars.
Specifies LUN product string up to 16 chars.
.It Va revision
Specifies LUN revision string up to 4 chars.
+.It Va scsiname
+Specifies LUN SCSI name string.
.It Va unmap
Set to "on", enables UNMAP support for the LUN.
.El
diff --git a/usr.sbin/ctld/kernel.c b/usr.sbin/ctld/kernel.c
index 0225691..3c958c8 100644
--- a/usr.sbin/ctld/kernel.c
+++ b/usr.sbin/ctld/kernel.c
@@ -113,7 +113,6 @@ struct cctl_lun {
char *serial_number;
char *device_id;
char *cfiscsi_target;
- char *cfiscsi_target_alias;
int cfiscsi_lun;
STAILQ_HEAD(,cctl_lun_nv) attr_list;
STAILQ_ENTRY(cctl_lun) links;
@@ -230,9 +229,6 @@ cctl_end_element(void *user_data, const char *name)
} else if (strcmp(name, "cfiscsi_target") == 0) {
cur_lun->cfiscsi_target = str;
str = NULL;
- } else if (strcmp(name, "cfiscsi_target_alias") == 0) {
- cur_lun->cfiscsi_target_alias = str;
- str = NULL;
} else if (strcmp(name, "cfiscsi_lun") == 0) {
cur_lun->cfiscsi_lun = strtoul(str, NULL, 0);
} else if (strcmp(name, "lun") == 0) {
@@ -640,17 +636,6 @@ kernel_lun_add(struct lun *lun)
assert(lo != NULL);
}
- if (lun->l_target->t_alias != NULL) {
- lo = lun_option_find(lun, "cfiscsi_target_alias");
- if (lo != NULL) {
- lun_option_set(lo, lun->l_target->t_alias);
- } else {
- lo = lun_option_new(lun, "cfiscsi_target_alias",
- lun->l_target->t_alias);
- assert(lo != NULL);
- }
- }
-
asprintf(&tmp, "%d", lun->l_lun);
if (tmp == NULL)
log_errx(1, "asprintf");
@@ -664,6 +649,19 @@ kernel_lun_add(struct lun *lun)
assert(lo != NULL);
}
+ asprintf(&tmp, "%s,lun,%d", lun->l_target->t_name, lun->l_lun);
+ if (tmp == NULL)
+ log_errx(1, "asprintf");
+ lo = lun_option_find(lun, "scsiname");
+ if (lo != NULL) {
+ lun_option_set(lo, tmp);
+ free(tmp);
+ } else {
+ lo = lun_option_new(lun, "scsiname", tmp);
+ free(tmp);
+ assert(lo != NULL);
+ }
+
num_options = 0;
TAILQ_FOREACH(lo, &lun->l_options, lo_next)
num_options++;
OpenPOWER on IntegriCloud