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",