diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c index ebf547d6a83f..4a5e40acbac3 100644 --- a/sys/cam/ctl/ctl.c +++ b/sys/cam/ctl/ctl.c @@ -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); diff --git a/sys/cam/ctl/ctl_frontend.c b/sys/cam/ctl/ctl_frontend.c index 210a85f922ed..7af7a71b555d 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 dae9ce8ea82a..b246a22fb602 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 2cea264ebcbc..0e454014b60b 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 e1d1982dabce..da2ba3f927eb 100644 --- a/sys/cam/ctl/ctl_frontend_iscsi.c +++ b/sys/cam/ctl/ctl_frontend_iscsi.c @@ -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) { diff --git a/sys/cam/ctl/ctl_private.h b/sys/cam/ctl/ctl_private.h index 3b2069fa3d49..fff05e71ad5f 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 4a81abf519ee..8d38b024c094 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 73846a96a866..536d456cf9ab 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 ecc43cf929df..dc07591bfb9b 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++;