Improve and document ctladm portlist
subcommand.
Make this subcommand less FC-specific, reporting target and port addresses in more generic way. Also make it report list of connected initiators in unified way, working for both FC and iSCSI, and potentially others. MFC after: 1 week
This commit is contained in:
parent
106faa1462
commit
e3e9d7f585
@ -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<wwnn>%#jx</wwnn>\n",
|
||||
(uintmax_t)port->wwnn);
|
||||
if (retval != 0)
|
||||
break;
|
||||
if (port->target_devid != NULL) {
|
||||
sbuf_printf(sb, "\t<target>");
|
||||
ctl_id_sbuf(port->target_devid, sb);
|
||||
sbuf_printf(sb, "</target>\n");
|
||||
}
|
||||
|
||||
retval = sbuf_printf(sb, "\t<wwpn>%#jx</wwpn>\n",
|
||||
(uintmax_t)port->wwpn);
|
||||
if (retval != 0)
|
||||
break;
|
||||
if (port->port_devid != NULL) {
|
||||
sbuf_printf(sb, "\t<port>");
|
||||
ctl_id_sbuf(port->port_devid, sb);
|
||||
sbuf_printf(sb, "</port>\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<initiator>%u %s</initiator>\n",
|
||||
j, port->wwpn_iid[j].name);
|
||||
else
|
||||
retval = sbuf_printf(sb,
|
||||
"\t<initiator>%u naa.%08jx</initiator>\n",
|
||||
j, port->wwpn_iid[j].wwpn);
|
||||
if (retval != 0)
|
||||
break;
|
||||
}
|
||||
if (retval != 0)
|
||||
break;
|
||||
|
||||
retval = sbuf_printf(sb, "</targ_port>\n");
|
||||
if (retval != 0)
|
||||
break;
|
||||
|
@ -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
|
||||
|
@ -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 <on|off> | [-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",
|
||||
|
Loading…
Reference in New Issue
Block a user