diff --git a/sys/cam/ctl/ctl.c b/sys/cam/ctl/ctl.c index 622aeee9c2f0..66e00f9cf639 100644 --- a/sys/cam/ctl/ctl.c +++ b/sys/cam/ctl/ctl.c @@ -2237,6 +2237,43 @@ ctl_sbuf_printf_esc(struct sbuf *sb, char *str) return (retval); } +static void +ctl_id_sbuf(struct ctl_devid *id, struct sbuf *sb) +{ + struct scsi_vpd_id_descriptor *desc; + int i; + + if (id == NULL || id->len < 4) + return; + desc = (struct scsi_vpd_id_descriptor *)id->data; + switch (desc->id_type & SVPD_ID_TYPE_MASK) { + case SVPD_ID_TYPE_T10: + sbuf_printf(sb, "t10."); + break; + case SVPD_ID_TYPE_EUI64: + sbuf_printf(sb, "eui."); + break; + case SVPD_ID_TYPE_NAA: + sbuf_printf(sb, "naa."); + break; + case SVPD_ID_TYPE_SCSI_NAME: + break; + } + switch (desc->proto_codeset & SVPD_ID_CODESET_MASK) { + case SVPD_ID_CODESET_BINARY: + for (i = 0; i < desc->length; i++) + sbuf_printf(sb, "%02x", desc->identifier[i]); + break; + case SVPD_ID_CODESET_ASCII: + sbuf_printf(sb, "%.*s", (int)desc->length, + (char *)desc->identifier); + break; + case SVPD_ID_CODESET_UTF8: + sbuf_printf(sb, "%s", (char *)desc->identifier); + break; + } +} + static int ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct thread *td) @@ -3288,6 +3325,7 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, struct ctl_port *port; struct ctl_lun_list *list; struct ctl_option *opt; + int j; list = (struct ctl_lun_list *)addr; @@ -3344,15 +3382,17 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, if (retval != 0) break; - retval = sbuf_printf(sb, "\t%#jx\n", - (uintmax_t)port->wwnn); - if (retval != 0) - break; + if (port->target_devid != NULL) { + sbuf_printf(sb, "\t"); + ctl_id_sbuf(port->target_devid, sb); + sbuf_printf(sb, "\n"); + } - retval = sbuf_printf(sb, "\t%#jx\n", - (uintmax_t)port->wwpn); - if (retval != 0) - break; + if (port->port_devid != NULL) { + sbuf_printf(sb, "\t"); + ctl_id_sbuf(port->port_devid, sb); + sbuf_printf(sb, "\n"); + } if (port->port_info != NULL) { retval = port->port_info(port->onoff_arg, sb); @@ -3366,6 +3406,26 @@ ctl_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int flag, break; } + for (j = 0; j < CTL_MAX_INIT_PER_PORT; j++) { + if (port->wwpn_iid[j].in_use == 0 || + (port->wwpn_iid[j].wwpn == 0 && + port->wwpn_iid[j].name == NULL)) + continue; + + if (port->wwpn_iid[j].name != NULL) + retval = sbuf_printf(sb, + "\t%u %s\n", + j, port->wwpn_iid[j].name); + else + retval = sbuf_printf(sb, + "\t%u naa.%08jx\n", + j, port->wwpn_iid[j].wwpn); + if (retval != 0) + break; + } + if (retval != 0) + break; + retval = sbuf_printf(sb, "\n"); if (retval != 0) break; diff --git a/usr.sbin/ctladm/ctladm.8 b/usr.sbin/ctladm/ctladm.8 index 19ee806fd83a..5e69dd25402b 100644 --- a/usr.sbin/ctladm/ctladm.8 +++ b/usr.sbin/ctladm/ctladm.8 @@ -34,7 +34,7 @@ .\" $Id: //depot/users/kenm/FreeBSD-test2/usr.sbin/ctladm/ctladm.8#3 $ .\" $FreeBSD$ .\" -.Dd October 8, 2014 +.Dd October 12, 2014 .Dt CTLADM 8 .Os .Sh NAME @@ -193,6 +193,14 @@ .Op Fl q .Op Fl x .Nm +.Ic portlist +.Op Fl f Ar frontend +.Op Fl i +.Op Fl p Ar targ_port +.Op Fl q +.Op Fl v +.Op Fl x +.Nm .Ic dumpooa .Nm .Ic dumpstructs @@ -768,6 +776,22 @@ As a general rule, the WWPN must be different for every port in the system. .It Fl x Output the port list in XML format. .El +.It Ic portlist +List CTL frontend ports. +.Bl -tag -width 12n +.It Fl f Ar frontend +Specify the frontend type. +.It Fl i +Report target and connected initiators addresses +.It Fl p Ar targ_port +Specify the frontend port number. +.It Fl q +Omit the header in the port list output. +.It Fl v +Enable verbose output (report all port options). +.It Fl x +Output the port list in XML format. +.El .It Ic dumpooa Dump the OOA (Order Of Arrival) queue for each LUN registered with CTL. .It Ic dumpstructs diff --git a/usr.sbin/ctladm/ctladm.c b/usr.sbin/ctladm/ctladm.c index 29fdd501057f..731c7d81160b 100644 --- a/usr.sbin/ctladm/ctladm.c +++ b/usr.sbin/ctladm/ctladm.c @@ -191,7 +191,7 @@ static struct ctladm_opts option_table[] = { {"modesense", CTLADM_CMD_MODESENSE, CTLADM_ARG_NEED_TL, "P:S:dlm:c:"}, {"modify", CTLADM_CMD_MODIFY, CTLADM_ARG_NONE, "b:l:s:"}, {"port", CTLADM_CMD_PORT, CTLADM_ARG_NONE, "lo:p:qt:w:W:x"}, - {"portlist", CTLADM_CMD_PORTLIST, CTLADM_ARG_NONE, "f:vx"}, + {"portlist", CTLADM_CMD_PORTLIST, CTLADM_ARG_NONE, "f:ip:qvx"}, {"prin", CTLADM_CMD_PRES_IN, CTLADM_ARG_NEED_TL, "a:"}, {"prout", CTLADM_CMD_PRES_OUT, CTLADM_ARG_NEED_TL, "a:k:r:s:"}, {"read", CTLADM_CMD_READ, CTLADM_ARG_NEED_TL, rw_opts}, @@ -4100,7 +4100,8 @@ struct cctl_port { char *frontend_type; char *name; int pp, vp; - char *wwnn, *wwpn; + char *target, *port; + STAILQ_HEAD(,cctl_lun_nv) init_list; STAILQ_HEAD(,cctl_lun_nv) attr_list; STAILQ_ENTRY(cctl_port) links; }; @@ -4144,6 +4145,7 @@ cctl_start_pelement(void *user_data, const char *name, const char **attr) portlist->num_ports++; portlist->cur_port = cur_port; + STAILQ_INIT(&cur_port->init_list); STAILQ_INIT(&cur_port->attr_list); STAILQ_INSERT_TAIL(&portlist->port_list, cur_port, links); @@ -4205,11 +4207,11 @@ cctl_end_pelement(void *user_data, const char *name) cur_port->pp = strtoull(str, NULL, 0); } else if (strcmp(name, "virtual_port") == 0) { cur_port->vp = strtoull(str, NULL, 0); - } else if (strcmp(name, "wwnn") == 0) { - cur_port->wwnn = str; + } else if (strcmp(name, "target") == 0) { + cur_port->target = str; str = NULL; - } else if (strcmp(name, "wwpn") == 0) { - cur_port->wwpn = str; + } else if (strcmp(name, "port") == 0) { + cur_port->port = str; str = NULL; } else if (strcmp(name, "targ_port") == 0) { portlist->cur_port = NULL; @@ -4230,7 +4232,10 @@ cctl_end_pelement(void *user_data, const char *name) nv->value = str; str = NULL; - STAILQ_INSERT_TAIL(&cur_port->attr_list, nv, links); + if (strcmp(name, "initiator") == 0) + STAILQ_INSERT_TAIL(&cur_port->init_list, nv, links); + else + STAILQ_INSERT_TAIL(&cur_port->attr_list, nv, links); } free(str); @@ -4258,7 +4263,8 @@ cctl_portlist(int fd, int argc, char **argv, char *combinedopt) int dump_xml = 0; int retval, c; char *frontend = NULL; - int verbose = 0; + uint64_t portarg = UINT64_MAX; + int verbose = 0, init = 0, quiet = 0; retval = 0; port_len = 4096; @@ -4271,6 +4277,15 @@ cctl_portlist(int fd, int argc, char **argv, char *combinedopt) case 'f': frontend = strdup(optarg); break; + case 'i': + init++; + break; + case 'p': + portarg = strtoll(optarg, NULL, 0); + break; + case 'q': + quiet++; + break; case 'v': verbose++; break; @@ -4327,8 +4342,8 @@ cctl_portlist(int fd, int argc, char **argv, char *combinedopt) goto bailout; } - printf("Port Online Frontend %-12s pp vp %-18s %-18s\n", - "Name", "WWNN", "WWPN"); + if (quiet == 0) + printf("Port Online Frontend Name pp vp\n"); STAILQ_FOREACH(port, &portlist.port_list, links) { struct cctl_lun_nv *nv; @@ -4336,16 +4351,26 @@ cctl_portlist(int fd, int argc, char **argv, char *combinedopt) && (strcmp(port->frontend_type, frontend) != 0)) continue; - printf("%-4ju %-6s %-8s %-12s %-2d %-2d %-18s %-18s\n", - (uintmax_t)port->port_id, port->online, - port->frontend_type, port->name, port->pp, port->vp, - port->wwnn, port->wwpn); - - if (verbose == 0) + if ((portarg != UINT64_MAX) && (portarg != port->port_id)) continue; - STAILQ_FOREACH(nv, &port->attr_list, links) { - printf(" %s=%s\n", nv->name, nv->value); + printf("%-4ju %-6s %-8s %-8s %-2d %-2d %s\n", + (uintmax_t)port->port_id, port->online, + port->frontend_type, port->name, port->pp, port->vp, + port->port ? port->port : ""); + + if (init || verbose) { + if (port->target) + printf(" Target: %s\n", port->target); + STAILQ_FOREACH(nv, &port->init_list, links) { + printf(" Initiator: %s\n", nv->value); + } + } + + if (verbose) { + STAILQ_FOREACH(nv, &port->attr_list, links) { + printf(" %s=%s\n", nv->name, nv->value); + } } } bailout: @@ -4401,7 +4426,7 @@ usage(int error) " [-s len fmt [args]] [-c] [-d delete_id]\n" " ctladm port <-l | -o | [-w wwnn][-W wwpn]>\n" " [-p targ_port] [-t port_type] [-q] [-x]\n" -" ctladm portlist [-f frontend] [-v] [-x]\n" +" ctladm portlist [-f frontend] [-i] [-p targ_port] [-q] [-v] [-x]\n" " ctladm islist [-v | -x]\n" " ctladm islogout <-a | -c connection-id | -i name | -p portal>\n" " ctladm isterminate <-a | -c connection-id | -i name | -p portal>\n" @@ -4487,6 +4512,13 @@ usage(int error) "-p targ_port : specify target port number\n" "-q : omit header in list output\n" "-x : output port list in XML format\n" +"portlist options:\n" +"-f fronetnd : specify frontend type\n" +"-i : report target and initiators addresses\n" +"-p targ_port : specify target port number\n" +"-q : omit header in list output\n" +"-v : verbose output (report all port options)\n" +"-x : output port list in XML format\n" "bbrread options:\n" "-l lba : starting LBA\n" "-d datalen : length, in bytes, to read\n",