Print this page
8708 Want diskinfo(1m) to list all disk bays, including those don't have disk installed

Split Close
Expand all
Collapse all
          --- old/usr/src/cmd/diskinfo/diskinfo.c
          +++ new/usr/src/cmd/diskinfo/diskinfo.c
↓ open down ↓ 22 lines elided ↑ open up ↑
  23   23  #include <limits.h>
  24   24  #include <assert.h>
  25   25  #include <ctype.h>
  26   26  #include <stdarg.h>
  27   27  #include <strings.h>
  28   28  
  29   29  #include <libdiskmgt.h>
  30   30  #include <sys/nvpair.h>
  31   31  #include <sys/param.h>
  32   32  #include <sys/ccompile.h>
       33 +#include <sys/list.h>
  33   34  
  34   35  #include <fm/libtopo.h>
  35   36  #include <fm/topo_hc.h>
  36   37  #include <fm/topo_list.h>
  37   38  #include <sys/fm/protocol.h>
  38   39  #include <modules/common/disk/disk.h>
  39   40  
  40   41  typedef struct di_opts {
       42 +        boolean_t di_allslots;
  41   43          boolean_t di_scripted;
  42   44          boolean_t di_parseable;
  43   45          boolean_t di_physical;
  44   46          boolean_t di_condensed;
  45   47  } di_opts_t;
  46   48  
       49 +static list_t g_disks;
       50 +static di_opts_t g_opts = { B_FALSE, B_FALSE, B_FALSE, B_FALSE, B_FALSE };
       51 +
  47   52  typedef struct di_phys {
  48      -        const char *dp_dev;
  49      -        const char *dp_serial;
  50      -        const char *dp_slotname;
       53 +        uint64_t dp_size;
       54 +        uint32_t dp_blksize;
       55 +        char *dp_vid;
       56 +        char *dp_pid;
       57 +        boolean_t dp_removable;
       58 +        boolean_t dp_ssd;
       59 +        char *dp_dev;
       60 +        char *dp_ctype;
       61 +        char *dp_serial;
       62 +        char *dp_slotname;
  51   63          int dp_chassis;
  52   64          int dp_slot;
  53   65          int dp_faulty;
  54   66          int dp_locate;
       67 +        list_node_t dp_next;
  55   68  } di_phys_t;
  56   69  
  57   70  static void __NORETURN
  58   71  fatal(int rv, const char *fmt, ...)
  59   72  {
  60   73          va_list ap;
  61   74  
  62   75          va_start(ap, fmt);
  63   76          (void) vfprintf(stderr, fmt, ap);
  64   77          va_end(ap);
  65   78  
  66   79          exit(rv);
  67   80  }
  68   81  
       82 +static void *
       83 +safe_zmalloc(size_t size)
       84 +{
       85 +        void *ptr = malloc(size);
       86 +        if (ptr == NULL)
       87 +                fatal(-1, "failed to allocate memeory");
       88 +        memset(ptr, 0, size);
       89 +        return (ptr);
       90 +}
       91 +
       92 +static char *
       93 +safe_strdup(const char *s1)
       94 +{
       95 +        char *s2 = strdup(s1);
       96 +        if (s2 == NULL)
       97 +                fatal(-1, "failed to allocate memeory");
       98 +        return (s2);
       99 +}
      100 +
      101 +static int
      102 +safe_asprintf(char **ret, const char *fmt, ...)
      103 +{
      104 +        va_list ap;
      105 +        int v;
      106 +
      107 +        va_start(ap, fmt);
      108 +        v = vasprintf(ret, fmt, ap);
      109 +        va_end(ap);
      110 +        if (v == -1)
      111 +                fatal(-1, "failed to allocate memeory");
      112 +        return (v);
      113 +}
      114 +
  69  115  static void
  70  116  usage(const char *execname)
  71  117  {
  72      -        (void) fprintf(stderr, "Usage: %s [-Hp] [{-c|-P}]\n", execname);
      118 +        (void) fprintf(stderr, "Usage: %s [-aHp] [{-c|-P}]\n", execname);
  73  119  }
  74  120  
  75  121  static void
  76  122  nvlist_query_string(nvlist_t *nvl, const char *label, char **val)
  77  123  {
  78  124          if (nvlist_lookup_string(nvl, label, val) != 0)
  79  125                  *val = "-";
  80  126  }
  81  127  
  82  128  static const char *
↓ open down ↓ 16 lines elided ↑ open up ↑
  99  145  static char
 100  146  condensed_tristate(int val, char c)
 101  147  {
 102  148          if (val == 0)
 103  149                  return ('-');
 104  150          if (val == 1)
 105  151                  return (c);
 106  152  
 107  153          return ('?');
 108  154  }
 109      -static int
 110      -disk_walker(topo_hdl_t *hp, tnode_t *np, void *arg)
      155 +
      156 +static void
      157 +set_disk_bay_info(topo_hdl_t *hp, tnode_t *np, di_phys_t *dip)
 111  158  {
 112      -        di_phys_t *pp = arg;
 113      -        tnode_t *pnp;
 114      -        tnode_t *ppnp;
 115  159          topo_faclist_t fl;
 116  160          topo_faclist_t *lp;
 117      -        int err;
 118  161          topo_led_state_t mode;
 119  162          topo_led_type_t type;
 120      -        char *name, *slotname, *serial;
      163 +        int err;
 121  164  
 122      -        if (strcmp(topo_node_name(np), DISK) != 0)
 123      -                return (TOPO_WALK_NEXT);
      165 +        if (strcmp(topo_node_name(np), BAY) != 0)
      166 +                return;
 124  167  
 125      -        if (topo_prop_get_string(np, TOPO_PGROUP_STORAGE,
 126      -            TOPO_STORAGE_LOGICAL_DISK_NAME, &name, &err) != 0) {
 127      -                return (TOPO_WALK_NEXT);
 128      -        }
      168 +        if (topo_node_facility(hp, np, TOPO_FAC_TYPE_INDICATOR,
      169 +            TOPO_FAC_TYPE_ANY, &fl, &err) == 0) {
      170 +                for (lp = topo_list_next(&fl.tf_list); lp != NULL;
      171 +                    lp = topo_list_next(lp)) {
      172 +                        uint32_t prop;
 129  173  
 130      -        if (strcmp(name, pp->dp_dev) != 0)
 131      -                return (TOPO_WALK_NEXT);
      174 +                        if (topo_prop_get_uint32(lp->tf_node,
      175 +                            TOPO_PGROUP_FACILITY, TOPO_FACILITY_TYPE,
      176 +                            &prop, &err) != 0) {
      177 +                                continue;
      178 +                        }
      179 +                        type = (topo_led_type_t)prop;
 132  180  
 133      -        if (topo_prop_get_string(np, TOPO_PGROUP_STORAGE,
 134      -            TOPO_STORAGE_SERIAL_NUM, &serial, &err) == 0) {
 135      -                pp->dp_serial = serial;
      181 +                        if (topo_prop_get_uint32(lp->tf_node,
      182 +                            TOPO_PGROUP_FACILITY, TOPO_LED_MODE,
      183 +                            &prop, &err) != 0) {
      184 +                                continue;
      185 +                        }
      186 +                        mode = (topo_led_state_t)prop;
      187 +
      188 +                        switch (type) {
      189 +                        case TOPO_LED_TYPE_SERVICE:
      190 +                                dip->dp_faulty = mode ? 1 : 0;
      191 +                                break;
      192 +                        case TOPO_LED_TYPE_LOCATE:
      193 +                                dip->dp_locate = mode ? 1 : 0;
      194 +                                break;
      195 +                        default:
      196 +                                break;
      197 +                        }
      198 +                }
 136  199          }
 137  200  
 138      -        pnp = topo_node_parent(np);
 139      -        ppnp = topo_node_parent(pnp);
 140      -        if (strcmp(topo_node_name(pnp), BAY) == 0) {
 141      -                if (topo_node_facility(hp, pnp, TOPO_FAC_TYPE_INDICATOR,
 142      -                    TOPO_FAC_TYPE_ANY, &fl, &err) == 0) {
 143      -                        for (lp = topo_list_next(&fl.tf_list); lp != NULL;
 144      -                            lp = topo_list_next(lp)) {
 145      -                                uint32_t prop;
      201 +        if (topo_prop_get_string(np, TOPO_PGROUP_PROTOCOL,
      202 +            TOPO_PROP_LABEL, &dip->dp_slotname, &err) == 0) {
      203 +                dip->dp_slotname = safe_strdup(dip->dp_slotname);
      204 +        }
 146  205  
 147      -                                if (topo_prop_get_uint32(lp->tf_node,
 148      -                                    TOPO_PGROUP_FACILITY, TOPO_FACILITY_TYPE,
 149      -                                    &prop, &err) != 0) {
 150      -                                        continue;
 151      -                                }
 152      -                                type = (topo_led_type_t)prop;
      206 +        dip->dp_slot = topo_node_instance(np);
      207 +        dip->dp_chassis = topo_node_instance(topo_node_parent(np));
      208 +}
 153  209  
 154      -                                if (topo_prop_get_uint32(lp->tf_node,
 155      -                                    TOPO_PGROUP_FACILITY, TOPO_LED_MODE,
 156      -                                    &prop, &err) != 0) {
 157      -                                        continue;
 158      -                                }
 159      -                                mode = (topo_led_state_t)prop;
      210 +static int
      211 +bay_walker(topo_hdl_t *hp, tnode_t *np, void *arg)
      212 +{
      213 +        di_phys_t *dip;
      214 +        int slot, chassis;
 160  215  
 161      -                                switch (type) {
 162      -                                case TOPO_LED_TYPE_SERVICE:
 163      -                                        pp->dp_faulty = mode ? 1 : 0;
 164      -                                        break;
 165      -                                case TOPO_LED_TYPE_LOCATE:
 166      -                                        pp->dp_locate = mode ? 1 : 0;
 167      -                                        break;
 168      -                                default:
 169      -                                        break;
 170      -                                }
 171      -                        }
 172      -                }
      216 +        if (strcmp(topo_node_name(np), BAY) != 0)
      217 +                return (TOPO_WALK_NEXT);
 173  218  
 174      -                if (topo_prop_get_string(pnp, TOPO_PGROUP_PROTOCOL,
 175      -                    TOPO_PROP_LABEL, &slotname, &err) == 0) {
 176      -                        pp->dp_slotname = slotname;
 177      -                }
      219 +        slot = topo_node_instance(np);
      220 +        chassis = topo_node_instance(topo_node_parent(np));
 178  221  
 179      -                pp->dp_slot = topo_node_instance(pnp);
      222 +        for (dip = list_head(&g_disks); dip != NULL;
      223 +            dip = list_next(&g_disks, dip)) {
      224 +                if (dip->dp_slot == slot && dip->dp_chassis == chassis)
      225 +                        return (TOPO_WALK_NEXT);
 180  226          }
 181  227  
 182      -        pp->dp_chassis = topo_node_instance(ppnp);
      228 +        dip = safe_zmalloc(sizeof (di_phys_t));
      229 +        set_disk_bay_info(hp, np, dip);
      230 +        list_insert_tail(&g_disks, dip);
      231 +        return (TOPO_WALK_NEXT);
      232 +}
 183  233  
 184      -        return (TOPO_WALK_TERMINATE);
      234 +static int
      235 +disk_walker(topo_hdl_t *hp, tnode_t *np, void *arg)
      236 +{
      237 +        char *dev;
      238 +        di_phys_t *dip;
      239 +        int err;
      240 +
      241 +        if (strcmp(topo_node_name(np), DISK) != 0)
      242 +                return (TOPO_WALK_NEXT);
      243 +
      244 +        if (topo_prop_get_string(np, TOPO_PGROUP_STORAGE,
      245 +            TOPO_STORAGE_LOGICAL_DISK_NAME, &dev, &err) != 0) {
      246 +                return (TOPO_WALK_NEXT);
      247 +        }
      248 +
      249 +        for (dip = list_head(&g_disks); dip != NULL;
      250 +            dip = list_next(&g_disks, dip)) {
      251 +                if (strcmp(dip->dp_dev, dev) == 0) {
      252 +                        if (topo_prop_get_string(np, TOPO_PGROUP_STORAGE,
      253 +                            TOPO_STORAGE_SERIAL_NUM,
      254 +                            &dip->dp_serial, &err) == 0) {
      255 +                                dip->dp_serial = safe_strdup(dip->dp_serial);
      256 +                        }
      257 +                        set_disk_bay_info(hp, topo_node_parent(np), dip);
      258 +                }
      259 +        }
      260 +        return (TOPO_WALK_NEXT);
 185  261  }
 186  262  
 187  263  static void
 188      -populate_physical(topo_hdl_t *hp, di_phys_t *pp)
      264 +walk_topo_snapshot(topo_hdl_t *hp, topo_walk_cb_t cb)
 189  265  {
 190      -        int err;
      266 +        int err = 0;
 191  267          topo_walk_t *wp;
 192  268  
 193      -        pp->dp_faulty = pp->dp_locate = -1;
 194      -        pp->dp_chassis = pp->dp_slot = -1;
 195      -
 196      -        err = 0;
 197      -        wp = topo_walk_init(hp, FM_FMRI_SCHEME_HC, disk_walker, pp, &err);
 198      -        if (wp == NULL) {
      269 +        if ((wp = topo_walk_init(hp, FM_FMRI_SCHEME_HC, cb, NULL,
      270 +            &err)) == NULL) {
 199  271                  fatal(-1, "unable to initialise topo walker: %s",
 200  272                      topo_strerror(err));
 201  273          }
 202  274  
 203  275          while ((err = topo_walk_step(wp, TOPO_WALK_CHILD)) == TOPO_WALK_NEXT)
 204  276                  ;
 205  277  
 206  278          if (err == TOPO_WALK_ERR)
 207  279                  fatal(-1, "topo walk failed");
 208      -
 209  280          topo_walk_fini(wp);
 210  281  }
 211  282  
 212  283  static void
 213      -enumerate_disks(di_opts_t *opts)
      284 +enumerate_disks()
 214  285  {
 215  286          topo_hdl_t *hp;
 216  287          dm_descriptor_t *media;
 217      -        int err, i;
 218  288          int filter[] = { DM_DT_FIXED, -1 };
 219  289          dm_descriptor_t *disk, *controller;
 220      -        nvlist_t *mattrs, *dattrs, *cattrs = NULL;
      290 +        nvlist_t *mattrs, *dattrs, *cattrs;
 221  291  
 222      -        uint64_t size, total;
 223      -        uint32_t blocksize;
 224      -        double total_in_GiB;
 225      -        char sizestr[32];
 226      -        char slotname[32];
 227      -        char statestr[8];
 228      -
 229      -        char *vid, *pid, *opath, *c, *ctype = NULL;
 230      -        boolean_t removable;
 231      -        boolean_t ssd;
 232      -        char device[MAXPATHLEN];
 233      -        di_phys_t phys;
      292 +        char *s, *c;
      293 +        di_phys_t *dip;
 234  294          size_t len;
      295 +        int err, i;
 235  296  
      297 +        list_create(&g_disks, sizeof (di_phys_t), offsetof(di_phys_t, dp_next));
      298 +
 236  299          err = 0;
 237  300          if ((media = dm_get_descriptors(DM_MEDIA, filter, &err)) == NULL) {
 238  301                  fatal(-1, "failed to obtain media descriptors: %s\n",
 239  302                      strerror(err));
 240  303          }
 241  304  
 242      -        err = 0;
 243      -        hp = topo_open(TOPO_VERSION, NULL, &err);
 244      -        if (hp == NULL) {
 245      -                fatal(-1, "unable to obtain topo handle: %s",
 246      -                    topo_strerror(err));
 247      -        }
 248      -
 249      -        err = 0;
 250      -        (void) topo_snap_hold(hp, NULL, &err);
 251      -        if (err != 0) {
 252      -                fatal(-1, "unable to hold topo snapshot: %s",
 253      -                    topo_strerror(err));
 254      -        }
 255      -
 256  305          for (i = 0; media != NULL && media[i] != NULL; i++) {
 257  306                  if ((disk = dm_get_associated_descriptors(media[i],
 258  307                      DM_DRIVE, &err)) == NULL) {
 259  308                          continue;
 260  309                  }
 261  310  
      311 +                dip = safe_zmalloc(sizeof (di_phys_t));
      312 +
 262  313                  mattrs = dm_get_attributes(media[i], &err);
 263      -                err = nvlist_lookup_uint64(mattrs, DM_SIZE, &size);
      314 +                err = nvlist_lookup_uint64(mattrs, DM_SIZE, &dip->dp_size);
 264  315                  assert(err == 0);
 265      -                err = nvlist_lookup_uint32(mattrs, DM_BLOCKSIZE, &blocksize);
      316 +                err = nvlist_lookup_uint32(mattrs, DM_BLOCKSIZE,
      317 +                    &dip->dp_blksize);
 266  318                  assert(err == 0);
 267  319                  nvlist_free(mattrs);
 268  320  
 269  321                  dattrs = dm_get_attributes(disk[0], &err);
 270  322  
 271      -                nvlist_query_string(dattrs, DM_VENDOR_ID, &vid);
 272      -                nvlist_query_string(dattrs, DM_PRODUCT_ID, &pid);
 273      -                nvlist_query_string(dattrs, DM_OPATH, &opath);
      323 +                nvlist_query_string(dattrs, DM_VENDOR_ID, &dip->dp_vid);
      324 +                nvlist_query_string(dattrs, DM_PRODUCT_ID, &dip->dp_pid);
      325 +                nvlist_query_string(dattrs, DM_OPATH, &dip->dp_dev);
 274  326  
 275      -                removable = B_FALSE;
      327 +                dip->dp_vid = safe_strdup(dip->dp_vid);
      328 +                dip->dp_pid = safe_strdup(dip->dp_pid);
      329 +                dip->dp_dev = safe_strdup(dip->dp_dev);
      330 +
      331 +                dip->dp_removable = B_FALSE;
 276  332                  if (nvlist_lookup_boolean(dattrs, DM_REMOVABLE) == 0)
 277      -                        removable = B_TRUE;
      333 +                        dip->dp_removable = B_TRUE;
 278  334  
 279      -                ssd = B_FALSE;
      335 +                dip->dp_ssd = B_FALSE;
 280  336                  if (nvlist_lookup_boolean(dattrs, DM_SOLIDSTATE) == 0)
 281      -                        ssd = B_TRUE;
      337 +                        dip->dp_ssd = B_TRUE;
 282  338  
      339 +                nvlist_free(dattrs);
      340 +
 283  341                  if ((controller = dm_get_associated_descriptors(disk[0],
 284  342                      DM_CONTROLLER, &err)) != NULL) {
 285  343                          cattrs = dm_get_attributes(controller[0], &err);
 286      -                        nvlist_query_string(cattrs, DM_CTYPE, &ctype);
 287      -                        ctype = strdup(ctype);
 288      -                        for (c = ctype; *c != '\0'; c++)
      344 +                        nvlist_query_string(cattrs, DM_CTYPE, &dip->dp_ctype);
      345 +                        dip->dp_ctype = safe_strdup(dip->dp_ctype);
      346 +                        for (c = dip->dp_ctype; *c != '\0'; c++)
 289  347                                  *c = toupper(*c);
      348 +                        nvlist_free(cattrs);
 290  349                  }
 291  350  
      351 +                dm_free_descriptors(controller);
      352 +                dm_free_descriptors(disk);
      353 +
 292  354                  /*
 293  355                   * Parse full device path to only show the device name,
 294  356                   * i.e. c0t1d0.  Many paths will reference a particular
 295  357                   * slice (c0t1d0s0), so remove the slice if present.
 296  358                   */
 297      -                if ((c = strrchr(opath, '/')) != NULL)
 298      -                        (void) strlcpy(device, c + 1, sizeof (device));
 299      -                else
 300      -                        (void) strlcpy(device, opath, sizeof (device));
 301      -                len = strlen(device);
 302      -                if (device[len - 2] == 's' &&
 303      -                    (device[len - 1] >= '0' && device[len - 1] <= '9'))
 304      -                        device[len - 2] = '\0';
      359 +                if ((c = strrchr(dip->dp_dev, '/')) != NULL) {
      360 +                        s = dip->dp_dev;
      361 +                        while ((*s++ = *++c))
      362 +                                ;
      363 +                }
      364 +                len = strlen(dip->dp_dev);
      365 +                if (dip->dp_dev[len - 2] == 's' &&
      366 +                    dip->dp_dev[len - 1] >= '0' &&
      367 +                    dip->dp_dev[len - 1] <= '9')
      368 +                        dip->dp_dev[len - 2] = '\0';
 305  369  
 306      -                bzero(&phys, sizeof (phys));
 307      -                phys.dp_dev = device;
 308      -                populate_physical(hp, &phys);
      370 +                dip->dp_faulty = dip->dp_locate = -1;
      371 +                dip->dp_chassis = dip->dp_slot = -1;
      372 +                list_insert_tail(&g_disks, dip);
      373 +        }
 309  374  
      375 +        dm_free_descriptors(media);
      376 +
      377 +        /*
      378 +         * Walk toplogy information to populate serial, chassis,
      379 +         * slot, faulty and locator information.
      380 +         */
      381 +
      382 +        err = 0;
      383 +        hp = topo_open(TOPO_VERSION, NULL, &err);
      384 +        if (hp == NULL) {
      385 +                fatal(-1, "unable to obtain topo handle: %s",
      386 +                    topo_strerror(err));
      387 +        }
      388 +
      389 +        err = 0;
      390 +        (void) topo_snap_hold(hp, NULL, &err);
      391 +        if (err != 0) {
      392 +                fatal(-1, "unable to hold topo snapshot: %s",
      393 +                    topo_strerror(err));
      394 +        }
      395 +
      396 +        walk_topo_snapshot(hp, disk_walker);
      397 +
      398 +        if (g_opts.di_allslots)
      399 +                walk_topo_snapshot(hp, bay_walker);
      400 +
      401 +        topo_snap_release(hp);
      402 +        topo_close(hp);
      403 +}
      404 +
      405 +static void
      406 +show_disks()
      407 +{
      408 +        uint64_t total;
      409 +        double total_in_GiB;
      410 +        char *sizestr = NULL, *slotname = NULL, *statestr = NULL;
      411 +        di_phys_t *dip;
      412 +
      413 +        for (dip = list_head(&g_disks); dip != NULL;
      414 +            dip = list_next(&g_disks, dip)) {
 310  415                  /*
 311  416                   * The size is given in blocks, so multiply the number
 312  417                   * of blocks by the block size to get the total size,
 313  418                   * then convert to GiB.
 314  419                   */
 315      -                total = size * blocksize;
      420 +                total = dip->dp_size * dip->dp_blksize;
 316  421  
 317      -                if (opts->di_parseable) {
 318      -                        (void) snprintf(sizestr, sizeof (sizestr),
 319      -                            "%llu", total);
      422 +                if (g_opts.di_parseable) {
      423 +                        (void) safe_asprintf(&sizestr, "%llu", total);
 320  424                  } else {
 321  425                          total_in_GiB = (double)total /
 322  426                              1024.0 / 1024.0 / 1024.0;
 323      -                        (void) snprintf(sizestr, sizeof (sizestr),
 324      -                            "%7.2f GiB", total_in_GiB);
      427 +                        (void) safe_asprintf(&sizestr,
      428 +                            "%7.2f GiB", (total_in_GiB));
 325  429                  }
 326  430  
 327      -                if (opts->di_parseable) {
 328      -                        (void) snprintf(slotname, sizeof (slotname), "%d,%d",
 329      -                            phys.dp_chassis, phys.dp_slot);
 330      -                } else if (phys.dp_slotname != NULL) {
 331      -                        (void) snprintf(slotname, sizeof (slotname),
 332      -                            "[%d] %s", phys.dp_chassis, phys.dp_slotname);
      431 +                if (g_opts.di_parseable) {
      432 +                        (void) safe_asprintf(&slotname, "%d,%d",
      433 +                            dip->dp_chassis, dip->dp_slot);
      434 +                } else if (dip->dp_slotname != NULL) {
      435 +                        (void) safe_asprintf(&slotname, "[%d] %s",
      436 +                            dip->dp_chassis, dip->dp_slotname);
 333  437                  } else {
 334      -                        slotname[0] = '-';
 335      -                        slotname[1] = '\0';
      438 +                        slotname = safe_strdup("-");
 336  439                  }
 337  440  
 338      -                if (opts->di_condensed) {
 339      -                        (void) snprintf(statestr, sizeof (statestr), "%c%c%c%c",
 340      -                            condensed_tristate(phys.dp_faulty, 'F'),
 341      -                            condensed_tristate(phys.dp_locate, 'L'),
 342      -                            condensed_tristate(removable, 'R'),
 343      -                            condensed_tristate(ssd, 'S'));
      441 +                if (g_opts.di_condensed) {
      442 +                        (void) safe_asprintf(&statestr, "%c%c%c%c",
      443 +                            condensed_tristate(dip->dp_faulty, 'F'),
      444 +                            condensed_tristate(dip->dp_locate, 'L'),
      445 +                            condensed_tristate(dip->dp_removable, 'R'),
      446 +                            condensed_tristate(dip->dp_ssd, 'S'));
 344  447                  }
 345  448  
 346      -                if (opts->di_physical) {
 347      -                        if (opts->di_scripted) {
      449 +                if (g_opts.di_physical) {
      450 +                        if (g_opts.di_scripted) {
 348  451                                  printf("%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
 349      -                                    device, vid, pid,
 350      -                                    display_string(phys.dp_serial),
 351      -                                    display_tristate(phys.dp_faulty),
 352      -                                    display_tristate(phys.dp_locate), slotname);
      452 +                                    display_string(dip->dp_dev),
      453 +                                    display_string(dip->dp_vid),
      454 +                                    display_string(dip->dp_pid),
      455 +                                    display_string(dip->dp_serial),
      456 +                                    display_tristate(dip->dp_faulty),
      457 +                                    display_tristate(dip->dp_locate), slotname);
 353  458                          } else {
 354  459                                  printf("%-22s  %-8s %-16s "
 355  460                                      "%-20s %-3s %-3s %s\n",
 356      -                                    device, vid, pid,
 357      -                                    display_string(phys.dp_serial),
 358      -                                    display_tristate(phys.dp_faulty),
 359      -                                    display_tristate(phys.dp_locate), slotname);
      461 +                                    display_string(dip->dp_dev),
      462 +                                    display_string(dip->dp_vid),
      463 +                                    display_string(dip->dp_pid),
      464 +                                    display_string(dip->dp_serial),
      465 +                                    display_tristate(dip->dp_faulty),
      466 +                                    display_tristate(dip->dp_locate), slotname);
 360  467                          }
 361      -                } else if (opts->di_condensed) {
 362      -                        if (opts->di_scripted) {
      468 +                } else if (g_opts.di_condensed) {
      469 +                        if (g_opts.di_scripted) {
 363  470                                  printf("%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
 364      -                                    ctype, device, vid, pid,
 365      -                                    display_string(phys.dp_serial),
      471 +                                    display_string(dip->dp_ctype),
      472 +                                    display_string(dip->dp_dev),
      473 +                                    display_string(dip->dp_vid),
      474 +                                    display_string(dip->dp_pid),
      475 +                                    display_string(dip->dp_serial),
 366  476                                      sizestr, statestr, slotname);
 367  477                          } else {
 368  478                                  printf("%-7s %-22s  %-8s %-16s "
 369  479                                      "%-20s\n\t%-13s %-4s %s\n",
 370      -                                    ctype, device, vid, pid,
 371      -                                    display_string(phys.dp_serial),
      480 +                                    display_string(dip->dp_ctype),
      481 +                                    display_string(dip->dp_dev),
      482 +                                    display_string(dip->dp_vid),
      483 +                                    display_string(dip->dp_pid),
      484 +                                    display_string(dip->dp_serial),
 372  485                                      sizestr, statestr, slotname);
 373  486                          }
 374  487                  } else {
 375      -                        if (opts->di_scripted) {
      488 +                        if (g_opts.di_scripted) {
 376  489                                  printf("%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
 377      -                                    ctype, device, vid, pid, sizestr,
 378      -                                    display_tristate(removable),
 379      -                                    display_tristate(ssd));
      490 +                                    display_string(dip->dp_ctype),
      491 +                                    display_string(dip->dp_dev),
      492 +                                    display_string(dip->dp_vid),
      493 +                                    display_string(dip->dp_pid), sizestr,
      494 +                                    display_tristate(dip->dp_removable),
      495 +                                    display_tristate(dip->dp_ssd));
 380  496                          } else {
 381  497                                  printf("%-7s %-22s  %-8s %-16s "
 382      -                                    "%-13s %-3s %-3s\n", ctype, device,
 383      -                                    vid, pid, sizestr,
 384      -                                    display_tristate(removable),
 385      -                                    display_tristate(ssd));
      498 +                                    "%-13s %-3s %-3s\n",
      499 +                                    display_string(dip->dp_ctype),
      500 +                                    display_string(dip->dp_dev),
      501 +                                    display_string(dip->dp_vid),
      502 +                                    display_string(dip->dp_pid), sizestr,
      503 +                                    display_tristate(dip->dp_removable),
      504 +                                    display_tristate(dip->dp_ssd));
 386  505                          }
 387  506                  }
 388      -
 389      -                free(ctype);
 390      -                nvlist_free(cattrs);
 391      -                nvlist_free(dattrs);
 392      -                dm_free_descriptors(controller);
 393      -                dm_free_descriptors(disk);
      507 +        free(sizestr); free(slotname); free(statestr);
      508 +        sizestr = slotname = statestr = NULL;
 394  509          }
      510 +}
 395  511  
 396      -        dm_free_descriptors(media);
 397      -        topo_snap_release(hp);
 398      -        topo_close(hp);
      512 +static void
      513 +cleanup()
      514 +{
      515 +        di_phys_t *dip;
      516 +        while ((dip = list_head(&g_disks)) != NULL) {
      517 +                list_remove(&g_disks, dip);
      518 +                free(dip->dp_vid);
      519 +                free(dip->dp_pid);
      520 +                free(dip->dp_dev);
      521 +                free(dip->dp_ctype);
      522 +                free(dip->dp_serial);
      523 +                free(dip->dp_slotname);
      524 +                free(dip);
      525 +        }
      526 +        list_destroy(&g_disks);
 399  527  }
 400  528  
 401  529  int
 402  530  main(int argc, char *argv[])
 403  531  {
 404  532          char c;
 405  533  
 406      -        di_opts_t opts = {
 407      -                .di_condensed = B_FALSE,
 408      -                .di_scripted = B_FALSE,
 409      -                .di_physical = B_FALSE,
 410      -                .di_parseable = B_FALSE
 411      -        };
 412      -
 413      -        while ((c = getopt(argc, argv, ":cHPp")) != EOF) {
      534 +        while ((c = getopt(argc, argv, ":acHPp")) != EOF) {
 414  535                  switch (c) {
      536 +                case 'a':
      537 +                        g_opts.di_allslots = B_TRUE;
      538 +                        break;
 415  539                  case 'c':
 416      -                        if (opts.di_physical) {
 417      -                                usage(argv[0]);
 418      -                                fatal(1, "-c and -P are mutually exclusive\n");
 419      -                        }
 420      -                        opts.di_condensed = B_TRUE;
      540 +                        g_opts.di_condensed = B_TRUE;
 421  541                          break;
 422  542                  case 'H':
 423      -                        opts.di_scripted = B_TRUE;
      543 +                        g_opts.di_scripted = B_TRUE;
 424  544                          break;
 425  545                  case 'P':
 426      -                        if (opts.di_condensed) {
 427      -                                usage(argv[0]);
 428      -                                fatal(1, "-c and -P are mutually exclusive\n");
 429      -                        }
 430      -                        opts.di_physical = B_TRUE;
      546 +                        g_opts.di_physical = B_TRUE;
 431  547                          break;
 432  548                  case 'p':
 433      -                        opts.di_parseable = B_TRUE;
      549 +                        g_opts.di_parseable = B_TRUE;
 434  550                          break;
 435  551                  case '?':
 436  552                          usage(argv[0]);
 437  553                          fatal(1, "unknown option -%c\n", optopt);
 438  554                  default:
 439  555                          fatal(-1, "unexpected error on option -%c\n", optopt);
 440  556                  }
 441  557          }
 442  558  
 443      -        if (!opts.di_scripted) {
 444      -                if (opts.di_physical) {
      559 +        if (g_opts.di_condensed && g_opts.di_physical) {
      560 +                usage(argv[0]);
      561 +                fatal(1, "-c and -P are mutually exclusive\n");
      562 +        }
      563 +
      564 +        if (!g_opts.di_scripted) {
      565 +                if (g_opts.di_physical) {
 445  566                          printf("DISK                    VID      PID"
 446  567                              "              SERIAL               FLT LOC"
 447  568                              " LOCATION\n");
 448      -                } else if (opts.di_condensed) {
      569 +                } else if (g_opts.di_condensed) {
 449  570                          printf("TYPE    DISK                    VID      PID"
 450  571                              "              SERIAL\n");
 451  572                          printf("\tSIZE          FLRS LOCATION\n");
 452  573                  } else {
 453  574                          printf("TYPE    DISK                    VID      PID"
 454  575                              "              SIZE          RMV SSD\n");
 455  576                  }
 456  577          }
 457  578  
 458      -        enumerate_disks(&opts);
      579 +        enumerate_disks();
      580 +        show_disks();
      581 +        cleanup();
 459  582  
 460  583          return (0);
 461  584  }
    
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX