Burry devid port method, which was a gross hack.
Instead make ports provide wanted port and target IDs, and LUNs provide wanted LUN IDs. After that core Device ID VPD code only had to link all of them together and add relative port and port group numbers. LUN ID for iSCSI LUNs no longer created by CTL, but by ctld, and passed to CTL as "scsiname" LUN option. This makes LUNs to report the same set of IDs, independently from the port through which it is accessed, as required by SCSI specifications.
This commit is contained in:
parent
6c17b5fab9
commit
027e5269c9
@ -4293,7 +4293,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);
|
||||
@ -4325,6 +4329,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
|
||||
@ -4546,6 +4587,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);
|
||||
|
||||
@ -9624,39 +9666,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;
|
||||
@ -9675,15 +9707,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.
|
||||
@ -9693,112 +9716,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);
|
||||
|
@ -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
|
||||
|
@ -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 */
|
||||
};
|
||||
|
@ -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;
|
||||
|
@ -151,7 +151,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);
|
||||
@ -1948,8 +1947,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");
|
||||
@ -1994,7 +1994,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;
|
||||
|
||||
@ -2006,10 +2005,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);
|
||||
@ -2136,206 +2166,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)
|
||||
{
|
||||
|
@ -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 {
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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
|
||||
|
@ -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++;
|
||||
|
Loading…
Reference in New Issue
Block a user