Print this page
8708 Want diskinfo(1m) to list all disk bays, including those don't have disk installed
@@ -28,32 +28,45 @@
#include <libdiskmgt.h>
#include <sys/nvpair.h>
#include <sys/param.h>
#include <sys/ccompile.h>
+#include <sys/list.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_allslots;
boolean_t di_scripted;
boolean_t di_parseable;
boolean_t di_physical;
boolean_t di_condensed;
} di_opts_t;
+static list_t g_disks;
+static di_opts_t g_opts = { B_FALSE, B_FALSE, B_FALSE, B_FALSE, B_FALSE };
+
typedef struct di_phys {
- const char *dp_dev;
- const char *dp_serial;
- const char *dp_slotname;
+ uint64_t dp_size;
+ uint32_t dp_blksize;
+ char *dp_vid;
+ char *dp_pid;
+ boolean_t dp_removable;
+ boolean_t dp_ssd;
+ char *dp_dev;
+ char *dp_ctype;
+ char *dp_serial;
+ char *dp_slotname;
int dp_chassis;
int dp_slot;
int dp_faulty;
int dp_locate;
+ list_node_t dp_next;
} di_phys_t;
static void __NORETURN
fatal(int rv, const char *fmt, ...)
{
@@ -64,14 +77,47 @@
va_end(ap);
exit(rv);
}
+static void *
+safe_zmalloc(size_t size)
+{
+ void *ptr = malloc(size);
+ if (ptr == NULL)
+ fatal(-1, "failed to allocate memeory");
+ memset(ptr, 0, size);
+ return (ptr);
+}
+
+static char *
+safe_strdup(const char *s1)
+{
+ char *s2 = strdup(s1);
+ if (s2 == NULL)
+ fatal(-1, "failed to allocate memeory");
+ return (s2);
+}
+
+static int
+safe_asprintf(char **ret, const char *fmt, ...)
+{
+ va_list ap;
+ int v;
+
+ va_start(ap, fmt);
+ v = vasprintf(ret, fmt, ap);
+ va_end(ap);
+ if (v == -1)
+ fatal(-1, "failed to allocate memeory");
+ return (v);
+}
+
static void
usage(const char *execname)
{
- (void) fprintf(stderr, "Usage: %s [-Hp] [{-c|-P}]\n", execname);
+ (void) fprintf(stderr, "Usage: %s [-aHp] [{-c|-P}]\n", execname);
}
static void
nvlist_query_string(nvlist_t *nvl, const char *label, char **val)
{
@@ -104,43 +150,24 @@
if (val == 1)
return (c);
return ('?');
}
-static int
-disk_walker(topo_hdl_t *hp, tnode_t *np, void *arg)
+
+static void
+set_disk_bay_info(topo_hdl_t *hp, tnode_t *np, di_phys_t *dip)
{
- 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;
+ int err;
- if (strcmp(topo_node_name(np), DISK) != 0)
- return (TOPO_WALK_NEXT);
+ if (strcmp(topo_node_name(np), BAY) != 0)
+ return;
- 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,
+ if (topo_node_facility(hp, np, 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)) {
uint32_t prop;
@@ -158,304 +185,400 @@
}
mode = (topo_led_state_t)prop;
switch (type) {
case TOPO_LED_TYPE_SERVICE:
- pp->dp_faulty = mode ? 1 : 0;
+ dip->dp_faulty = mode ? 1 : 0;
break;
case TOPO_LED_TYPE_LOCATE:
- pp->dp_locate = mode ? 1 : 0;
+ dip->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;
+ if (topo_prop_get_string(np, TOPO_PGROUP_PROTOCOL,
+ TOPO_PROP_LABEL, &dip->dp_slotname, &err) == 0) {
+ dip->dp_slotname = safe_strdup(dip->dp_slotname);
}
- pp->dp_slot = topo_node_instance(pnp);
+ dip->dp_slot = topo_node_instance(np);
+ dip->dp_chassis = topo_node_instance(topo_node_parent(np));
+}
+
+static int
+bay_walker(topo_hdl_t *hp, tnode_t *np, void *arg)
+{
+ di_phys_t *dip;
+ int slot, chassis;
+
+ if (strcmp(topo_node_name(np), BAY) != 0)
+ return (TOPO_WALK_NEXT);
+
+ slot = topo_node_instance(np);
+ chassis = topo_node_instance(topo_node_parent(np));
+
+ for (dip = list_head(&g_disks); dip != NULL;
+ dip = list_next(&g_disks, dip)) {
+ if (dip->dp_slot == slot && dip->dp_chassis == chassis)
+ return (TOPO_WALK_NEXT);
}
- pp->dp_chassis = topo_node_instance(ppnp);
+ dip = safe_zmalloc(sizeof (di_phys_t));
+ set_disk_bay_info(hp, np, dip);
+ list_insert_tail(&g_disks, dip);
+ return (TOPO_WALK_NEXT);
+}
- return (TOPO_WALK_TERMINATE);
+static int
+disk_walker(topo_hdl_t *hp, tnode_t *np, void *arg)
+{
+ char *dev;
+ di_phys_t *dip;
+ int err;
+
+ 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, &dev, &err) != 0) {
+ return (TOPO_WALK_NEXT);
+ }
+
+ for (dip = list_head(&g_disks); dip != NULL;
+ dip = list_next(&g_disks, dip)) {
+ if (strcmp(dip->dp_dev, dev) == 0) {
+ if (topo_prop_get_string(np, TOPO_PGROUP_STORAGE,
+ TOPO_STORAGE_SERIAL_NUM,
+ &dip->dp_serial, &err) == 0) {
+ dip->dp_serial = safe_strdup(dip->dp_serial);
+ }
+ set_disk_bay_info(hp, topo_node_parent(np), dip);
+ }
+ }
+ return (TOPO_WALK_NEXT);
}
static void
-populate_physical(topo_hdl_t *hp, di_phys_t *pp)
+walk_topo_snapshot(topo_hdl_t *hp, topo_walk_cb_t cb)
{
- int err;
+ int err = 0;
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) {
+ if ((wp = topo_walk_init(hp, FM_FMRI_SCHEME_HC, cb, NULL,
+ &err)) == 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)
+enumerate_disks()
{
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;
+ nvlist_t *mattrs, *dattrs, *cattrs;
- 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;
+ char *s, *c;
+ di_phys_t *dip;
size_t len;
+ int err, i;
+ list_create(&g_disks, sizeof (di_phys_t), offsetof(di_phys_t, dp_next));
+
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;
}
+ dip = safe_zmalloc(sizeof (di_phys_t));
+
mattrs = dm_get_attributes(media[i], &err);
- err = nvlist_lookup_uint64(mattrs, DM_SIZE, &size);
+ err = nvlist_lookup_uint64(mattrs, DM_SIZE, &dip->dp_size);
assert(err == 0);
- err = nvlist_lookup_uint32(mattrs, DM_BLOCKSIZE, &blocksize);
+ err = nvlist_lookup_uint32(mattrs, DM_BLOCKSIZE,
+ &dip->dp_blksize);
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);
+ nvlist_query_string(dattrs, DM_VENDOR_ID, &dip->dp_vid);
+ nvlist_query_string(dattrs, DM_PRODUCT_ID, &dip->dp_pid);
+ nvlist_query_string(dattrs, DM_OPATH, &dip->dp_dev);
- removable = B_FALSE;
+ dip->dp_vid = safe_strdup(dip->dp_vid);
+ dip->dp_pid = safe_strdup(dip->dp_pid);
+ dip->dp_dev = safe_strdup(dip->dp_dev);
+
+ dip->dp_removable = B_FALSE;
if (nvlist_lookup_boolean(dattrs, DM_REMOVABLE) == 0)
- removable = B_TRUE;
+ dip->dp_removable = B_TRUE;
- ssd = B_FALSE;
+ dip->dp_ssd = B_FALSE;
if (nvlist_lookup_boolean(dattrs, DM_SOLIDSTATE) == 0)
- ssd = B_TRUE;
+ dip->dp_ssd = B_TRUE;
+ nvlist_free(dattrs);
+
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++)
+ nvlist_query_string(cattrs, DM_CTYPE, &dip->dp_ctype);
+ dip->dp_ctype = safe_strdup(dip->dp_ctype);
+ for (c = dip->dp_ctype; *c != '\0'; c++)
*c = toupper(*c);
+ nvlist_free(cattrs);
}
+ dm_free_descriptors(controller);
+ dm_free_descriptors(disk);
+
/*
* 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';
+ if ((c = strrchr(dip->dp_dev, '/')) != NULL) {
+ s = dip->dp_dev;
+ while ((*s++ = *++c))
+ ;
+ }
+ len = strlen(dip->dp_dev);
+ if (dip->dp_dev[len - 2] == 's' &&
+ dip->dp_dev[len - 1] >= '0' &&
+ dip->dp_dev[len - 1] <= '9')
+ dip->dp_dev[len - 2] = '\0';
- bzero(&phys, sizeof (phys));
- phys.dp_dev = device;
- populate_physical(hp, &phys);
+ dip->dp_faulty = dip->dp_locate = -1;
+ dip->dp_chassis = dip->dp_slot = -1;
+ list_insert_tail(&g_disks, dip);
+ }
+ dm_free_descriptors(media);
+
/*
+ * Walk toplogy information to populate serial, chassis,
+ * slot, faulty and locator information.
+ */
+
+ 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));
+ }
+
+ walk_topo_snapshot(hp, disk_walker);
+
+ if (g_opts.di_allslots)
+ walk_topo_snapshot(hp, bay_walker);
+
+ topo_snap_release(hp);
+ topo_close(hp);
+}
+
+static void
+show_disks()
+{
+ uint64_t total;
+ double total_in_GiB;
+ char *sizestr = NULL, *slotname = NULL, *statestr = NULL;
+ di_phys_t *dip;
+
+ for (dip = list_head(&g_disks); dip != NULL;
+ dip = list_next(&g_disks, dip)) {
+ /*
* 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;
+ total = dip->dp_size * dip->dp_blksize;
- if (opts->di_parseable) {
- (void) snprintf(sizestr, sizeof (sizestr),
- "%llu", total);
+ if (g_opts.di_parseable) {
+ (void) safe_asprintf(&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);
+ (void) safe_asprintf(&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);
+ if (g_opts.di_parseable) {
+ (void) safe_asprintf(&slotname, "%d,%d",
+ dip->dp_chassis, dip->dp_slot);
+ } else if (dip->dp_slotname != NULL) {
+ (void) safe_asprintf(&slotname, "[%d] %s",
+ dip->dp_chassis, dip->dp_slotname);
} else {
- slotname[0] = '-';
- slotname[1] = '\0';
+ slotname = safe_strdup("-");
}
- 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 (g_opts.di_condensed) {
+ (void) safe_asprintf(&statestr, "%c%c%c%c",
+ condensed_tristate(dip->dp_faulty, 'F'),
+ condensed_tristate(dip->dp_locate, 'L'),
+ condensed_tristate(dip->dp_removable, 'R'),
+ condensed_tristate(dip->dp_ssd, 'S'));
}
- if (opts->di_physical) {
- if (opts->di_scripted) {
+ if (g_opts.di_physical) {
+ if (g_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);
+ display_string(dip->dp_dev),
+ display_string(dip->dp_vid),
+ display_string(dip->dp_pid),
+ display_string(dip->dp_serial),
+ display_tristate(dip->dp_faulty),
+ display_tristate(dip->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);
+ display_string(dip->dp_dev),
+ display_string(dip->dp_vid),
+ display_string(dip->dp_pid),
+ display_string(dip->dp_serial),
+ display_tristate(dip->dp_faulty),
+ display_tristate(dip->dp_locate), slotname);
}
- } else if (opts->di_condensed) {
- if (opts->di_scripted) {
+ } else if (g_opts.di_condensed) {
+ if (g_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),
+ display_string(dip->dp_ctype),
+ display_string(dip->dp_dev),
+ display_string(dip->dp_vid),
+ display_string(dip->dp_pid),
+ display_string(dip->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),
+ display_string(dip->dp_ctype),
+ display_string(dip->dp_dev),
+ display_string(dip->dp_vid),
+ display_string(dip->dp_pid),
+ display_string(dip->dp_serial),
sizestr, statestr, slotname);
}
} else {
- if (opts->di_scripted) {
+ if (g_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));
+ display_string(dip->dp_ctype),
+ display_string(dip->dp_dev),
+ display_string(dip->dp_vid),
+ display_string(dip->dp_pid), sizestr,
+ display_tristate(dip->dp_removable),
+ display_tristate(dip->dp_ssd));
} else {
printf("%-7s %-22s %-8s %-16s "
- "%-13s %-3s %-3s\n", ctype, device,
- vid, pid, sizestr,
- display_tristate(removable),
- display_tristate(ssd));
+ "%-13s %-3s %-3s\n",
+ display_string(dip->dp_ctype),
+ display_string(dip->dp_dev),
+ display_string(dip->dp_vid),
+ display_string(dip->dp_pid), sizestr,
+ display_tristate(dip->dp_removable),
+ display_tristate(dip->dp_ssd));
}
}
-
- free(ctype);
- nvlist_free(cattrs);
- nvlist_free(dattrs);
- dm_free_descriptors(controller);
- dm_free_descriptors(disk);
+ free(sizestr); free(slotname); free(statestr);
+ sizestr = slotname = statestr = NULL;
}
+}
- dm_free_descriptors(media);
- topo_snap_release(hp);
- topo_close(hp);
+static void
+cleanup()
+{
+ di_phys_t *dip;
+ while ((dip = list_head(&g_disks)) != NULL) {
+ list_remove(&g_disks, dip);
+ free(dip->dp_vid);
+ free(dip->dp_pid);
+ free(dip->dp_dev);
+ free(dip->dp_ctype);
+ free(dip->dp_serial);
+ free(dip->dp_slotname);
+ free(dip);
+ }
+ list_destroy(&g_disks);
}
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) {
+ while ((c = getopt(argc, argv, ":acHPp")) != EOF) {
switch (c) {
+ case 'a':
+ g_opts.di_allslots = B_TRUE;
+ break;
case 'c':
- if (opts.di_physical) {
- usage(argv[0]);
- fatal(1, "-c and -P are mutually exclusive\n");
- }
- opts.di_condensed = B_TRUE;
+ g_opts.di_condensed = B_TRUE;
break;
case 'H':
- opts.di_scripted = B_TRUE;
+ g_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;
+ g_opts.di_physical = B_TRUE;
break;
case 'p':
- opts.di_parseable = B_TRUE;
+ g_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) {
+ if (g_opts.di_condensed && g_opts.di_physical) {
+ usage(argv[0]);
+ fatal(1, "-c and -P are mutually exclusive\n");
+ }
+
+ if (!g_opts.di_scripted) {
+ if (g_opts.di_physical) {
printf("DISK VID PID"
" SERIAL FLT LOC"
" LOCATION\n");
- } else if (opts.di_condensed) {
+ } else if (g_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);
+ enumerate_disks();
+ show_disks();
+ cleanup();
return (0);
}