13 * Copyright (c) 2013 Joyent Inc., All rights reserved.
14 */
15
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <fcntl.h>
19 #include <errno.h>
20 #include <string.h>
21 #include <stdio.h>
22 #include <unistd.h>
23 #include <limits.h>
24 #include <assert.h>
25 #include <ctype.h>
26 #include <stdarg.h>
27 #include <strings.h>
28
29 #include <libdiskmgt.h>
30 #include <sys/nvpair.h>
31 #include <sys/param.h>
32 #include <sys/ccompile.h>
33
34 #include <fm/libtopo.h>
35 #include <fm/topo_hc.h>
36 #include <fm/topo_list.h>
37 #include <sys/fm/protocol.h>
38 #include <modules/common/disk/disk.h>
39
40 typedef struct di_opts {
41 boolean_t di_scripted;
42 boolean_t di_parseable;
43 boolean_t di_physical;
44 boolean_t di_condensed;
45 } di_opts_t;
46
47 typedef struct di_phys {
48 const char *dp_dev;
49 const char *dp_serial;
50 const char *dp_slotname;
51 int dp_chassis;
52 int dp_slot;
53 int dp_faulty;
54 int dp_locate;
55 } di_phys_t;
56
57 static void __NORETURN
58 fatal(int rv, const char *fmt, ...)
59 {
60 va_list ap;
61
62 va_start(ap, fmt);
63 (void) vfprintf(stderr, fmt, ap);
64 va_end(ap);
65
66 exit(rv);
67 }
68
69 static void
70 usage(const char *execname)
71 {
72 (void) fprintf(stderr, "Usage: %s [-Hp] [{-c|-P}]\n", execname);
73 }
74
75 static void
76 nvlist_query_string(nvlist_t *nvl, const char *label, char **val)
77 {
78 if (nvlist_lookup_string(nvl, label, val) != 0)
79 *val = "-";
80 }
81
82 static const char *
83 display_string(const char *label)
84 {
85 return ((label) ? label : "-");
86 }
87
88 static const char *
89 display_tristate(int val)
90 {
91 if (val == 0)
92 return ("no");
93 if (val == 1)
94 return ("yes");
95
96 return ("-");
97 }
98
99 static char
100 condensed_tristate(int val, char c)
101 {
102 if (val == 0)
103 return ('-');
104 if (val == 1)
105 return (c);
106
107 return ('?');
108 }
109 static int
110 disk_walker(topo_hdl_t *hp, tnode_t *np, void *arg)
111 {
112 di_phys_t *pp = arg;
113 tnode_t *pnp;
114 tnode_t *ppnp;
115 topo_faclist_t fl;
116 topo_faclist_t *lp;
117 int err;
118 topo_led_state_t mode;
119 topo_led_type_t type;
120 char *name, *slotname, *serial;
121
122 if (strcmp(topo_node_name(np), DISK) != 0)
123 return (TOPO_WALK_NEXT);
124
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 }
129
130 if (strcmp(name, pp->dp_dev) != 0)
131 return (TOPO_WALK_NEXT);
132
133 if (topo_prop_get_string(np, TOPO_PGROUP_STORAGE,
134 TOPO_STORAGE_SERIAL_NUM, &serial, &err) == 0) {
135 pp->dp_serial = serial;
136 }
137
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;
146
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;
153
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;
160
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 }
173
174 if (topo_prop_get_string(pnp, TOPO_PGROUP_PROTOCOL,
175 TOPO_PROP_LABEL, &slotname, &err) == 0) {
176 pp->dp_slotname = slotname;
177 }
178
179 pp->dp_slot = topo_node_instance(pnp);
180 }
181
182 pp->dp_chassis = topo_node_instance(ppnp);
183
184 return (TOPO_WALK_TERMINATE);
185 }
186
187 static void
188 populate_physical(topo_hdl_t *hp, di_phys_t *pp)
189 {
190 int err;
191 topo_walk_t *wp;
192
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) {
199 fatal(-1, "unable to initialise topo walker: %s",
200 topo_strerror(err));
201 }
202
203 while ((err = topo_walk_step(wp, TOPO_WALK_CHILD)) == TOPO_WALK_NEXT)
204 ;
205
206 if (err == TOPO_WALK_ERR)
207 fatal(-1, "topo walk failed");
208
209 topo_walk_fini(wp);
210 }
211
212 static void
213 enumerate_disks(di_opts_t *opts)
214 {
215 topo_hdl_t *hp;
216 dm_descriptor_t *media;
217 int err, i;
218 int filter[] = { DM_DT_FIXED, -1 };
219 dm_descriptor_t *disk, *controller;
220 nvlist_t *mattrs, *dattrs, *cattrs = NULL;
221
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;
234 size_t len;
235
236 err = 0;
237 if ((media = dm_get_descriptors(DM_MEDIA, filter, &err)) == NULL) {
238 fatal(-1, "failed to obtain media descriptors: %s\n",
239 strerror(err));
240 }
241
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 for (i = 0; media != NULL && media[i] != NULL; i++) {
257 if ((disk = dm_get_associated_descriptors(media[i],
258 DM_DRIVE, &err)) == NULL) {
259 continue;
260 }
261
262 mattrs = dm_get_attributes(media[i], &err);
263 err = nvlist_lookup_uint64(mattrs, DM_SIZE, &size);
264 assert(err == 0);
265 err = nvlist_lookup_uint32(mattrs, DM_BLOCKSIZE, &blocksize);
266 assert(err == 0);
267 nvlist_free(mattrs);
268
269 dattrs = dm_get_attributes(disk[0], &err);
270
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);
274
275 removable = B_FALSE;
276 if (nvlist_lookup_boolean(dattrs, DM_REMOVABLE) == 0)
277 removable = B_TRUE;
278
279 ssd = B_FALSE;
280 if (nvlist_lookup_boolean(dattrs, DM_SOLIDSTATE) == 0)
281 ssd = B_TRUE;
282
283 if ((controller = dm_get_associated_descriptors(disk[0],
284 DM_CONTROLLER, &err)) != NULL) {
285 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++)
289 *c = toupper(*c);
290 }
291
292 /*
293 * Parse full device path to only show the device name,
294 * i.e. c0t1d0. Many paths will reference a particular
295 * slice (c0t1d0s0), so remove the slice if present.
296 */
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';
305
306 bzero(&phys, sizeof (phys));
307 phys.dp_dev = device;
308 populate_physical(hp, &phys);
309
310 /*
311 * The size is given in blocks, so multiply the number
312 * of blocks by the block size to get the total size,
313 * then convert to GiB.
314 */
315 total = size * blocksize;
316
317 if (opts->di_parseable) {
318 (void) snprintf(sizestr, sizeof (sizestr),
319 "%llu", total);
320 } else {
321 total_in_GiB = (double)total /
322 1024.0 / 1024.0 / 1024.0;
323 (void) snprintf(sizestr, sizeof (sizestr),
324 "%7.2f GiB", total_in_GiB);
325 }
326
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);
333 } else {
334 slotname[0] = '-';
335 slotname[1] = '\0';
336 }
337
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'));
344 }
345
346 if (opts->di_physical) {
347 if (opts->di_scripted) {
348 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);
353 } else {
354 printf("%-22s %-8s %-16s "
355 "%-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);
360 }
361 } else if (opts->di_condensed) {
362 if (opts->di_scripted) {
363 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),
366 sizestr, statestr, slotname);
367 } else {
368 printf("%-7s %-22s %-8s %-16s "
369 "%-20s\n\t%-13s %-4s %s\n",
370 ctype, device, vid, pid,
371 display_string(phys.dp_serial),
372 sizestr, statestr, slotname);
373 }
374 } else {
375 if (opts->di_scripted) {
376 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));
380 } else {
381 printf("%-7s %-22s %-8s %-16s "
382 "%-13s %-3s %-3s\n", ctype, device,
383 vid, pid, sizestr,
384 display_tristate(removable),
385 display_tristate(ssd));
386 }
387 }
388
389 free(ctype);
390 nvlist_free(cattrs);
391 nvlist_free(dattrs);
392 dm_free_descriptors(controller);
393 dm_free_descriptors(disk);
394 }
395
396 dm_free_descriptors(media);
397 topo_snap_release(hp);
398 topo_close(hp);
399 }
400
401 int
402 main(int argc, char *argv[])
403 {
404 char c;
405
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) {
414 switch (c) {
415 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;
421 break;
422 case 'H':
423 opts.di_scripted = B_TRUE;
424 break;
425 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;
431 break;
432 case 'p':
433 opts.di_parseable = B_TRUE;
434 break;
435 case '?':
436 usage(argv[0]);
437 fatal(1, "unknown option -%c\n", optopt);
438 default:
439 fatal(-1, "unexpected error on option -%c\n", optopt);
440 }
441 }
442
443 if (!opts.di_scripted) {
444 if (opts.di_physical) {
445 printf("DISK VID PID"
446 " SERIAL FLT LOC"
447 " LOCATION\n");
448 } else if (opts.di_condensed) {
449 printf("TYPE DISK VID PID"
450 " SERIAL\n");
451 printf("\tSIZE FLRS LOCATION\n");
452 } else {
453 printf("TYPE DISK VID PID"
454 " SIZE RMV SSD\n");
455 }
456 }
457
458 enumerate_disks(&opts);
459
460 return (0);
461 }
|
13 * Copyright (c) 2013 Joyent Inc., All rights reserved.
14 */
15
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <fcntl.h>
19 #include <errno.h>
20 #include <string.h>
21 #include <stdio.h>
22 #include <unistd.h>
23 #include <limits.h>
24 #include <assert.h>
25 #include <ctype.h>
26 #include <stdarg.h>
27 #include <strings.h>
28
29 #include <libdiskmgt.h>
30 #include <sys/nvpair.h>
31 #include <sys/param.h>
32 #include <sys/ccompile.h>
33 #include <sys/list.h>
34
35 #include <fm/libtopo.h>
36 #include <fm/topo_hc.h>
37 #include <fm/topo_list.h>
38 #include <sys/fm/protocol.h>
39 #include <modules/common/disk/disk.h>
40
41 typedef struct di_opts {
42 boolean_t di_allslots;
43 boolean_t di_scripted;
44 boolean_t di_parseable;
45 boolean_t di_physical;
46 boolean_t di_condensed;
47 } di_opts_t;
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
52 typedef struct di_phys {
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;
63 int dp_chassis;
64 int dp_slot;
65 int dp_faulty;
66 int dp_locate;
67 list_node_t dp_next;
68 } di_phys_t;
69
70 static void __NORETURN
71 fatal(int rv, const char *fmt, ...)
72 {
73 va_list ap;
74
75 va_start(ap, fmt);
76 (void) vfprintf(stderr, fmt, ap);
77 va_end(ap);
78
79 exit(rv);
80 }
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
115 static void
116 usage(const char *execname)
117 {
118 (void) fprintf(stderr, "Usage: %s [-aHp] [{-c|-P}]\n", execname);
119 }
120
121 static void
122 nvlist_query_string(nvlist_t *nvl, const char *label, char **val)
123 {
124 if (nvlist_lookup_string(nvl, label, val) != 0)
125 *val = "-";
126 }
127
128 static const char *
129 display_string(const char *label)
130 {
131 return ((label) ? label : "-");
132 }
133
134 static const char *
135 display_tristate(int val)
136 {
137 if (val == 0)
138 return ("no");
139 if (val == 1)
140 return ("yes");
141
142 return ("-");
143 }
144
145 static char
146 condensed_tristate(int val, char c)
147 {
148 if (val == 0)
149 return ('-');
150 if (val == 1)
151 return (c);
152
153 return ('?');
154 }
155
156 static void
157 set_disk_bay_info(topo_hdl_t *hp, tnode_t *np, di_phys_t *dip)
158 {
159 topo_faclist_t fl;
160 topo_faclist_t *lp;
161 topo_led_state_t mode;
162 topo_led_type_t type;
163 int err;
164
165 if (strcmp(topo_node_name(np), BAY) != 0)
166 return;
167
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;
173
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;
180
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 }
199 }
200
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 }
205
206 dip->dp_slot = topo_node_instance(np);
207 dip->dp_chassis = topo_node_instance(topo_node_parent(np));
208 }
209
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;
215
216 if (strcmp(topo_node_name(np), BAY) != 0)
217 return (TOPO_WALK_NEXT);
218
219 slot = topo_node_instance(np);
220 chassis = topo_node_instance(topo_node_parent(np));
221
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);
226 }
227
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 }
233
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);
261 }
262
263 static void
264 walk_topo_snapshot(topo_hdl_t *hp, topo_walk_cb_t cb)
265 {
266 int err = 0;
267 topo_walk_t *wp;
268
269 if ((wp = topo_walk_init(hp, FM_FMRI_SCHEME_HC, cb, NULL,
270 &err)) == NULL) {
271 fatal(-1, "unable to initialise topo walker: %s",
272 topo_strerror(err));
273 }
274
275 while ((err = topo_walk_step(wp, TOPO_WALK_CHILD)) == TOPO_WALK_NEXT)
276 ;
277
278 if (err == TOPO_WALK_ERR)
279 fatal(-1, "topo walk failed");
280 topo_walk_fini(wp);
281 }
282
283 static void
284 enumerate_disks()
285 {
286 topo_hdl_t *hp;
287 dm_descriptor_t *media;
288 int filter[] = { DM_DT_FIXED, -1 };
289 dm_descriptor_t *disk, *controller;
290 nvlist_t *mattrs, *dattrs, *cattrs;
291
292 char *s, *c;
293 di_phys_t *dip;
294 size_t len;
295 int err, i;
296
297 list_create(&g_disks, sizeof (di_phys_t), offsetof(di_phys_t, dp_next));
298
299 err = 0;
300 if ((media = dm_get_descriptors(DM_MEDIA, filter, &err)) == NULL) {
301 fatal(-1, "failed to obtain media descriptors: %s\n",
302 strerror(err));
303 }
304
305 for (i = 0; media != NULL && media[i] != NULL; i++) {
306 if ((disk = dm_get_associated_descriptors(media[i],
307 DM_DRIVE, &err)) == NULL) {
308 continue;
309 }
310
311 dip = safe_zmalloc(sizeof (di_phys_t));
312
313 mattrs = dm_get_attributes(media[i], &err);
314 err = nvlist_lookup_uint64(mattrs, DM_SIZE, &dip->dp_size);
315 assert(err == 0);
316 err = nvlist_lookup_uint32(mattrs, DM_BLOCKSIZE,
317 &dip->dp_blksize);
318 assert(err == 0);
319 nvlist_free(mattrs);
320
321 dattrs = dm_get_attributes(disk[0], &err);
322
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);
326
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;
332 if (nvlist_lookup_boolean(dattrs, DM_REMOVABLE) == 0)
333 dip->dp_removable = B_TRUE;
334
335 dip->dp_ssd = B_FALSE;
336 if (nvlist_lookup_boolean(dattrs, DM_SOLIDSTATE) == 0)
337 dip->dp_ssd = B_TRUE;
338
339 nvlist_free(dattrs);
340
341 if ((controller = dm_get_associated_descriptors(disk[0],
342 DM_CONTROLLER, &err)) != NULL) {
343 cattrs = dm_get_attributes(controller[0], &err);
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++)
347 *c = toupper(*c);
348 nvlist_free(cattrs);
349 }
350
351 dm_free_descriptors(controller);
352 dm_free_descriptors(disk);
353
354 /*
355 * Parse full device path to only show the device name,
356 * i.e. c0t1d0. Many paths will reference a particular
357 * slice (c0t1d0s0), so remove the slice if present.
358 */
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';
369
370 dip->dp_faulty = dip->dp_locate = -1;
371 dip->dp_chassis = dip->dp_slot = -1;
372 list_insert_tail(&g_disks, dip);
373 }
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)) {
415 /*
416 * The size is given in blocks, so multiply the number
417 * of blocks by the block size to get the total size,
418 * then convert to GiB.
419 */
420 total = dip->dp_size * dip->dp_blksize;
421
422 if (g_opts.di_parseable) {
423 (void) safe_asprintf(&sizestr, "%llu", total);
424 } else {
425 total_in_GiB = (double)total /
426 1024.0 / 1024.0 / 1024.0;
427 (void) safe_asprintf(&sizestr,
428 "%7.2f GiB", (total_in_GiB));
429 }
430
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);
437 } else {
438 slotname = safe_strdup("-");
439 }
440
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'));
447 }
448
449 if (g_opts.di_physical) {
450 if (g_opts.di_scripted) {
451 printf("%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
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);
458 } else {
459 printf("%-22s %-8s %-16s "
460 "%-20s %-3s %-3s %s\n",
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);
467 }
468 } else if (g_opts.di_condensed) {
469 if (g_opts.di_scripted) {
470 printf("%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
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),
476 sizestr, statestr, slotname);
477 } else {
478 printf("%-7s %-22s %-8s %-16s "
479 "%-20s\n\t%-13s %-4s %s\n",
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),
485 sizestr, statestr, slotname);
486 }
487 } else {
488 if (g_opts.di_scripted) {
489 printf("%s\t%s\t%s\t%s\t%s\t%s\t%s\n",
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));
496 } else {
497 printf("%-7s %-22s %-8s %-16s "
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));
505 }
506 }
507 free(sizestr); free(slotname); free(statestr);
508 sizestr = slotname = statestr = NULL;
509 }
510 }
511
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);
527 }
528
529 int
530 main(int argc, char *argv[])
531 {
532 char c;
533
534 while ((c = getopt(argc, argv, ":acHPp")) != EOF) {
535 switch (c) {
536 case 'a':
537 g_opts.di_allslots = B_TRUE;
538 break;
539 case 'c':
540 g_opts.di_condensed = B_TRUE;
541 break;
542 case 'H':
543 g_opts.di_scripted = B_TRUE;
544 break;
545 case 'P':
546 g_opts.di_physical = B_TRUE;
547 break;
548 case 'p':
549 g_opts.di_parseable = B_TRUE;
550 break;
551 case '?':
552 usage(argv[0]);
553 fatal(1, "unknown option -%c\n", optopt);
554 default:
555 fatal(-1, "unexpected error on option -%c\n", optopt);
556 }
557 }
558
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) {
566 printf("DISK VID PID"
567 " SERIAL FLT LOC"
568 " LOCATION\n");
569 } else if (g_opts.di_condensed) {
570 printf("TYPE DISK VID PID"
571 " SERIAL\n");
572 printf("\tSIZE FLRS LOCATION\n");
573 } else {
574 printf("TYPE DISK VID PID"
575 " SIZE RMV SSD\n");
576 }
577 }
578
579 enumerate_disks();
580 show_disks();
581 cleanup();
582
583 return (0);
584 }
|