summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJerry Jelinek <jerry.jelinek@joyent.com>2017-01-20 13:14:41 +0000
committerJerry Jelinek <jerry.jelinek@joyent.com>2017-01-20 13:14:41 +0000
commitfcad5553b5bffeb072d20a89b3733efd983829b3 (patch)
tree43ae03a37249e81e64aaf7a7a90ebae228c1d766
parent00102e8416e6dca2396e94214e0d5b7a2bca98c3 (diff)
parented5fe2f85936728de7ab82b44e9b9742c976d436 (diff)
downloadillumos-joyent-fcad5553b5bffeb072d20a89b3733efd983829b3.tar.gz
[illumos-gate merge]
commit ed5fe2f85936728de7ab82b44e9b9742c976d436 7771 integrate diskinfo commit 9c21aec34549fc6b22406628ae7954badcc9ec37 7783 uts: gallant font a-acute points to wrong glyph
-rw-r--r--manifest2
-rw-r--r--usr/src/cmd/Makefile1
-rw-r--r--usr/src/cmd/diskinfo/Makefile40
-rw-r--r--usr/src/cmd/diskinfo/diskinfo.c456
-rw-r--r--usr/src/man/man1m/Makefile1
-rw-r--r--usr/src/man/man1m/diskinfo.1m191
-rw-r--r--usr/src/pkg/manifests/diagnostic-diskinfo.mf33
-rw-r--r--usr/src/uts/common/io/12x22.c2
8 files changed, 725 insertions, 1 deletions
diff --git a/manifest b/manifest
index b415cb73db..63450b0dc8 100644
--- a/manifest
+++ b/manifest
@@ -10337,6 +10337,7 @@ s usr/sbin/devnm=df
f usr/sbin/df 0555 root bin
f usr/sbin/dfmounts 0555 root bin
h usr/sbin/dfshares=usr/sbin/dfmounts
+f usr/sbin/diskinfo 0555 root bin
h usr/sbin/disks=usr/sbin/devfsadm
f usr/sbin/dispadmin 0555 root bin
s usr/sbin/dladm=../../sbin/dladm
@@ -11932,6 +11933,7 @@ f usr/share/man/man1m/dfmounts_nfs.1m 0444 root bin
f usr/share/man/man1m/dfshares.1m 0444 root bin
f usr/share/man/man1m/dfshares_nfs.1m 0444 root bin
f usr/share/man/man1m/dhcpagent.1m 0444 root bin
+f usr/share/man/man1m/diskinfo.1m 0444 root bin
f usr/share/man/man1m/disks.1m 0444 root bin
f usr/share/man/man1m/diskscan.1m 0444 root bin
f usr/share/man/man1m/dispadmin.1m 0444 root bin
diff --git a/usr/src/cmd/Makefile b/usr/src/cmd/Makefile
index 94c75bd0f6..5c52596c03 100644
--- a/usr/src/cmd/Makefile
+++ b/usr/src/cmd/Makefile
@@ -131,6 +131,7 @@ COMMON_SUBDIRS= \
dircmp \
dirname \
dis \
+ diskinfo \
diskmgtd \
dispadmin \
dladm \
diff --git a/usr/src/cmd/diskinfo/Makefile b/usr/src/cmd/diskinfo/Makefile
new file mode 100644
index 0000000000..47d2289c90
--- /dev/null
+++ b/usr/src/cmd/diskinfo/Makefile
@@ -0,0 +1,40 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2016 Nexenta Systems, Inc.
+#
+
+PROG= diskinfo
+OBJS= diskinfo.o
+SRCS= $(OBJS:%.o=%.c)
+
+include $(SRC)/cmd/Makefile.cmd
+include $(SRC)/cmd/Makefile.ctf
+
+CPPFLAGS += -I$(SRC)/lib/fm/topo
+
+LDLIBS += -L$(ROOT)/usr/lib/fm -R/usr/lib/fm -ldiskmgt -lnvpair -ltopo
+
+.KEEP_STATE:
+
+all: $(PROG)
+
+$(PROG): $(OBJS)
+ $(LINK.c) $(OBJS) -o $@ $(LDLIBS)
+ $(POST_PROCESS)
+
+clean:
+ $(RM) $(OBJS)
+
+install: all $(ROOTUSRSBINPROG)
+
+include $(SRC)/cmd/Makefile.targ
diff --git a/usr/src/cmd/diskinfo/diskinfo.c b/usr/src/cmd/diskinfo/diskinfo.c
new file mode 100644
index 0000000000..cf28f00889
--- /dev/null
+++ b/usr/src/cmd/diskinfo/diskinfo.c
@@ -0,0 +1,456 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source. A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright (c) 2013 Joyent Inc., All rights reserved.
+ */
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <limits.h>
+#include <assert.h>
+#include <ctype.h>
+#include <stdarg.h>
+#include <strings.h>
+
+#include <libdiskmgt.h>
+#include <sys/nvpair.h>
+#include <sys/param.h>
+#include <sys/ccompile.h>
+
+#include <fm/libtopo.h>
+#include <fm/topo_hc.h>
+#include <fm/topo_list.h>
+#include <sys/fm/protocol.h>
+#include <modules/common/disk/disk.h>
+
+typedef struct di_opts {
+ boolean_t di_scripted;
+ boolean_t di_parseable;
+ boolean_t di_physical;
+ boolean_t di_condensed;
+} di_opts_t;
+
+typedef struct di_phys {
+ const char *dp_dev;
+ const char *dp_serial;
+ const char *dp_slotname;
+ int dp_chassis;
+ int dp_slot;
+ int dp_faulty;
+ int dp_locate;
+} di_phys_t;
+
+static void __NORETURN
+fatal(int rv, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ (void) vfprintf(stderr, fmt, ap);
+ va_end(ap);
+
+ exit(rv);
+}
+
+static void
+usage(const char *execname)
+{
+ (void) fprintf(stderr, "Usage: %s [-Hp] [{-c|-P}]\n", execname);
+}
+
+static void
+nvlist_query_string(nvlist_t *nvl, const char *label, char **val)
+{
+ if (nvlist_lookup_string(nvl, label, val) != 0)
+ *val = "-";
+}
+
+static const char *
+display_string(const char *label)
+{
+ return ((label) ? label : "-");
+}
+
+static const char *
+display_tristate(int val)
+{
+ if (val == 0)
+ return ("no");
+ if (val == 1)
+ return ("yes");
+
+ return ("-");
+}
+
+static char
+condensed_tristate(int val, char c)
+{
+ if (val == 0)
+ return ('-');
+ if (val == 1)
+ return (c);
+
+ return ('?');
+}
+static int
+disk_walker(topo_hdl_t *hp, tnode_t *np, void *arg)
+{
+ di_phys_t *pp = arg;
+ tnode_t *pnp;
+ tnode_t *ppnp;
+ topo_faclist_t fl;
+ topo_faclist_t *lp;
+ int err;
+ topo_led_state_t mode;
+ topo_led_type_t type;
+ char *name, *slotname, *serial;
+
+ if (strcmp(topo_node_name(np), DISK) != 0)
+ return (TOPO_WALK_NEXT);
+
+ if (topo_prop_get_string(np, TOPO_PGROUP_STORAGE,
+ TOPO_STORAGE_LOGICAL_DISK_NAME, &name, &err) != 0) {
+ return (TOPO_WALK_NEXT);
+ }
+
+ if (strcmp(name, pp->dp_dev) != 0)
+ return (TOPO_WALK_NEXT);
+
+ if (topo_prop_get_string(np, TOPO_PGROUP_STORAGE,
+ TOPO_STORAGE_SERIAL_NUM, &serial, &err) == 0) {
+ pp->dp_serial = serial;
+ }
+
+ pnp = topo_node_parent(np);
+ ppnp = topo_node_parent(pnp);
+ if (strcmp(topo_node_name(pnp), BAY) == 0) {
+ if (topo_node_facility(hp, pnp, TOPO_FAC_TYPE_INDICATOR,
+ TOPO_FAC_TYPE_ANY, &fl, &err) == 0) {
+ for (lp = topo_list_next(&fl.tf_list); lp != NULL;
+ lp = topo_list_next(lp)) {
+ if (topo_prop_get_uint32(lp->tf_node,
+ TOPO_PGROUP_FACILITY, TOPO_FACILITY_TYPE,
+ &type, &err) != 0) {
+ continue;
+ }
+ if (topo_prop_get_uint32(lp->tf_node,
+ TOPO_PGROUP_FACILITY, TOPO_LED_MODE,
+ &mode, &err) != 0) {
+ continue;
+ }
+
+ switch (type) {
+ case TOPO_LED_TYPE_SERVICE:
+ pp->dp_faulty = mode ? 1 : 0;
+ break;
+ case TOPO_LED_TYPE_LOCATE:
+ pp->dp_locate = mode ? 1 : 0;
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ if (topo_prop_get_string(pnp, TOPO_PGROUP_PROTOCOL,
+ TOPO_PROP_LABEL, &slotname, &err) == 0) {
+ pp->dp_slotname = slotname;
+ }
+
+ pp->dp_slot = topo_node_instance(pnp);
+ }
+
+ pp->dp_chassis = topo_node_instance(ppnp);
+
+ return (TOPO_WALK_TERMINATE);
+}
+
+static void
+populate_physical(topo_hdl_t *hp, di_phys_t *pp)
+{
+ int err;
+ topo_walk_t *wp;
+
+ pp->dp_faulty = pp->dp_locate = -1;
+ pp->dp_chassis = pp->dp_slot = -1;
+
+ err = 0;
+ wp = topo_walk_init(hp, FM_FMRI_SCHEME_HC, disk_walker, pp, &err);
+ if (wp == NULL) {
+ fatal(-1, "unable to initialise topo walker: %s",
+ topo_strerror(err));
+ }
+
+ while ((err = topo_walk_step(wp, TOPO_WALK_CHILD)) == TOPO_WALK_NEXT)
+ ;
+
+ if (err == TOPO_WALK_ERR)
+ fatal(-1, "topo walk failed");
+
+ topo_walk_fini(wp);
+}
+
+static void
+enumerate_disks(di_opts_t *opts)
+{
+ topo_hdl_t *hp;
+ dm_descriptor_t *media;
+ int err, i;
+ int filter[] = { DM_DT_FIXED, -1 };
+ dm_descriptor_t *disk, *controller;
+ nvlist_t *mattrs, *dattrs, *cattrs = NULL;
+
+ uint64_t size, total;
+ uint32_t blocksize;
+ double total_in_GiB;
+ char sizestr[32];
+ char slotname[32];
+ char statestr[8];
+
+ char *vid, *pid, *opath, *c, *ctype = NULL;
+ boolean_t removable;
+ boolean_t ssd;
+ char device[MAXPATHLEN];
+ di_phys_t phys;
+ size_t len;
+
+ err = 0;
+ if ((media = dm_get_descriptors(DM_MEDIA, filter, &err)) == NULL) {
+ fatal(-1, "failed to obtain media descriptors: %s\n",
+ strerror(err));
+ }
+
+ err = 0;
+ hp = topo_open(TOPO_VERSION, NULL, &err);
+ if (hp == NULL) {
+ fatal(-1, "unable to obtain topo handle: %s",
+ topo_strerror(err));
+ }
+
+ err = 0;
+ (void) topo_snap_hold(hp, NULL, &err);
+ if (err != 0) {
+ fatal(-1, "unable to hold topo snapshot: %s",
+ topo_strerror(err));
+ }
+
+ for (i = 0; media != NULL && media[i] != NULL; i++) {
+ if ((disk = dm_get_associated_descriptors(media[i],
+ DM_DRIVE, &err)) == NULL) {
+ continue;
+ }
+
+ mattrs = dm_get_attributes(media[i], &err);
+ err = nvlist_lookup_uint64(mattrs, DM_SIZE, &size);
+ assert(err == 0);
+ err = nvlist_lookup_uint32(mattrs, DM_BLOCKSIZE, &blocksize);
+ assert(err == 0);
+ nvlist_free(mattrs);
+
+ dattrs = dm_get_attributes(disk[0], &err);
+
+ nvlist_query_string(dattrs, DM_VENDOR_ID, &vid);
+ nvlist_query_string(dattrs, DM_PRODUCT_ID, &pid);
+ nvlist_query_string(dattrs, DM_OPATH, &opath);
+
+ removable = B_FALSE;
+ if (nvlist_lookup_boolean(dattrs, DM_REMOVABLE) == 0)
+ removable = B_TRUE;
+
+ ssd = B_FALSE;
+ if (nvlist_lookup_boolean(dattrs, DM_SOLIDSTATE) == 0)
+ ssd = B_TRUE;
+
+ if ((controller = dm_get_associated_descriptors(disk[0],
+ DM_CONTROLLER, &err)) != NULL) {
+ cattrs = dm_get_attributes(controller[0], &err);
+ nvlist_query_string(cattrs, DM_CTYPE, &ctype);
+ ctype = strdup(ctype);
+ for (c = ctype; *c != '\0'; c++)
+ *c = toupper(*c);
+ }
+
+ /*
+ * Parse full device path to only show the device name,
+ * i.e. c0t1d0. Many paths will reference a particular
+ * slice (c0t1d0s0), so remove the slice if present.
+ */
+ if ((c = strrchr(opath, '/')) != NULL)
+ (void) strlcpy(device, c + 1, sizeof (device));
+ else
+ (void) strlcpy(device, opath, sizeof (device));
+ len = strlen(device);
+ if (device[len - 2] == 's' &&
+ (device[len - 1] >= '0' && device[len - 1] <= '9'))
+ device[len - 2] = '\0';
+
+ bzero(&phys, sizeof (phys));
+ phys.dp_dev = device;
+ populate_physical(hp, &phys);
+
+ /*
+ * The size is given in blocks, so multiply the number
+ * of blocks by the block size to get the total size,
+ * then convert to GiB.
+ */
+ total = size * blocksize;
+
+ if (opts->di_parseable) {
+ (void) snprintf(sizestr, sizeof (sizestr),
+ "%llu", total);
+ } else {
+ total_in_GiB = (double)total /
+ 1024.0 / 1024.0 / 1024.0;
+ (void) snprintf(sizestr, sizeof (sizestr),
+ "%7.2f GiB", total_in_GiB);
+ }
+
+ if (opts->di_parseable) {
+ (void) snprintf(slotname, sizeof (slotname), "%d,%d",
+ phys.dp_chassis, phys.dp_slot);
+ } else if (phys.dp_slotname != NULL) {
+ (void) snprintf(slotname, sizeof (slotname),
+ "[%d] %s", phys.dp_chassis, phys.dp_slotname);
+ } else {
+ slotname[0] = '-';
+ slotname[1] = '\0';
+ }
+
+ if (opts->di_condensed) {
+ (void) snprintf(statestr, sizeof (statestr), "%c%c%c%c",
+ condensed_tristate(phys.dp_faulty, 'F'),
+ condensed_tristate(phys.dp_locate, 'L'),
+ condensed_tristate(removable, 'R'),
+ condensed_tristate(ssd, 'S'));
+ }
+
+ if (opts->di_physical) {
+ if (opts->di_scripted) {
+ printf("%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
+ device, vid, pid,
+ display_string(phys.dp_serial),
+ display_tristate(phys.dp_faulty),
+ display_tristate(phys.dp_locate), slotname);
+ } else {
+ printf("%-22s %-8s %-16s "
+ "%-20s %-3s %-3s %s\n",
+ device, vid, pid,
+ display_string(phys.dp_serial),
+ display_tristate(phys.dp_faulty),
+ display_tristate(phys.dp_locate), slotname);
+ }
+ } else if (opts->di_condensed) {
+ if (opts->di_scripted) {
+ printf("%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
+ ctype, device, vid, pid,
+ display_string(phys.dp_serial),
+ sizestr, statestr, slotname);
+ } else {
+ printf("%-7s %-22s %-8s %-16s "
+ "%-20s\n\t%-13s %-4s %s\n",
+ ctype, device, vid, pid,
+ display_string(phys.dp_serial),
+ sizestr, statestr, slotname);
+ }
+ } else {
+ if (opts->di_scripted) {
+ printf("%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
+ ctype, device, vid, pid, sizestr,
+ display_tristate(removable),
+ display_tristate(ssd));
+ } else {
+ printf("%-7s %-22s %-8s %-16s "
+ "%-13s %-3s %-3s\n", ctype, device,
+ vid, pid, sizestr,
+ display_tristate(removable),
+ display_tristate(ssd));
+ }
+ }
+
+ free(ctype);
+ nvlist_free(cattrs);
+ nvlist_free(dattrs);
+ dm_free_descriptors(controller);
+ dm_free_descriptors(disk);
+ }
+
+ dm_free_descriptors(media);
+ topo_snap_release(hp);
+ topo_close(hp);
+}
+
+int
+main(int argc, char *argv[])
+{
+ char c;
+
+ di_opts_t opts = {
+ .di_condensed = B_FALSE,
+ .di_scripted = B_FALSE,
+ .di_physical = B_FALSE,
+ .di_parseable = B_FALSE
+ };
+
+ while ((c = getopt(argc, argv, ":cHPp")) != EOF) {
+ switch (c) {
+ case 'c':
+ if (opts.di_physical) {
+ usage(argv[0]);
+ fatal(1, "-c and -P are mutually exclusive\n");
+ }
+ opts.di_condensed = B_TRUE;
+ break;
+ case 'H':
+ opts.di_scripted = B_TRUE;
+ break;
+ case 'P':
+ if (opts.di_condensed) {
+ usage(argv[0]);
+ fatal(1, "-c and -P are mutually exclusive\n");
+ }
+ opts.di_physical = B_TRUE;
+ break;
+ case 'p':
+ opts.di_parseable = B_TRUE;
+ break;
+ case '?':
+ usage(argv[0]);
+ fatal(1, "unknown option -%c\n", optopt);
+ default:
+ fatal(-1, "unexpected error on option -%c\n", optopt);
+ }
+ }
+
+ if (!opts.di_scripted) {
+ if (opts.di_physical) {
+ printf("DISK VID PID"
+ " SERIAL FLT LOC"
+ " LOCATION\n");
+ } else if (opts.di_condensed) {
+ printf("TYPE DISK VID PID"
+ " SERIAL\n");
+ printf("\tSIZE FLRS LOCATION\n");
+ } else {
+ printf("TYPE DISK VID PID"
+ " SIZE RMV SSD\n");
+ }
+ }
+
+ enumerate_disks(&opts);
+
+ return (0);
+}
diff --git a/usr/src/man/man1m/Makefile b/usr/src/man/man1m/Makefile
index 337b29fc18..fb87a94fdc 100644
--- a/usr/src/man/man1m/Makefile
+++ b/usr/src/man/man1m/Makefile
@@ -99,6 +99,7 @@ _MANFILES= 6to4relay.1m \
dfshares.1m \
dfshares_nfs.1m \
dhcpagent.1m \
+ diskinfo.1m \
disks.1m \
diskscan.1m \
dispadmin.1m \
diff --git a/usr/src/man/man1m/diskinfo.1m b/usr/src/man/man1m/diskinfo.1m
new file mode 100644
index 0000000000..867592fef9
--- /dev/null
+++ b/usr/src/man/man1m/diskinfo.1m
@@ -0,0 +1,191 @@
+.\"
+.\" This file and its contents are supplied under the terms of the
+.\" Common Development and Distribution License ("CDDL"), version 1.0.
+.\" You may only use this file in accordance with the terms of version
+.\" 1.0 of the CDDL.
+.\"
+.\" A full copy of the text of the CDDL should have accompanied this
+.\" source. A copy of the CDDL is also available via the Internet at
+.\" http://www.illumos.org/license/CDDL.
+.\"
+.\" Copyright 2014 Joyent, Inc.
+.\" Copyright 2016 Nexenta Systems, Inc.
+.\"
+.Dd July 20, 2016
+.Dt DISKINFO 1M
+.Os
+.Sh NAME
+.Nm diskinfo
+.Nd provide disk device inventory and status
+.Sh SYNOPSIS
+.Nm
+.Op Fl Hp
+.Op Fl c Ns | Ns Fl P
+.Sh DESCRIPTION
+The diskinfo tool provides information about the disk devices in the system.
+Because it interacts with the kernel's device management subsystem, this tool
+can be used only from the global zone.
+If run in any other zone, its output will be incomplete and unreliable.
+.Pp
+There are three main modes.
+The default mode, when neither the
+.Fl c
+nor
+.Fl P
+option is specified, provides a basic inventory of the disk devices in the
+system.
+Each line describes a single device and contains the device's attachment bus or
+fabric type, the base name of the device in the
+.Pa /dev/dsk
+directory, the disk's vendor and product identification strings, the size
+.Pq storage capacity
+of the device, whether the device is removable, and whether it is solid-state.
+.Pp
+The
+.Fl P
+option selects physical mode.
+In this mode, each line of output likewise describes one disk device; however,
+the fields provided indicate the base name of the device in the
+.Pa /dev/dsk
+directory, the disk's vendor and product identification strings, the serial number of the
+device, whether the device is faulty as diagnosed by
+.Xr fmd 1M ,
+whether the locate or identification indicator is on for the device
+.Pq if one is present ,
+and the chassis and bay number containing the disk if known.
+.Pp
+The
+.Fl c
+option selects compact mode.
+This mode provides all of the information provided by both the default mode and
+physical mode in a compact format.
+.Pp
+See
+.Sx OUTPUT FIELDS
+below for a detailed description of each column.
+.Sh OPTIONS
+.Bl -tag -width Ds
+.It Fl c
+Select compact mode output.
+At most one of
+.Fl c
+and
+.Fl P
+may be present on the command line.
+.It Fl H
+Do not print a header.
+This provides output suitable for passing into text processing tools.
+.It Fl P
+Select physical mode output.
+At most one of
+.Fl P
+and
+.Fl c
+may be present on the command line.
+.It Fl p
+Parsable output.
+When
+.Fl p
+is selected, the size
+.Pq storage capacity
+is output in bytes instead of in human-readable units, and the device's location
+.Pq if known
+is provided as a comma-separated chassis and bay number instead of a
+human-readable location.
+This option may be used in any output mode and is intended for use by scripts or
+other robotic tooling.
+.El
+.Sh OUTPUT FIELDS
+.Bl -tag -width "LOCATION"
+.It Sy DISK
+The base name of the device node within the
+.Pa /dev/dsk
+directory.
+The names of partitions and/or slices, if any, are derived from this name as
+described by
+.Xr prtvtoc 1M .
+.Pp
+This field is available in all output modes.
+.It Sy FLRS
+A condensed field incorporating the same information as the
+.Sy FLT , LOC , RMV ,
+and
+.Sy SSD
+fields.
+Each field is condensed to a single character.
+If the field is true, the first letter of the field name will appear in its
+position in the string; otherwise, the
+.Qq Sy -
+character will appear instead.
+.Pp
+This field is available only in compact output mode.
+.It Sy FLT
+A boolean field indicating whether the device is faulty; specifically, whether
+the fault indicator
+.Pq if one is present
+is active.
+.Pp
+This field is available only in physical output mode.
+.It Sy LOC
+A boolean field indicating whether the locate or identify indicator, if any,
+associated with the device's bay, is active.
+.Pp
+This field is available only in physical output mode.
+.It Sy LOCATION
+The physical chassis and bay name
+.Po or chassis and bay numbers, if
+.Fl p
+is given
+.Pc
+in which the device is located.
+The chassis number is identified in human-readable output within
+.Bq square brackets ;
+chassis 0 is the host chassis itself.
+The bay name, if any, is provided by the enclosure, typically via a SCSI
+Enclosure Services processor.
+.Pp
+This field is available in compact and physical output modes.
+.It Sy PID
+The product identification string reported by the device.
+.Pp
+This field is available in all output modes.
+.It Sy RMV
+A boolean field indicating whether the device is removable.
+USB storage devices, most optical drives and changers, and certain other devices
+that report themselves as removable will be identified as such.
+.Pp
+This field is available only in default output mode.
+.It Sy SERIAL
+The serial number of the device. The entire serial number is reported if the
+device and its drivers provide it.
+.Pp
+This field is available in compact and physical output modes.
+.It Sy SIZE
+The device's storage capacity.
+If the
+.Fl p
+option is given, this is reported in bytes; otherwise, it is reported in a
+human-readable format with units specified.
+All units are based on powers of 2 and are expressed in SI standard notation.
+.Pp
+This field is available in compact and default output modes.
+.It Sy SSD
+A boolean field indicating whether the device is solid-state.
+.Pp
+This field is available only in default output mode.
+.It Sy TYPE
+The transport
+.Pq fabric or bus
+type by which the storage device is attached to the host, if known.
+Typical transports include SCSI and USB.
+.Pp
+This field is available in compact and default output modes.
+.It Sy VID
+The vendor identification string reported by the device.
+.Pp
+This field is available in all output modes.
+.El
+.Sh SEE ALSO
+.Xr fmd 1M ,
+.Xr prtvtoc 1M ,
+.Xr sd 7D
diff --git a/usr/src/pkg/manifests/diagnostic-diskinfo.mf b/usr/src/pkg/manifests/diagnostic-diskinfo.mf
new file mode 100644
index 0000000000..a7a62def0d
--- /dev/null
+++ b/usr/src/pkg/manifests/diagnostic-diskinfo.mf
@@ -0,0 +1,33 @@
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source. A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright 2016 Nexenta Systems, Inc.
+#
+
+#
+# The default for payload-bearing actions in this package is to appear in the
+# global zone only. See the include file for greater detail, as well as
+# information about overriding the defaults.
+#
+<include global_zone_only_component>
+set name=pkg.fmri value=pkg:/diagnostic/diskinfo@$(PKGVERS)
+set name=pkg.description value=diskinfo
+set name=pkg.summary value=diskinfo
+set name=info.classification \
+ value="org.opensolaris.category.2008:Applications/System Utilities"
+set name=variant.arch value=$(ARCH)
+dir path=usr group=sys
+dir path=usr/sbin
+dir path=usr/share/man/man1m
+file path=usr/sbin/diskinfo mode=0555
+file path=usr/share/man/man1m/diskinfo.1m mode=0444
+license lic_CDDL license=lic_CDDL
diff --git a/usr/src/uts/common/io/12x22.c b/usr/src/uts/common/io/12x22.c
index 0efeaf386d..43c5683e34 100644
--- a/usr/src/uts/common/io/12x22.c
+++ b/usr/src/uts/common/io/12x22.c
@@ -5239,7 +5239,7 @@ static unsigned char *ENCODINGS_12x22[256] = {
FONTDATA_12x22+6908+748,
FONTDATA_12x22+6952+748,
FONTDATA_12x22+6996+748,
- FONTDATA_12x22+7480+748,
+ FONTDATA_12x22+7040+748,
FONTDATA_12x22+7084+748,
FONTDATA_12x22+7128+748,
FONTDATA_12x22+7172+748,