summaryrefslogtreecommitdiffstats
path: root/usr.sbin/ctladm
diff options
context:
space:
mode:
authorsjg <sjg@FreeBSD.org>2015-05-27 01:19:58 +0000
committersjg <sjg@FreeBSD.org>2015-05-27 01:19:58 +0000
commit65145fa4c81da358fcbc3b650156dab705dfa34e (patch)
tree55c065b6730aaac2afb6c29933ee6ec5fa4c4249 /usr.sbin/ctladm
parent60ff4eb0dff94a04d75d0d52a3957aaaf5f8c693 (diff)
parente6b664c390af88d4a87208bc042ce503da664c3b (diff)
downloadFreeBSD-src-65145fa4c81da358fcbc3b650156dab705dfa34e.zip
FreeBSD-src-65145fa4c81da358fcbc3b650156dab705dfa34e.tar.gz
Merge sync of head
Diffstat (limited to 'usr.sbin/ctladm')
-rw-r--r--usr.sbin/ctladm/Makefile3
-rw-r--r--usr.sbin/ctladm/ctladm.857
-rw-r--r--usr.sbin/ctladm/ctladm.c132
3 files changed, 166 insertions, 26 deletions
diff --git a/usr.sbin/ctladm/Makefile b/usr.sbin/ctladm/Makefile
index a9f6bfd..fd9e606 100644
--- a/usr.sbin/ctladm/Makefile
+++ b/usr.sbin/ctladm/Makefile
@@ -14,8 +14,7 @@ CFLAGS+= -I${SDIR}
WARNS?= 3
.endif
-DPADD= ${LIBCAM} ${LIBSBUF} ${LIBBSDXML} ${LIBUTIL}
-LDADD= -lcam -lsbuf -lbsdxml -lutil
+LIBADD= cam sbuf bsdxml util
MAN= ctladm.8
.include <bsd.prog.mk>
diff --git a/usr.sbin/ctladm/ctladm.8 b/usr.sbin/ctladm/ctladm.8
index 23f63d4..c4508cc 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 November 5, 2014
+.Dd May 22, 2015
.Dt CTLADM 8
.Os
.Sh NAME
@@ -196,11 +196,17 @@
.Ic portlist
.Op Fl f Ar frontend
.Op Fl i
+.Op Fl l
.Op Fl p Ar targ_port
.Op Fl q
.Op Fl v
.Op Fl x
.Nm
+.Ic lunmap
+.Aq Fl p Ar targ_port
+.Op Fl l Ar pLUN
+.Op Fl L Ar cLUN
+.Nm
.Ic dumpooa
.Nm
.Ic dumpstructs
@@ -782,7 +788,9 @@ List CTL frontend ports.
.It Fl f Ar frontend
Specify the frontend type.
.It Fl i
-Report target and connected initiators addresses
+Report target and connected initiators addresses.
+.It Fl l
+Report LUN mapping.
.It Fl p Ar targ_port
Specify the frontend port number.
.It Fl q
@@ -792,6 +800,31 @@ Enable verbose output (report all port options).
.It Fl x
Output the port list in XML format.
.El
+.It Ic lunmap
+Change LUN mapping for specified port.
+If both
+.Ar pLUN
+and
+.Ar cLUN
+are specified -- LUN will be mapped.
+If
+.Ar pLUN
+is specified, but
+.Ar cLUN
+is not -- LUN will be unmapped.
+If neither
+.Ar pLUN
+nor
+.Ar cLUN
+are specified -- LUN mapping will be disabled, exposing all CTL LUNs.
+.Bl -tag -width 12n
+.It Fl p Ar targ_port
+Specify the frontend port number.
+.It Fl l Ar pLUN
+LUN number visible by specified port.
+.It Fl L Ar cLUN
+CTL LUN number.
+.El
.It Ic dumpooa
Dump the OOA (Order Of Arrival) queue for each LUN registered with CTL.
.It Ic dumpstructs
@@ -995,6 +1028,20 @@ command sequence order shall be explicitly handled by the application
client through the selection of appropriate commands and task attributes.
The default value is "restricted". It improves data integrity, but may
introduce some additional delays.
+.It Va serseq
+Set to "on" to serialize conseсutive reads/writes.
+Set to "read" to serialize conseсutive reads.
+Set to "off" to allow them be issued in parallel.
+Parallel issue of consecutive operations may confuse logic of the
+backing file system, hurting performance; but it may improve performance
+of backing stores without prefetch/write-back.
+.It Va pblocksize
+.It Va pblockoffset
+Specify physical block size and offset of the device.
+.It Va ublocksize
+.It Va ublockoffset
+Specify UNMAP block size and offset of the device.
+.It Va rpm
.It Va rpm
Specifies medium rotation rate of the device: 0 -- not reported,
1 -- non-rotating (SSD), >1024 -- value in revolutions per minute.
@@ -1007,10 +1054,11 @@ Set to "on", enables UNMAP support for the LUN, if supported by the backend.
.It Va used-threshold
.It Va pool-avail-threshold
.It Va pool-used-threshold
-Set per-LUN/-pool thin provisioning soft thresholds for ZVOL-backed LUNs.
+Set per-LUN/-pool thin provisioning soft thresholds.
LUN will establish UNIT ATTENTION condition if its or pool available space
get below configured avail values, or its or pool used space get above
configured used values.
+Pool thresholds are working only for ZVOL-backed LUNs.
.It Va writecache
Set to "off", disables write caching for the LUN, if supported by the backend.
.El
@@ -1112,7 +1160,8 @@ This will result in a sense key of NOT READY (0x02), and an ASC/ASCQ of
.Xr ctl 4 ,
.Xr xpt 4 ,
.Xr camcontrol 8 ,
-.Xr ctld 8
+.Xr ctld 8 ,
+.Xr ctlstat 8
.Sh HISTORY
The
.Nm
diff --git a/usr.sbin/ctladm/ctladm.c b/usr.sbin/ctladm/ctladm.c
index 03f46c9..aefba04 100644
--- a/usr.sbin/ctladm/ctladm.c
+++ b/usr.sbin/ctladm/ctladm.c
@@ -121,7 +121,8 @@ typedef enum {
CTLADM_CMD_MODIFY,
CTLADM_CMD_ISLIST,
CTLADM_CMD_ISLOGOUT,
- CTLADM_CMD_ISTERMINATE
+ CTLADM_CMD_ISTERMINATE,
+ CTLADM_CMD_LUNMAP
} ctladm_cmdfunction;
typedef enum {
@@ -188,10 +189,11 @@ static struct ctladm_opts option_table[] = {
{"islogout", CTLADM_CMD_ISLOGOUT, CTLADM_ARG_NONE, "ac:i:p:"},
{"isterminate", CTLADM_CMD_ISTERMINATE, CTLADM_ARG_NONE, "ac:i:p:"},
{"lunlist", CTLADM_CMD_LUNLIST, CTLADM_ARG_NONE, NULL},
+ {"lunmap", CTLADM_CMD_LUNMAP, CTLADM_ARG_NONE, "p:l:L:"},
{"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:ip:qvx"},
+ {"portlist", CTLADM_CMD_PORTLIST, CTLADM_ARG_NONE, "f:ilp: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},
@@ -3437,6 +3439,7 @@ struct cctl_islist_conn {
char *header_digest;
char *data_digest;
char *max_data_segment_length;;
+ char *offload;;
int immediate_data;
int iser;
STAILQ_ENTRY(cctl_islist_conn) links;
@@ -3540,6 +3543,7 @@ cctl_islist_end_element(void *user_data, const char *name)
} else if (strcmp(name, "target_alias") == 0) {
cur_conn->target_alias = str;
str = NULL;
+ } else if (strcmp(name, "target_portal_group_tag") == 0) {
} else if (strcmp(name, "header_digest") == 0) {
cur_conn->header_digest = str;
str = NULL;
@@ -3549,6 +3553,9 @@ cctl_islist_end_element(void *user_data, const char *name)
} else if (strcmp(name, "max_data_segment_length") == 0) {
cur_conn->max_data_segment_length = str;
str = NULL;
+ } else if (strcmp(name, "offload") == 0) {
+ cur_conn->offload = str;
+ str = NULL;
} else if (strcmp(name, "immediate_data") == 0) {
cur_conn->immediate_data = atoi(str);
} else if (strcmp(name, "iser") == 0) {
@@ -3556,8 +3563,12 @@ cctl_islist_end_element(void *user_data, const char *name)
} else if (strcmp(name, "connection") == 0) {
islist->cur_conn = NULL;
} else if (strcmp(name, "ctlislist") == 0) {
- } else
- errx(1, "unknown element %s", name);
+ /* Nothing. */
+ } else {
+ /*
+ * Unknown element; ignore it for forward compatiblity.
+ */
+ }
free(str);
}
@@ -3643,11 +3654,14 @@ retry:
XML_SetCharacterDataHandler(parser, cctl_islist_char_handler);
retval = XML_Parse(parser, conn_str, strlen(conn_str), 1);
- XML_ParserFree(parser);
if (retval != 1) {
+ warnx("%s: Unable to parse XML: Error %d", __func__,
+ XML_GetErrorCode(parser));
+ XML_ParserFree(parser);
retval = 1;
goto bailout;
}
+ XML_ParserFree(parser);
if (verbose != 0) {
STAILQ_FOREACH(conn, &islist.conn_list, links) {
@@ -3662,6 +3676,7 @@ retry:
printf("DataSegmentLen: %s\n", conn->max_data_segment_length);
printf("ImmediateData: %s\n", conn->immediate_data ? "Yes" : "No");
printf("iSER (RDMA): %s\n", conn->iser ? "Yes" : "No");
+ printf("Offload driver: %s\n", conn->offload);
printf("\n");
}
} else {
@@ -4058,11 +4073,14 @@ retry:
XML_SetCharacterDataHandler(parser, cctl_char_handler);
retval = XML_Parse(parser, lun_str, strlen(lun_str), 1);
- XML_ParserFree(parser);
if (retval != 1) {
+ warnx("%s: Unable to parse XML: Error %d", __func__,
+ XML_GetErrorCode(parser));
+ XML_ParserFree(parser);
retval = 1;
goto bailout;
}
+ XML_ParserFree(parser);
printf("LUN Backend %18s %4s %-16s %-16s\n", "Size (Blocks)", "BS",
"Serial Number", "Device ID");
@@ -4100,8 +4118,9 @@ struct cctl_port {
char *frontend_type;
char *name;
int pp, vp;
- char *target, *port;
+ char *target, *port, *lun_map;
STAILQ_HEAD(,cctl_lun_nv) init_list;
+ STAILQ_HEAD(,cctl_lun_nv) lun_list;
STAILQ_HEAD(,cctl_lun_nv) attr_list;
STAILQ_ENTRY(cctl_port) links;
};
@@ -4111,6 +4130,7 @@ struct cctl_portlist_data {
STAILQ_HEAD(,cctl_port) port_list;
struct cctl_port *cur_port;
int level;
+ uint64_t cur_id;
struct sbuf *cur_sb[32];
};
@@ -4133,6 +4153,14 @@ cctl_start_pelement(void *user_data, const char *name, const char **attr)
if (portlist->cur_sb[portlist->level] == NULL)
err(1, "%s: Unable to allocate sbuf", __func__);
+ portlist->cur_id = 0;
+ for (i = 0; attr[i] != NULL; i += 2) {
+ if (strcmp(attr[i], "id") == 0) {
+ portlist->cur_id = strtoull(attr[i+1], NULL, 0);
+ break;
+ }
+ }
+
if (strcmp(name, "targ_port") == 0) {
if (cur_port != NULL)
errx(1, "%s: improper port element nesting", __func__);
@@ -4146,17 +4174,10 @@ cctl_start_pelement(void *user_data, const char *name, const char **attr)
portlist->cur_port = cur_port;
STAILQ_INIT(&cur_port->init_list);
+ STAILQ_INIT(&cur_port->lun_list);
STAILQ_INIT(&cur_port->attr_list);
+ cur_port->port_id = portlist->cur_id;
STAILQ_INSERT_TAIL(&portlist->port_list, cur_port, links);
-
- for (i = 0; attr[i] != NULL; i += 2) {
- if (strcmp(attr[i], "id") == 0) {
- cur_port->port_id = strtoull(attr[i+1], NULL, 0);
- } else {
- errx(1, "%s: invalid LUN attribute %s = %s",
- __func__, attr[i], attr[i+1]);
- }
- }
}
}
@@ -4213,6 +4234,9 @@ cctl_end_pelement(void *user_data, const char *name)
} else if (strcmp(name, "port") == 0) {
cur_port->port = str;
str = NULL;
+ } else if (strcmp(name, "lun_map") == 0) {
+ cur_port->lun_map = str;
+ str = NULL;
} else if (strcmp(name, "targ_port") == 0) {
portlist->cur_port = NULL;
} else if (strcmp(name, "ctlportlist") == 0) {
@@ -4225,7 +4249,11 @@ cctl_end_pelement(void *user_data, const char *name)
err(1, "%s: can't allocate %zd bytes for nv pair",
__func__, sizeof(*nv));
- nv->name = strdup(name);
+ if (strcmp(name, "initiator") == 0 ||
+ strcmp(name, "lun") == 0)
+ asprintf(&nv->name, "%ju", portlist->cur_id);
+ else
+ nv->name = strdup(name);
if (nv->name == NULL)
err(1, "%s: can't allocated %zd bytes for string",
__func__, strlen(name));
@@ -4234,6 +4262,8 @@ cctl_end_pelement(void *user_data, const char *name)
str = NULL;
if (strcmp(name, "initiator") == 0)
STAILQ_INSERT_TAIL(&cur_port->init_list, nv, links);
+ else if (strcmp(name, "lun") == 0)
+ STAILQ_INSERT_TAIL(&cur_port->lun_list, nv, links);
else
STAILQ_INSERT_TAIL(&cur_port->attr_list, nv, links);
}
@@ -4264,7 +4294,7 @@ cctl_portlist(int fd, int argc, char **argv, char *combinedopt)
int retval, c;
char *frontend = NULL;
uint64_t portarg = UINT64_MAX;
- int verbose = 0, init = 0, quiet = 0;
+ int verbose = 0, init = 0, lun = 0, quiet = 0;
retval = 0;
port_len = 4096;
@@ -4280,6 +4310,9 @@ cctl_portlist(int fd, int argc, char **argv, char *combinedopt)
case 'i':
init++;
break;
+ case 'l':
+ lun++;
+ break;
case 'p':
portarg = strtoll(optarg, NULL, 0);
break;
@@ -4336,11 +4369,14 @@ retry:
XML_SetCharacterDataHandler(parser, cctl_char_phandler);
retval = XML_Parse(parser, port_str, strlen(port_str), 1);
- XML_ParserFree(parser);
if (retval != 1) {
+ warnx("%s: Unable to parse XML: Error %d", __func__,
+ XML_GetErrorCode(parser));
+ XML_ParserFree(parser);
retval = 1;
goto bailout;
}
+ XML_ParserFree(parser);
if (quiet == 0)
printf("Port Online Frontend Name pp vp\n");
@@ -4363,10 +4399,22 @@ retry:
if (port->target)
printf(" Target: %s\n", port->target);
STAILQ_FOREACH(nv, &port->init_list, links) {
- printf(" Initiator: %s\n", nv->value);
+ printf(" Initiator %s: %s\n",
+ nv->name, nv->value);
}
}
+ if (lun || verbose) {
+ if (port->lun_map) {
+ STAILQ_FOREACH(nv, &port->lun_list, links)
+ printf(" LUN %s: %s\n",
+ nv->name, nv->value);
+ if (STAILQ_EMPTY(&port->lun_list))
+ printf(" No LUNs mapped\n");
+ } else
+ printf(" All LUNs mapped\n");
+ }
+
if (verbose) {
STAILQ_FOREACH(nv, &port->attr_list, links) {
printf(" %s=%s\n", nv->name, nv->value);
@@ -4379,6 +4427,41 @@ bailout:
return (retval);
}
+static int
+cctl_lunmap(int fd, int argc, char **argv, char *combinedopt)
+{
+ struct ctl_lun_map lm;
+ int retval = 0, c;
+
+ retval = 0;
+ lm.port = UINT32_MAX;
+ lm.plun = UINT32_MAX;
+ lm.lun = UINT32_MAX;
+
+ while ((c = getopt(argc, argv, combinedopt)) != -1) {
+ switch (c) {
+ case 'p':
+ lm.port = strtoll(optarg, NULL, 0);
+ break;
+ case 'l':
+ lm.plun = strtoll(optarg, NULL, 0);
+ break;
+ case 'L':
+ lm.lun = strtoll(optarg, NULL, 0);
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (ioctl(fd, CTL_LUN_MAP, &lm) == -1) {
+ warn("%s: error issuing CTL_LUN_MAP ioctl", __func__);
+ retval = 1;
+ }
+
+ return (retval);
+}
+
void
usage(int error)
{
@@ -4416,6 +4499,7 @@ usage(int error)
" ctladm hardstop\n"
" ctladm hardstart\n"
" ctladm lunlist\n"
+" ctladm lunmap -p targ_port [-l pLUN] [-L cLUN]\n"
" ctladm bbrread [dev_id] <-l lba> <-d datalen>\n"
" ctladm delay [dev_id] <-l datamove|done> [-T oneshot|cont]\n"
" [-t secs]\n"
@@ -4515,10 +4599,15 @@ usage(int error)
"portlist options:\n"
"-f fronetnd : specify frontend type\n"
"-i : report target and initiators addresses\n"
+"-l : report LUN mapping\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"
+"lunmap options:\n"
+"-p targ_port : specify target port number\n"
+"-L pLUN : specify port-visible LUN\n"
+"-L cLUN : specify CTL LUN\n"
"bbrread options:\n"
"-l lba : starting LBA\n"
"-d datalen : length, in bytes, to read\n",
@@ -4746,6 +4835,9 @@ main(int argc, char **argv)
case CTLADM_CMD_PORTLIST:
retval = cctl_portlist(fd, argc, argv, combinedopt);
break;
+ case CTLADM_CMD_LUNMAP:
+ retval = cctl_lunmap(fd, argc, argv, combinedopt);
+ break;
case CTLADM_CMD_READCAPACITY:
retval = cctl_read_capacity(fd, target, lun, initid, retries,
argc, argv, combinedopt);
OpenPOWER on IntegriCloud