Print this page
2976 remove useless offsetof() macros
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/fm/fmadm/common/faulty.c
+++ new/usr/src/cmd/fm/fmadm/common/faulty.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
23 23 */
24 24
25 25 #include <sys/types.h>
26 26 #include <fmadm.h>
27 27 #include <errno.h>
28 28 #include <limits.h>
29 29 #include <strings.h>
30 30 #include <stdio.h>
31 31 #include <unistd.h>
32 32 #include <sys/wait.h>
33 33 #include <sys/stat.h>
34 34 #include <fcntl.h>
35 35 #include <fm/fmd_log.h>
36 36 #include <sys/fm/protocol.h>
37 37 #include <fm/libtopo.h>
↓ open down ↓ |
37 lines elided |
↑ open up ↑ |
38 38 #include <fm/fmd_adm.h>
39 39 #include <fm/fmd_msg.h>
40 40 #include <dlfcn.h>
41 41 #include <sys/systeminfo.h>
42 42 #include <sys/utsname.h>
43 43 #include <libintl.h>
44 44 #include <locale.h>
45 45 #include <sys/smbios.h>
46 46 #include <libdevinfo.h>
47 47 #include <stdlib.h>
48 -
49 -#define offsetof(s, m) ((size_t)(&(((s*)0)->m)))
48 +#include <stddef.h>
50 49
51 50 /*
52 51 * Fault records are added to catalog by calling add_fault_record_to_catalog()
53 52 * records are stored in order of importance to the system.
54 53 * If -g flag is set or not_suppressed is not set and the class fru, fault,
55 54 * type are the same then details are merged into an existing record, with uuid
56 55 * records are stored in time order.
57 56 * For each record information is extracted from nvlist and merged into linked
58 57 * list each is checked for identical records for which percentage certainty are
59 58 * added together.
60 59 * print_catalog() is called to print out catalog and release external resources
61 60 *
62 61 * /---------------\
63 62 * status_rec_list -> | | -|
64 63 * \---------------/
65 64 * \/
66 65 * /---------------\ /-------\ /-------\
67 66 * status_fru_list | status_record | -> | uurec | -> | uurec | -|
68 67 * \/ | | |- | | <- | |
69 68 * /-------------\ | | \-------/ \-------/
70 69 * | | -> | | \/ \/
71 70 * \-------------/ | | /-------\ /-------\
72 71 * \/ | | -> | asru | -> | asru |
73 72 * --- | | | | <- | |
74 73 * | | \-------/ \-------/
75 74 * status_asru_list | class |
76 75 * \/ | resource | /-------\ /-------\
77 76 * /-------------\ | fru | -> | list | -> | list |
78 77 * | | -> | serial | | | <- | |
79 78 * \-------------/ | | \-------/ \-------/
80 79 * \/ \---------------/
81 80 * --- \/ /\
82 81 * /---------------\
83 82 * | status_record |
84 83 * \---------------/
85 84 *
86 85 * Fmadm faulty takes a number of options which affect the format of the
87 86 * output displayed. By default, the display reports the FRU and ASRU along
88 87 * with other information on per-case basis as in the example below.
89 88 *
90 89 * --------------- ------------------------------------ -------------- -------
91 90 * TIME EVENT-ID MSG-ID SEVERITY
92 91 * --------------- ------------------------------------ -------------- -------
93 92 * Sep 21 10:01:36 d482f935-5c8f-e9ab-9f25-d0aaafec1e6c AMD-8000-2F Major
94 93 *
95 94 * Fault class : fault.memory.dimm_sb
96 95 * Affects : mem:///motherboard=0/chip=0/memory-controller=0/dimm=0/rank=0
97 96 * faulted but still in service
98 97 * FRU : "CPU 0 DIMM 0" (hc://.../memory-controller=0/dimm=0)
99 98 * faulty
100 99 *
101 100 * Description : The number of errors associated with this memory module has
102 101 * exceeded acceptable levels. Refer to
103 102 * http://illumos.org/msg/AMD-8000-2F for more information.
104 103 *
105 104 * Response : Pages of memory associated with this memory module are being
106 105 * removed from service as errors are reported.
107 106 *
108 107 * Impact : Total system memory capacity will be reduced as pages are
109 108 * retired.
110 109 *
111 110 * Action : Schedule a repair procedure to replace the affected memory
112 111 * module. Use fmdump -v -u <EVENT_ID> to identify the module.
113 112 *
114 113 * The -v flag is similar, but adds some additonal information such as the
115 114 * resource. The -s flag is also similar but just gives the top line summary.
116 115 * All these options (ie without the -f or -r flags) use the print_catalog()
117 116 * function to do the display.
118 117 *
119 118 * The -f flag changes the output so that it appears sorted on a per-fru basis.
120 119 * The output is somewhat cut down compared to the default output. If -f is
121 120 * used, then print_fru() is used to print the output.
122 121 *
123 122 * -----------------------------------------------------------------------------
124 123 * "SLOT 2" (hc://.../hostbridge=3/pciexrc=3/pciexbus=4/pciexdev=0) faulty
125 124 * 5ca4aeb3-36...f6be-c2e8166dc484 2 suspects in this FRU total certainty 100%
126 125 *
127 126 * Description : A problem was detected for a PCI device.
128 127 * Refer to http://illumos.org/msg/PCI-8000-7J
129 128 * for more information.
130 129 *
131 130 * Response : One or more device instances may be disabled
132 131 *
133 132 * Impact : Possible loss of services provided by the device instances
134 133 * associated with this fault
135 134 *
136 135 * Action : Schedule a repair procedure to replace the affected device.
137 136 * Use fmdump -v -u <EVENT_ID> to identify the device or contact
138 137 * Sun for support.
139 138 *
140 139 * The -r flag changes the output so that it appears sorted on a per-asru basis.
141 140 * The output is very much cut down compared to the default output, just giving
142 141 * the asru fmri and state. Here print_asru() is used to print the output.
143 142 *
144 143 * mem:///motherboard=0/chip=0/memory-controller=0/dimm=0/rank=0 degraded
145 144 *
146 145 * For all fmadm faulty options, the sequence of events is
147 146 *
148 147 * 1) Walk through all the cases in the system using fmd_adm_case_iter() and
149 148 * for each case call dfault_rec(). This will call add_fault_record_to_catalog()
150 149 * This will extract the data from the nvlist and call catalog_new_record() to
151 150 * save the data away in various linked lists in the catalogue.
152 151 *
153 152 * 2) Once this is done, the data can be supplemented by using
154 153 * fmd_adm_rsrc_iter(). However this is now only necessary for the -i option.
155 154 *
156 155 * 3) Finally print_catalog(), print_fru() or print_asru() are called as
157 156 * appropriate to display the information from the catalogue sorted in the
158 157 * requested way.
159 158 *
160 159 */
161 160
162 161 typedef struct name_list {
163 162 struct name_list *next;
164 163 struct name_list *prev;
165 164 char *name;
166 165 uint8_t pct;
167 166 uint8_t max_pct;
168 167 ushort_t count;
169 168 int status;
170 169 char *label;
171 170 } name_list_t;
172 171
173 172 typedef struct ari_list {
174 173 char *ari_uuid;
175 174 struct ari_list *next;
176 175 } ari_list_t;
177 176
178 177 typedef struct uurec {
179 178 struct uurec *next;
180 179 struct uurec *prev;
181 180 char *uuid;
182 181 ari_list_t *ari_uuid_list;
183 182 name_list_t *asru;
184 183 uint64_t sec;
185 184 nvlist_t *event;
186 185 } uurec_t;
187 186
188 187 typedef struct uurec_select {
189 188 struct uurec_select *next;
190 189 char *uuid;
191 190 } uurec_select_t;
192 191
193 192 typedef struct host_id {
194 193 char *chassis;
195 194 char *server;
196 195 char *platform;
197 196 char *domain;
198 197 char *product_sn;
199 198 } hostid_t;
200 199
201 200 typedef struct host_id_list {
202 201 hostid_t hostid;
203 202 struct host_id_list *next;
204 203 } host_id_list_t;
205 204
206 205 typedef struct status_record {
207 206 hostid_t *host;
208 207 int nrecs;
209 208 uurec_t *uurec;
210 209 char *severity; /* in C locale */
211 210 char *msgid;
212 211 name_list_t *class;
213 212 name_list_t *resource;
214 213 name_list_t *asru;
215 214 name_list_t *fru;
216 215 name_list_t *serial;
217 216 uint8_t not_suppressed;
218 217 uint8_t injected;
219 218 } status_record_t;
220 219
221 220 typedef struct sr_list {
222 221 struct sr_list *next;
223 222 struct sr_list *prev;
224 223 struct status_record *status_record;
225 224 } sr_list_t;
226 225
227 226 typedef struct resource_list {
228 227 struct resource_list *next;
229 228 struct resource_list *prev;
230 229 sr_list_t *status_rec_list;
231 230 char *resource;
232 231 uint8_t not_suppressed;
233 232 uint8_t injected;
234 233 uint8_t max_pct;
235 234 } resource_list_t;
236 235
237 236 sr_list_t *status_rec_list;
238 237 resource_list_t *status_fru_list;
239 238 resource_list_t *status_asru_list;
240 239
241 240 static int max_display;
242 241 static int max_fault = 0;
243 242 static topo_hdl_t *topo_handle;
244 243 static host_id_list_t *host_list;
245 244 static int n_server;
246 245 static int opt_g;
247 246 static fmd_msg_hdl_t *fmadm_msghdl = NULL; /* handle for libfmd_msg calls */
248 247
249 248 static char *
250 249 format_date(char *buf, size_t len, uint64_t sec)
251 250 {
252 251 if (sec > LONG_MAX) {
253 252 (void) fprintf(stderr,
254 253 "record time is too large for 32-bit utility\n");
255 254 (void) snprintf(buf, len, "0x%llx", sec);
256 255 } else {
257 256 time_t tod = (time_t)sec;
258 257 time_t now = time(NULL);
259 258 if (tod > now+60 ||
260 259 tod < now - 6L*30L*24L*60L*60L) { /* 6 months ago */
261 260 (void) strftime(buf, len, "%b %d %Y ",
262 261 localtime(&tod));
263 262 } else {
264 263 (void) strftime(buf, len, "%b %d %T", localtime(&tod));
265 264 }
266 265 }
267 266
268 267 return (buf);
269 268 }
270 269
271 270 static hostid_t *
272 271 find_hostid_in_list(char *platform, char *chassis, char *server, char *domain,
273 272 char *product_sn)
274 273 {
275 274 hostid_t *rt = NULL;
276 275 host_id_list_t *hostp;
277 276
278 277 if (platform == NULL)
279 278 platform = "-";
280 279 if (server == NULL)
281 280 server = "-";
282 281 hostp = host_list;
283 282 while (hostp) {
284 283 if (hostp->hostid.platform &&
285 284 strcmp(hostp->hostid.platform, platform) == 0 &&
286 285 hostp->hostid.server &&
287 286 strcmp(hostp->hostid.server, server) == 0 &&
288 287 (chassis == NULL || hostp->hostid.chassis == NULL ||
289 288 strcmp(chassis, hostp->hostid.chassis) == 0) &&
290 289 (product_sn == NULL || hostp->hostid.product_sn == NULL ||
291 290 strcmp(product_sn, hostp->hostid.product_sn) == 0) &&
292 291 (domain == NULL || hostp->hostid.domain == NULL ||
293 292 strcmp(domain, hostp->hostid.domain) == 0)) {
294 293 rt = &hostp->hostid;
295 294 break;
296 295 }
297 296 hostp = hostp->next;
298 297 }
299 298 if (rt == NULL) {
300 299 hostp = malloc(sizeof (host_id_list_t));
301 300 hostp->hostid.platform = strdup(platform);
302 301 hostp->hostid.product_sn =
303 302 product_sn ? strdup(product_sn) : NULL;
304 303 hostp->hostid.server = strdup(server);
305 304 hostp->hostid.chassis = chassis ? strdup(chassis) : NULL;
306 305 hostp->hostid.domain = domain ? strdup(domain) : NULL;
307 306 hostp->next = host_list;
308 307 host_list = hostp;
309 308 rt = &hostp->hostid;
310 309 n_server++;
311 310 }
312 311 return (rt);
313 312 }
314 313
315 314 static hostid_t *
316 315 find_hostid(nvlist_t *nvl)
317 316 {
318 317 char *platform = NULL, *chassis = NULL, *server = NULL, *domain = NULL;
319 318 char *product_sn = NULL;
320 319 nvlist_t *auth, *fmri;
321 320 hostid_t *rt = NULL;
322 321
323 322 if (nvlist_lookup_nvlist(nvl, FM_SUSPECT_DE, &fmri) == 0 &&
324 323 nvlist_lookup_nvlist(fmri, FM_FMRI_AUTHORITY, &auth) == 0) {
325 324 (void) nvlist_lookup_string(auth, FM_FMRI_AUTH_PRODUCT,
326 325 &platform);
327 326 (void) nvlist_lookup_string(auth, FM_FMRI_AUTH_PRODUCT_SN,
328 327 &product_sn);
329 328 (void) nvlist_lookup_string(auth, FM_FMRI_AUTH_SERVER, &server);
330 329 (void) nvlist_lookup_string(auth, FM_FMRI_AUTH_CHASSIS,
331 330 &chassis);
332 331 (void) nvlist_lookup_string(auth, FM_FMRI_AUTH_DOMAIN, &domain);
333 332 rt = find_hostid_in_list(platform, chassis, server,
334 333 domain, product_sn);
335 334 }
336 335 return (rt);
337 336 }
338 337
339 338 static char *
340 339 get_nvl2str_topo(nvlist_t *nvl)
341 340 {
342 341 char *name = NULL;
343 342 char *tname;
344 343 int err;
345 344 char *scheme = NULL;
346 345 char *mod_name = NULL;
347 346 char buf[128];
348 347
349 348 if (topo_handle == NULL)
350 349 topo_handle = topo_open(TOPO_VERSION, 0, &err);
351 350 if (topo_fmri_nvl2str(topo_handle, nvl, &tname, &err) == 0) {
352 351 name = strdup(tname);
353 352 topo_hdl_strfree(topo_handle, tname);
354 353 } else {
355 354 (void) nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &scheme);
356 355 (void) nvlist_lookup_string(nvl, FM_FMRI_MOD_NAME, &mod_name);
357 356 if (scheme && strcmp(scheme, FM_FMRI_SCHEME_FMD) == 0 &&
358 357 mod_name) {
359 358 (void) snprintf(buf, sizeof (buf), "%s:///module/%s",
360 359 scheme, mod_name);
361 360 name = strdup(buf);
362 361 }
363 362 }
364 363 return (name);
365 364 }
366 365
367 366 static int
368 367 set_priority(char *s)
369 368 {
370 369 int rt = 0;
371 370
372 371 if (s) {
373 372 if (strcmp(s, "Minor") == 0)
374 373 rt = 1;
375 374 else if (strcmp(s, "Major") == 0)
376 375 rt = 10;
377 376 else if (strcmp(s, "Critical") == 0)
378 377 rt = 100;
379 378 }
380 379 return (rt);
381 380 }
382 381
383 382 static int
384 383 cmp_priority(char *s1, char *s2, uint64_t t1, uint64_t t2, uint8_t p1,
385 384 uint8_t p2)
386 385 {
387 386 int r1, r2;
388 387 int rt;
389 388
390 389 r1 = set_priority(s1);
391 390 r2 = set_priority(s2);
392 391 rt = r1 - r2;
393 392 if (rt == 0) {
394 393 if (t1 > t2)
395 394 rt = 1;
396 395 else if (t1 < t2)
397 396 rt = -1;
398 397 else
399 398 rt = p1 - p2;
400 399 }
401 400 return (rt);
402 401 }
403 402
404 403 /*
405 404 * merge two lists into one, by comparing enties in new and moving into list if
406 405 * name is not there or free off memory for names which are already there
407 406 * add_pct indicates if pct is the sum or highest pct
408 407 */
409 408 static name_list_t *
410 409 merge_name_list(name_list_t **list, name_list_t *new, int add_pct)
411 410 {
412 411 name_list_t *lp, *np, *sp, *rt = NULL;
413 412 int max_pct;
414 413
415 414 rt = *list;
416 415 np = new;
417 416 while (np) {
418 417 lp = *list;
419 418 while (lp) {
420 419 if (strcmp(lp->name, np->name) == 0)
421 420 break;
422 421 lp = lp->next;
423 422 if (lp == *list)
424 423 lp = NULL;
425 424 }
426 425 if (np->next == new)
427 426 sp = NULL;
428 427 else
429 428 sp = np->next;
430 429 if (lp) {
431 430 lp->status |= (np->status & FM_SUSPECT_FAULTY);
432 431 if (add_pct) {
433 432 lp->pct += np->pct;
434 433 lp->count += np->count;
435 434 } else if (np->pct > lp->pct) {
436 435 lp->pct = np->pct;
437 436 }
438 437 max_pct = np->max_pct;
439 438 if (np->label)
440 439 free(np->label);
441 440 free(np->name);
442 441 free(np);
443 442 np = NULL;
444 443 if (max_pct > lp->max_pct) {
445 444 lp->max_pct = max_pct;
446 445 if (lp->max_pct > lp->prev->max_pct &&
447 446 lp != *list) {
448 447 lp->prev->next = lp->next;
449 448 lp->next->prev = lp->prev;
450 449 np = lp;
451 450 }
452 451 }
453 452 }
454 453 if (np) {
455 454 lp = *list;
456 455 if (lp) {
457 456 if (np->max_pct > lp->max_pct) {
458 457 np->next = lp;
459 458 np->prev = lp->prev;
460 459 lp->prev->next = np;
461 460 lp->prev = np;
462 461 *list = np;
463 462 rt = np;
464 463 } else {
465 464 lp = lp->next;
466 465 while (lp != *list &&
467 466 np->max_pct < lp->max_pct) {
468 467 lp = lp->next;
469 468 }
470 469 np->next = lp;
471 470 np->prev = lp->prev;
472 471 lp->prev->next = np;
473 472 lp->prev = np;
474 473 }
475 474 } else {
476 475 *list = np;
477 476 np->next = np;
478 477 np->prev = np;
479 478 rt = np;
480 479 }
481 480 }
482 481 np = sp;
483 482 }
484 483 return (rt);
485 484 }
486 485
487 486 static name_list_t *
488 487 alloc_name_list(char *name, uint8_t pct)
489 488 {
490 489 name_list_t *nlp;
491 490
492 491 nlp = malloc(sizeof (*nlp));
493 492 nlp->name = strdup(name);
494 493 nlp->pct = pct;
495 494 nlp->max_pct = pct;
496 495 nlp->count = 1;
497 496 nlp->next = nlp;
498 497 nlp->prev = nlp;
499 498 nlp->status = 0;
500 499 nlp->label = NULL;
501 500 return (nlp);
502 501 }
503 502
504 503 static status_record_t *
505 504 new_record_init(uurec_t *uurec_p, char *msgid, name_list_t *class,
506 505 name_list_t *fru, name_list_t *asru, name_list_t *resource,
507 506 name_list_t *serial, boolean_t not_suppressed,
508 507 hostid_t *hostid, boolean_t injected)
509 508 {
510 509 status_record_t *status_rec_p;
511 510
512 511 status_rec_p = (status_record_t *)malloc(sizeof (status_record_t));
513 512 status_rec_p->nrecs = 1;
514 513 status_rec_p->host = hostid;
515 514 status_rec_p->uurec = uurec_p;
516 515 uurec_p->next = NULL;
517 516 uurec_p->prev = NULL;
518 517 uurec_p->asru = asru;
519 518 if ((status_rec_p->severity = fmd_msg_getitem_id(fmadm_msghdl, NULL,
520 519 msgid, FMD_MSG_ITEM_SEVERITY)) == NULL)
521 520 status_rec_p->severity = strdup("unknown");
522 521 status_rec_p->class = class;
523 522 status_rec_p->fru = fru;
524 523 status_rec_p->asru = asru;
525 524 status_rec_p->resource = resource;
526 525 status_rec_p->serial = serial;
527 526 status_rec_p->msgid = strdup(msgid);
528 527 status_rec_p->not_suppressed = not_suppressed;
529 528 status_rec_p->injected = injected;
530 529 return (status_rec_p);
531 530 }
532 531
533 532 /*
534 533 * add record to given list maintaining order higher priority first.
535 534 */
536 535 static void
537 536 add_rec_list(status_record_t *status_rec_p, sr_list_t **list_pp)
538 537 {
539 538 sr_list_t *tp, *np, *sp;
540 539 int order;
541 540 uint64_t sec;
542 541
543 542 np = malloc(sizeof (sr_list_t));
544 543 np->status_record = status_rec_p;
545 544 sec = status_rec_p->uurec->sec;
546 545 if ((sp = *list_pp) == NULL) {
547 546 *list_pp = np;
548 547 np->next = np;
549 548 np->prev = np;
550 549 } else {
551 550 /* insert new record in front of lower priority */
552 551 tp = sp;
553 552 order = cmp_priority(status_rec_p->severity,
554 553 sp->status_record->severity, sec,
555 554 tp->status_record->uurec->sec, 0, 0);
556 555 if (order > 0) {
557 556 *list_pp = np;
558 557 } else {
559 558 tp = sp->next;
560 559 while (tp != sp &&
561 560 cmp_priority(status_rec_p->severity,
562 561 tp->status_record->severity, sec,
563 562 tp->status_record->uurec->sec, 0, 0)) {
564 563 tp = tp->next;
565 564 }
566 565 }
567 566 np->next = tp;
568 567 np->prev = tp->prev;
569 568 tp->prev->next = np;
570 569 tp->prev = np;
571 570 }
572 571 }
573 572
574 573 static void
575 574 add_resource(status_record_t *status_rec_p, resource_list_t **rp,
576 575 resource_list_t *np)
577 576 {
578 577 int order;
579 578 uint64_t sec;
580 579 resource_list_t *sp, *tp;
581 580 status_record_t *srp;
582 581 char *severity = status_rec_p->severity;
583 582
584 583 add_rec_list(status_rec_p, &np->status_rec_list);
585 584 if ((sp = *rp) == NULL) {
586 585 np->next = np;
587 586 np->prev = np;
588 587 *rp = np;
589 588 } else {
590 589 /*
591 590 * insert new record in front of lower priority
592 591 */
593 592 tp = sp->next;
594 593 srp = sp->status_rec_list->status_record;
595 594 sec = status_rec_p->uurec->sec;
596 595 order = cmp_priority(severity, srp->severity, sec,
597 596 srp->uurec->sec, np->max_pct, sp->max_pct);
598 597 if (order > 0) {
599 598 *rp = np;
600 599 } else {
601 600 srp = tp->status_rec_list->status_record;
602 601 while (tp != sp &&
603 602 cmp_priority(severity, srp->severity, sec,
604 603 srp->uurec->sec, np->max_pct, sp->max_pct) < 0) {
605 604 tp = tp->next;
606 605 srp = tp->status_rec_list->status_record;
607 606 }
608 607 }
609 608 np->next = tp;
610 609 np->prev = tp->prev;
611 610 tp->prev->next = np;
612 611 tp->prev = np;
613 612 }
614 613 }
615 614
616 615 static void
617 616 add_resource_list(status_record_t *status_rec_p, name_list_t *fp,
618 617 resource_list_t **rpp)
619 618 {
620 619 int order;
621 620 resource_list_t *np, *end;
622 621 status_record_t *srp;
623 622
624 623 np = *rpp;
625 624 end = np;
626 625 while (np) {
627 626 if (strcmp(fp->name, np->resource) == 0) {
628 627 np->not_suppressed |= status_rec_p->not_suppressed;
629 628 np->injected |= status_rec_p->injected;
630 629 srp = np->status_rec_list->status_record;
631 630 order = cmp_priority(status_rec_p->severity,
632 631 srp->severity, status_rec_p->uurec->sec,
633 632 srp->uurec->sec, fp->max_pct, np->max_pct);
634 633 if (order > 0 && np != end) {
635 634 /*
636 635 * remove from list and add again using
637 636 * new priority
638 637 */
639 638 np->prev->next = np->next;
640 639 np->next->prev = np->prev;
641 640 add_resource(status_rec_p,
642 641 rpp, np);
643 642 } else {
644 643 add_rec_list(status_rec_p,
645 644 &np->status_rec_list);
646 645 }
647 646 break;
648 647 }
649 648 np = np->next;
650 649 if (np == end) {
651 650 np = NULL;
652 651 break;
653 652 }
654 653 }
655 654 if (np == NULL) {
656 655 np = malloc(sizeof (resource_list_t));
657 656 np->resource = fp->name;
658 657 np->not_suppressed = status_rec_p->not_suppressed;
659 658 np->injected = status_rec_p->injected;
660 659 np->status_rec_list = NULL;
661 660 np->max_pct = fp->max_pct;
662 661 add_resource(status_rec_p, rpp, np);
663 662 }
664 663 }
665 664
666 665 static void
667 666 add_list(status_record_t *status_rec_p, name_list_t *listp,
668 667 resource_list_t **glistp)
669 668 {
670 669 name_list_t *fp, *end;
671 670
672 671 fp = listp;
673 672 end = fp;
674 673 while (fp) {
675 674 add_resource_list(status_rec_p, fp, glistp);
676 675 fp = fp->next;
677 676 if (fp == end)
678 677 break;
679 678 }
680 679 }
681 680
682 681 /*
683 682 * add record to rec, fru and asru lists.
684 683 */
685 684 static void
686 685 catalog_new_record(uurec_t *uurec_p, char *msgid, name_list_t *class,
687 686 name_list_t *fru, name_list_t *asru, name_list_t *resource,
688 687 name_list_t *serial, boolean_t not_suppressed,
689 688 hostid_t *hostid, boolean_t injected, boolean_t dummy_fru)
690 689 {
691 690 status_record_t *status_rec_p;
692 691
693 692 status_rec_p = new_record_init(uurec_p, msgid, class, fru, asru,
694 693 resource, serial, not_suppressed, hostid, injected);
695 694 add_rec_list(status_rec_p, &status_rec_list);
696 695 if (status_rec_p->fru && !dummy_fru)
697 696 add_list(status_rec_p, status_rec_p->fru, &status_fru_list);
698 697 if (status_rec_p->asru)
699 698 add_list(status_rec_p, status_rec_p->asru, &status_asru_list);
700 699 }
701 700
702 701 static void
703 702 get_serial_no(nvlist_t *nvl, name_list_t **serial_p, uint8_t pct)
704 703 {
705 704 char *name;
706 705 char *serial = NULL;
707 706 char **lserial = NULL;
708 707 uint64_t serint;
709 708 name_list_t *nlp;
710 709 int j;
711 710 uint_t nelem;
712 711 char buf[64];
713 712
714 713 if (nvlist_lookup_string(nvl, FM_FMRI_SCHEME, &name) == 0) {
715 714 if (strcmp(name, FM_FMRI_SCHEME_CPU) == 0) {
716 715 if (nvlist_lookup_uint64(nvl, FM_FMRI_CPU_SERIAL_ID,
717 716 &serint) == 0) {
718 717 (void) snprintf(buf, sizeof (buf), "%llX",
719 718 serint);
720 719 nlp = alloc_name_list(buf, pct);
721 720 (void) merge_name_list(serial_p, nlp, 1);
722 721 }
723 722 } else if (strcmp(name, FM_FMRI_SCHEME_MEM) == 0) {
724 723 if (nvlist_lookup_string_array(nvl,
725 724 FM_FMRI_MEM_SERIAL_ID, &lserial, &nelem) == 0) {
726 725 nlp = alloc_name_list(lserial[0], pct);
727 726 for (j = 1; j < nelem; j++) {
728 727 name_list_t *n1lp;
729 728 n1lp = alloc_name_list(lserial[j], pct);
730 729 (void) merge_name_list(&nlp, n1lp, 1);
731 730 }
732 731 (void) merge_name_list(serial_p, nlp, 1);
733 732 }
734 733 } else if (strcmp(name, FM_FMRI_SCHEME_HC) == 0) {
735 734 if (nvlist_lookup_string(nvl, FM_FMRI_HC_SERIAL_ID,
736 735 &serial) == 0) {
737 736 nlp = alloc_name_list(serial, pct);
738 737 (void) merge_name_list(serial_p, nlp, 1);
739 738 }
740 739 }
741 740 }
742 741 }
743 742
744 743 static void
745 744 extract_record_info(nvlist_t *nvl, name_list_t **class_p,
746 745 name_list_t **fru_p, name_list_t **serial_p, name_list_t **resource_p,
747 746 name_list_t **asru_p, boolean_t *dummy_fru, uint8_t status)
748 747 {
749 748 nvlist_t *lfru, *lasru, *rsrc;
750 749 name_list_t *nlp;
751 750 char *name;
752 751 uint8_t lpct = 0;
753 752 char *lclass = NULL;
754 753 char *label;
755 754
756 755 (void) nvlist_lookup_uint8(nvl, FM_FAULT_CERTAINTY, &lpct);
757 756 if (nvlist_lookup_string(nvl, FM_CLASS, &lclass) == 0) {
758 757 nlp = alloc_name_list(lclass, lpct);
759 758 (void) merge_name_list(class_p, nlp, 1);
760 759 }
761 760 if (nvlist_lookup_nvlist(nvl, FM_FAULT_FRU, &lfru) == 0) {
762 761 name = get_nvl2str_topo(lfru);
763 762 if (name != NULL) {
764 763 nlp = alloc_name_list(name, lpct);
765 764 nlp->status = status & ~(FM_SUSPECT_UNUSABLE |
766 765 FM_SUSPECT_DEGRADED);
767 766 free(name);
768 767 if (nvlist_lookup_string(nvl, FM_FAULT_LOCATION,
769 768 &label) == 0)
770 769 nlp->label = strdup(label);
771 770 (void) merge_name_list(fru_p, nlp, 1);
772 771 }
773 772 get_serial_no(lfru, serial_p, lpct);
774 773 } else if (nvlist_lookup_nvlist(nvl, FM_FAULT_RESOURCE, &rsrc) != 0) {
775 774 /*
776 775 * No FRU or resource. But we want to display the repair status
777 776 * somehow, so create a dummy FRU field.
778 777 */
779 778 *dummy_fru = 1;
780 779 nlp = alloc_name_list(dgettext("FMD", "None"), lpct);
781 780 nlp->status = status & ~(FM_SUSPECT_UNUSABLE |
782 781 FM_SUSPECT_DEGRADED);
783 782 (void) merge_name_list(fru_p, nlp, 1);
784 783 }
785 784 if (nvlist_lookup_nvlist(nvl, FM_FAULT_ASRU, &lasru) == 0) {
786 785 name = get_nvl2str_topo(lasru);
787 786 if (name != NULL) {
788 787 nlp = alloc_name_list(name, lpct);
789 788 nlp->status = status & ~(FM_SUSPECT_NOT_PRESENT |
790 789 FM_SUSPECT_REPAIRED | FM_SUSPECT_REPLACED |
791 790 FM_SUSPECT_ACQUITTED);
792 791 free(name);
793 792 (void) merge_name_list(asru_p, nlp, 1);
794 793 }
795 794 get_serial_no(lasru, serial_p, lpct);
796 795 }
797 796 if (nvlist_lookup_nvlist(nvl, FM_FAULT_RESOURCE, &rsrc) == 0) {
798 797 name = get_nvl2str_topo(rsrc);
799 798 if (name != NULL) {
800 799 nlp = alloc_name_list(name, lpct);
801 800 nlp->status = status;
802 801 free(name);
803 802 if (nvlist_lookup_string(nvl, FM_FAULT_LOCATION,
804 803 &label) == 0)
805 804 nlp->label = strdup(label);
806 805 (void) merge_name_list(resource_p, nlp, 1);
807 806 }
808 807 }
809 808 }
810 809
811 810 static void
812 811 add_fault_record_to_catalog(nvlist_t *nvl, uint64_t sec, char *uuid)
813 812 {
814 813 char *msgid = "-";
815 814 uint_t i, size = 0;
816 815 name_list_t *class = NULL, *resource = NULL;
817 816 name_list_t *asru = NULL, *fru = NULL, *serial = NULL;
818 817 nvlist_t **nva;
819 818 uint8_t *ba;
820 819 uurec_t *uurec_p;
821 820 hostid_t *host;
822 821 boolean_t not_suppressed = 1;
823 822 boolean_t any_present = 0;
824 823 boolean_t injected = 0;
825 824 boolean_t dummy_fru = 0;
826 825
827 826 (void) nvlist_lookup_string(nvl, FM_SUSPECT_DIAG_CODE, &msgid);
828 827 (void) nvlist_lookup_uint32(nvl, FM_SUSPECT_FAULT_SZ, &size);
829 828 (void) nvlist_lookup_boolean_value(nvl, FM_SUSPECT_MESSAGE,
830 829 ¬_suppressed);
831 830 (void) nvlist_lookup_boolean_value(nvl, FM_SUSPECT_INJECTED, &injected);
832 831
833 832 if (size != 0) {
834 833 (void) nvlist_lookup_nvlist_array(nvl, FM_SUSPECT_FAULT_LIST,
835 834 &nva, &size);
836 835 (void) nvlist_lookup_uint8_array(nvl, FM_SUSPECT_FAULT_STATUS,
837 836 &ba, &size);
838 837 for (i = 0; i < size; i++) {
839 838 extract_record_info(nva[i], &class, &fru, &serial,
840 839 &resource, &asru, &dummy_fru, ba[i]);
841 840 if (!(ba[i] & FM_SUSPECT_NOT_PRESENT) &&
842 841 (ba[i] & FM_SUSPECT_FAULTY))
843 842 any_present = 1;
844 843 }
845 844 /*
846 845 * also suppress if no resources present
847 846 */
848 847 if (any_present == 0)
849 848 not_suppressed = 0;
850 849 }
851 850
852 851 uurec_p = (uurec_t *)malloc(sizeof (uurec_t));
853 852 uurec_p->uuid = strdup(uuid);
854 853 uurec_p->sec = sec;
855 854 uurec_p->ari_uuid_list = NULL;
856 855 uurec_p->event = NULL;
857 856 (void) nvlist_dup(nvl, &uurec_p->event, 0);
858 857 host = find_hostid(nvl);
859 858 catalog_new_record(uurec_p, msgid, class, fru, asru,
860 859 resource, serial, not_suppressed, host, injected, dummy_fru);
861 860 }
862 861
863 862 static void
864 863 update_asru_state_in_catalog(const char *uuid, const char *ari_uuid)
865 864 {
866 865 sr_list_t *srp;
867 866 uurec_t *uurp;
868 867 ari_list_t *ari_list;
869 868
870 869 srp = status_rec_list;
871 870 if (srp) {
872 871 for (;;) {
873 872 uurp = srp->status_record->uurec;
874 873 while (uurp) {
875 874 if (strcmp(uuid, uurp->uuid) == 0) {
876 875 ari_list = (ari_list_t *)
877 876 malloc(sizeof (ari_list_t));
878 877 ari_list->ari_uuid = strdup(ari_uuid);
879 878 ari_list->next = uurp->ari_uuid_list;
880 879 uurp->ari_uuid_list = ari_list;
881 880 return;
882 881 }
883 882 uurp = uurp->next;
884 883 }
885 884 if (srp->next == status_rec_list)
886 885 break;
887 886 srp = srp->next;
888 887 }
889 888 }
890 889 }
891 890
892 891 static void
893 892 print_line(char *label, char *buf)
894 893 {
895 894 char *cp, *ep, *wp;
896 895 char c;
897 896 int i;
898 897 int lsz;
899 898 char *padding;
900 899
901 900 lsz = strlen(label);
902 901 padding = malloc(lsz + 1);
903 902 for (i = 0; i < lsz; i++)
904 903 padding[i] = ' ';
905 904 padding[i] = 0;
906 905 cp = buf;
907 906 ep = buf;
908 907 c = *ep;
909 908 (void) printf("\n");
910 909 while (c) {
911 910 i = lsz;
912 911 wp = NULL;
913 912 while ((c = *ep) != NULL && (wp == NULL || i < 80)) {
914 913 if (c == ' ')
915 914 wp = ep;
916 915 else if (c == '\n') {
917 916 i = 0;
918 917 *ep = 0;
919 918 do {
920 919 ep++;
921 920 } while ((c = *ep) != NULL && c == ' ');
922 921 break;
923 922 }
924 923 ep++;
925 924 i++;
926 925 }
927 926 if (i >= 80 && wp) {
928 927 *wp = 0;
929 928 ep = wp + 1;
930 929 c = *ep;
931 930 }
932 931 (void) printf("%s%s\n", label, cp);
933 932 cp = ep;
934 933 label = padding;
935 934 }
936 935 free(padding);
937 936 }
938 937
939 938 static void
940 939 print_dict_info_line(nvlist_t *e, fmd_msg_item_t what, const char *linehdr)
941 940 {
942 941 char *cp = fmd_msg_getitem_nv(fmadm_msghdl, NULL, e, what);
943 942
944 943 if (cp) {
945 944 print_line(dgettext("FMD", linehdr), cp);
946 945 free(cp);
947 946 }
948 947 }
949 948
950 949 static void
951 950 print_dict_info(nvlist_t *nvl)
952 951 {
953 952 print_dict_info_line(nvl, FMD_MSG_ITEM_DESC, "Description : ");
954 953 print_dict_info_line(nvl, FMD_MSG_ITEM_RESPONSE, "Response : ");
955 954 print_dict_info_line(nvl, FMD_MSG_ITEM_IMPACT, "Impact : ");
956 955 print_dict_info_line(nvl, FMD_MSG_ITEM_ACTION, "Action : ");
957 956 }
958 957
959 958 static void
960 959 print_name(name_list_t *list, char *padding, int *np, int pct, int full)
961 960 {
962 961 char *name;
963 962
964 963 name = list->name;
965 964 if (list->label) {
966 965 (void) printf("%s \"%s\" (%s)", padding, list->label, name);
967 966 *np += 1;
968 967 } else {
969 968 (void) printf("%s %s", padding, name);
970 969 *np += 1;
971 970 }
972 971 if (list->pct && pct > 0 && pct < 100) {
973 972 if (list->count > 1) {
974 973 if (full) {
975 974 (void) printf(" %d @ %s %d%%\n", list->count,
976 975 dgettext("FMD", "max"),
977 976 list->max_pct);
978 977 } else {
979 978 (void) printf(" %s %d%%\n",
980 979 dgettext("FMD", "max"),
981 980 list->max_pct);
982 981 }
983 982 } else {
984 983 (void) printf(" %d%%\n", list->pct);
985 984 }
986 985 } else {
987 986 (void) printf("\n");
988 987 }
989 988 }
990 989
991 990 static void
992 991 print_asru_status(int status, char *label)
993 992 {
994 993 char *msg = NULL;
995 994
996 995 switch (status) {
997 996 case 0:
998 997 msg = dgettext("FMD", "ok and in service");
999 998 break;
1000 999 case FM_SUSPECT_DEGRADED:
1001 1000 msg = dgettext("FMD", "service degraded, "
1002 1001 "but associated components no longer faulty");
1003 1002 break;
1004 1003 case FM_SUSPECT_FAULTY | FM_SUSPECT_DEGRADED:
1005 1004 msg = dgettext("FMD", "faulted but still "
1006 1005 "providing degraded service");
1007 1006 break;
1008 1007 case FM_SUSPECT_FAULTY:
1009 1008 msg = dgettext("FMD", "faulted but still in service");
1010 1009 break;
1011 1010 case FM_SUSPECT_UNUSABLE:
1012 1011 msg = dgettext("FMD", "out of service, "
1013 1012 "but associated components no longer faulty");
1014 1013 break;
1015 1014 case FM_SUSPECT_FAULTY | FM_SUSPECT_UNUSABLE:
1016 1015 msg = dgettext("FMD", "faulted and taken out of service");
1017 1016 break;
1018 1017 default:
1019 1018 break;
1020 1019 }
1021 1020 if (msg) {
1022 1021 (void) printf("%s %s\n", label, msg);
1023 1022 }
1024 1023 }
1025 1024
1026 1025 static void
1027 1026 print_fru_status(int status, char *label)
1028 1027 {
1029 1028 char *msg = NULL;
1030 1029
1031 1030 if (status & FM_SUSPECT_NOT_PRESENT)
1032 1031 msg = dgettext("FMD", "not present");
1033 1032 else if (status & FM_SUSPECT_FAULTY)
1034 1033 msg = dgettext("FMD", "faulty");
1035 1034 else if (status & FM_SUSPECT_REPLACED)
1036 1035 msg = dgettext("FMD", "replaced");
1037 1036 else if (status & FM_SUSPECT_REPAIRED)
1038 1037 msg = dgettext("FMD", "repair attempted");
1039 1038 else if (status & FM_SUSPECT_ACQUITTED)
1040 1039 msg = dgettext("FMD", "acquitted");
1041 1040 else
1042 1041 msg = dgettext("FMD", "removed");
1043 1042 (void) printf("%s %s\n", label, msg);
1044 1043 }
1045 1044
1046 1045 static void
1047 1046 print_rsrc_status(int status, char *label)
1048 1047 {
1049 1048 char *msg = "";
1050 1049
1051 1050 if (status & FM_SUSPECT_NOT_PRESENT)
1052 1051 msg = dgettext("FMD", "not present");
1053 1052 else if (status & FM_SUSPECT_FAULTY) {
1054 1053 if (status & FM_SUSPECT_DEGRADED)
1055 1054 msg = dgettext("FMD",
1056 1055 "faulted but still providing degraded service");
1057 1056 else if (status & FM_SUSPECT_UNUSABLE)
1058 1057 msg = dgettext("FMD",
1059 1058 "faulted and taken out of service");
1060 1059 else
1061 1060 msg = dgettext("FMD", "faulted but still in service");
1062 1061 } else if (status & FM_SUSPECT_REPLACED)
1063 1062 msg = dgettext("FMD", "replaced");
1064 1063 else if (status & FM_SUSPECT_REPAIRED)
1065 1064 msg = dgettext("FMD", "repair attempted");
1066 1065 else if (status & FM_SUSPECT_ACQUITTED)
1067 1066 msg = dgettext("FMD", "acquitted");
1068 1067 else
1069 1068 msg = dgettext("FMD", "removed");
1070 1069 (void) printf("%s %s\n", label, msg);
1071 1070 }
1072 1071
1073 1072 static void
1074 1073 print_name_list(name_list_t *list, char *label,
1075 1074 int limit, int pct, void (func1)(int, char *), int full)
1076 1075 {
1077 1076 char *name;
1078 1077 char *padding;
1079 1078 int i, j, l, n;
1080 1079 name_list_t *end = list;
1081 1080
1082 1081 l = strlen(label);
1083 1082 padding = malloc(l + 1);
1084 1083 for (i = 0; i < l; i++)
1085 1084 padding[i] = ' ';
1086 1085 padding[l] = 0;
1087 1086 (void) printf("%s", label);
1088 1087 name = list->name;
1089 1088 if (list->label)
1090 1089 (void) printf(" \"%s\" (%s)", list->label, name);
1091 1090 else
1092 1091 (void) printf(" %s", name);
1093 1092 if (list->pct && pct > 0 && pct < 100) {
1094 1093 if (list->count > 1) {
1095 1094 if (full) {
1096 1095 (void) printf(" %d @ %s %d%%\n", list->count,
1097 1096 dgettext("FMD", "max"), list->max_pct);
1098 1097 } else {
1099 1098 (void) printf(" %s %d%%\n",
1100 1099 dgettext("FMD", "max"), list->max_pct);
1101 1100 }
1102 1101 } else {
1103 1102 (void) printf(" %d%%\n", list->pct);
1104 1103 }
1105 1104 } else {
1106 1105 (void) printf("\n");
1107 1106 }
1108 1107 if (func1)
1109 1108 func1(list->status, padding);
1110 1109 n = 1;
1111 1110 j = 0;
1112 1111 while ((list = list->next) != end) {
1113 1112 if (limit == 0 || n < limit) {
1114 1113 print_name(list, padding, &n, pct, full);
1115 1114 if (func1)
1116 1115 func1(list->status, padding);
1117 1116 } else
1118 1117 j++;
1119 1118 }
1120 1119 if (j == 1) {
1121 1120 print_name(list->prev, padding, &n, pct, full);
1122 1121 } else if (j > 1) {
1123 1122 (void) printf("%s... %d %s\n", padding, j,
1124 1123 dgettext("FMD", "more entries suppressed,"
1125 1124 " use -v option for full list"));
1126 1125 }
1127 1126 free(padding);
1128 1127 }
1129 1128
1130 1129 static int
1131 1130 asru_same_status(name_list_t *list)
1132 1131 {
1133 1132 name_list_t *end = list;
1134 1133 int status = list->status;
1135 1134
1136 1135 while ((list = list->next) != end) {
1137 1136 if (status == -1) {
1138 1137 status = list->status;
1139 1138 continue;
1140 1139 }
1141 1140 if (list->status != -1 && status != list->status) {
1142 1141 status = -1;
1143 1142 break;
1144 1143 }
1145 1144 }
1146 1145 return (status);
1147 1146 }
1148 1147
1149 1148 static int
1150 1149 serial_in_fru(name_list_t *fru, name_list_t *serial)
1151 1150 {
1152 1151 name_list_t *sp = serial;
1153 1152 name_list_t *fp;
1154 1153 int nserial = 0;
1155 1154 int found = 0;
1156 1155 char buf[128];
1157 1156
1158 1157 while (sp) {
1159 1158 fp = fru;
1160 1159 nserial++;
1161 1160 (void) snprintf(buf, sizeof (buf), "serial=%s", sp->name);
1162 1161 buf[sizeof (buf) - 1] = 0;
1163 1162 while (fp) {
1164 1163 if (strstr(fp->name, buf) != NULL) {
1165 1164 found++;
1166 1165 break;
1167 1166 }
1168 1167 fp = fp->next;
1169 1168 if (fp == fru)
1170 1169 break;
1171 1170 }
1172 1171 sp = sp->next;
1173 1172 if (sp == serial)
1174 1173 break;
1175 1174 }
1176 1175 return (found == nserial ? 1 : 0);
1177 1176 }
1178 1177
1179 1178 static void
1180 1179 print_sup_record(status_record_t *srp, int opt_i, int full)
1181 1180 {
1182 1181 char buf[32];
1183 1182 uurec_t *uurp = srp->uurec;
1184 1183 int n, j, k, max;
1185 1184 int status;
1186 1185 ari_list_t *ari_list;
1187 1186
1188 1187 n = 0;
1189 1188 max = max_fault;
1190 1189 if (max < 0) {
1191 1190 max = 0;
1192 1191 }
1193 1192 j = max / 2;
1194 1193 max -= j;
1195 1194 k = srp->nrecs - max;
1196 1195 while ((uurp = uurp->next) != NULL) {
1197 1196 if (full || n < j || n >= k || max_fault == 0 ||
1198 1197 srp->nrecs == max_fault+1) {
1199 1198 if (opt_i) {
1200 1199 ari_list = uurp->ari_uuid_list;
1201 1200 while (ari_list) {
1202 1201 (void) printf("%-15s %s\n",
1203 1202 format_date(buf, sizeof (buf),
1204 1203 uurp->sec), ari_list->ari_uuid);
1205 1204 ari_list = ari_list->next;
1206 1205 }
1207 1206 } else {
1208 1207 (void) printf("%-15s %s\n",
1209 1208 format_date(buf, sizeof (buf), uurp->sec),
1210 1209 uurp->uuid);
1211 1210 }
1212 1211 } else if (n == j)
1213 1212 (void) printf("... %d %s\n", srp->nrecs - max_fault,
1214 1213 dgettext("FMD", "more entries suppressed"));
1215 1214 n++;
1216 1215 }
1217 1216 (void) printf("\n");
1218 1217 (void) printf("%s %s", dgettext("FMD", "Host :"),
1219 1218 srp->host->server);
1220 1219 if (srp->host->domain)
1221 1220 (void) printf("\t%s %s", dgettext("FMD", "Domain :"),
1222 1221 srp->host->domain);
1223 1222 (void) printf("\n%s %s", dgettext("FMD", "Platform :"),
1224 1223 srp->host->platform);
1225 1224 (void) printf("\t%s %s", dgettext("FMD", "Chassis_id :"),
1226 1225 srp->host->chassis ? srp->host->chassis : "");
1227 1226 (void) printf("\n%s %s\n\n", dgettext("FMD", "Product_sn :"),
1228 1227 srp->host->product_sn? srp->host->product_sn : "");
1229 1228 if (srp->class)
1230 1229 print_name_list(srp->class,
1231 1230 dgettext("FMD", "Fault class :"), 0, srp->class->pct,
1232 1231 NULL, full);
1233 1232 if (srp->asru) {
1234 1233 status = asru_same_status(srp->asru);
1235 1234 if (status != -1) {
1236 1235 print_name_list(srp->asru,
1237 1236 dgettext("FMD", "Affects :"),
1238 1237 full ? 0 : max_display, 0, NULL, full);
1239 1238 print_asru_status(status, " ");
1240 1239 } else
1241 1240 print_name_list(srp->asru,
1242 1241 dgettext("FMD", "Affects :"),
1243 1242 full ? 0 : max_display, 0, print_asru_status, full);
1244 1243 }
1245 1244 if (full || srp->fru == NULL || srp->asru == NULL) {
1246 1245 if (srp->resource) {
1247 1246 status = asru_same_status(srp->resource);
1248 1247 if (status != -1) {
1249 1248 print_name_list(srp->resource,
1250 1249 dgettext("FMD", "Problem in :"),
1251 1250 full ? 0 : max_display, 0, NULL, full);
1252 1251 print_rsrc_status(status, " ");
1253 1252 } else
1254 1253 print_name_list(srp->resource,
1255 1254 dgettext("FMD", "Problem in :"),
1256 1255 full ? 0 : max_display, 0,
1257 1256 print_rsrc_status, full);
1258 1257 }
1259 1258 }
1260 1259 if (srp->fru) {
1261 1260 status = asru_same_status(srp->fru);
1262 1261 if (status != -1) {
1263 1262 print_name_list(srp->fru, dgettext("FMD",
1264 1263 "FRU :"), 0,
1265 1264 srp->fru->pct == 100 ? 100 : srp->fru->max_pct,
1266 1265 NULL, full);
1267 1266 print_fru_status(status, " ");
1268 1267 } else
1269 1268 print_name_list(srp->fru, dgettext("FMD",
1270 1269 "FRU :"), 0,
1271 1270 srp->fru->pct == 100 ? 100 : srp->fru->max_pct,
1272 1271 print_fru_status, full);
1273 1272 }
1274 1273 if (srp->serial && !serial_in_fru(srp->fru, srp->serial) &&
1275 1274 !serial_in_fru(srp->asru, srp->serial)) {
1276 1275 print_name_list(srp->serial, dgettext("FMD", "Serial ID. :"),
1277 1276 0, 0, NULL, full);
1278 1277 }
1279 1278 print_dict_info(srp->uurec->event);
1280 1279 (void) printf("\n");
1281 1280 }
1282 1281
1283 1282 static void
1284 1283 print_status_record(status_record_t *srp, int summary, int opt_i, int full)
1285 1284 {
1286 1285 char buf[32];
1287 1286 uurec_t *uurp = srp->uurec;
1288 1287 static int header = 0;
1289 1288 char *head;
1290 1289 ari_list_t *ari_list;
1291 1290
1292 1291 if (!summary || !header) {
1293 1292 if (opt_i) {
1294 1293 head = "--------------- "
1295 1294 "------------------------------------ "
1296 1295 "-------------- ---------\n"
1297 1296 "TIME CACHE-ID"
1298 1297 " MSG-ID"
1299 1298 " SEVERITY\n--------------- "
1300 1299 "------------------------------------ "
1301 1300 " -------------- ---------";
1302 1301 } else {
1303 1302 head = "--------------- "
1304 1303 "------------------------------------ "
1305 1304 "-------------- ---------\n"
1306 1305 "TIME EVENT-ID"
1307 1306 " MSG-ID"
1308 1307 " SEVERITY\n--------------- "
1309 1308 "------------------------------------ "
1310 1309 " -------------- ---------";
1311 1310 }
1312 1311 (void) printf("%s\n", dgettext("FMD", head));
1313 1312 header = 1;
1314 1313 }
1315 1314 if (opt_i) {
1316 1315 ari_list = uurp->ari_uuid_list;
1317 1316 while (ari_list) {
1318 1317 (void) printf("%-15s %-37s %-14s %-9s %s\n",
1319 1318 format_date(buf, sizeof (buf), uurp->sec),
1320 1319 ari_list->ari_uuid, srp->msgid, srp->severity,
1321 1320 srp->injected ? dgettext("FMD", "injected") : "");
1322 1321 ari_list = ari_list->next;
1323 1322 }
1324 1323 } else {
1325 1324 (void) printf("%-15s %-37s %-14s %-9s %s\n",
1326 1325 format_date(buf, sizeof (buf), uurp->sec),
1327 1326 uurp->uuid, srp->msgid, srp->severity,
1328 1327 srp->injected ? dgettext("FMD", "injected") : "");
1329 1328 }
1330 1329
1331 1330 if (!summary)
1332 1331 print_sup_record(srp, opt_i, full);
1333 1332 }
1334 1333
1335 1334 static void
1336 1335 print_catalog(int summary, int opt_a, int full, int opt_i, int page_feed)
1337 1336 {
1338 1337 status_record_t *srp;
1339 1338 sr_list_t *slp;
1340 1339
1341 1340 slp = status_rec_list;
1342 1341 if (slp) {
1343 1342 for (;;) {
1344 1343 srp = slp->status_record;
1345 1344 if (opt_a || srp->not_suppressed) {
1346 1345 if (page_feed)
1347 1346 (void) printf("\f\n");
1348 1347 print_status_record(srp, summary, opt_i, full);
1349 1348 }
1350 1349 if (slp->next == status_rec_list)
1351 1350 break;
1352 1351 slp = slp->next;
1353 1352 }
1354 1353 }
1355 1354 }
1356 1355
1357 1356 static name_list_t *
1358 1357 find_fru(status_record_t *srp, char *resource)
1359 1358 {
1360 1359 name_list_t *rt = NULL;
1361 1360 name_list_t *fru = srp->fru;
1362 1361
1363 1362 while (fru) {
1364 1363 if (strcmp(resource, fru->name) == 0) {
1365 1364 rt = fru;
1366 1365 break;
1367 1366 }
1368 1367 fru = fru->next;
1369 1368 if (fru == srp->fru)
1370 1369 break;
1371 1370 }
1372 1371 return (rt);
1373 1372 }
1374 1373
1375 1374 static void
1376 1375 print_fru_line(name_list_t *fru, char *uuid)
1377 1376 {
1378 1377 if (fru->pct == 100) {
1379 1378 (void) printf("%s %d %s %d%%\n", uuid, fru->count,
1380 1379 dgettext("FMD", "suspects in this FRU total certainty"),
1381 1380 100);
1382 1381 } else {
1383 1382 (void) printf("%s %d %s %d%%\n", uuid, fru->count,
1384 1383 dgettext("FMD", "suspects in this FRU max certainty"),
1385 1384 fru->max_pct);
1386 1385 }
1387 1386 }
1388 1387
1389 1388 static void
1390 1389 print_fru(int summary, int opt_a, int opt_i, int page_feed)
1391 1390 {
1392 1391 resource_list_t *tp = status_fru_list;
1393 1392 status_record_t *srp;
1394 1393 sr_list_t *slp, *end;
1395 1394 uurec_t *uurp;
1396 1395 name_list_t *fru;
1397 1396 int status;
1398 1397 ari_list_t *ari_list;
1399 1398
1400 1399 while (tp) {
1401 1400 if (opt_a || tp->not_suppressed) {
1402 1401 if (page_feed)
1403 1402 (void) printf("\f\n");
1404 1403 if (!summary)
1405 1404 (void) printf("-----------------------------"
1406 1405 "---------------------------------------"
1407 1406 "----------\n");
1408 1407 slp = tp->status_rec_list;
1409 1408 end = slp;
1410 1409 do {
1411 1410 srp = slp->status_record;
1412 1411 if (!srp->not_suppressed) {
1413 1412 slp = slp->next;
1414 1413 continue;
1415 1414 }
1416 1415 fru = find_fru(srp, tp->resource);
1417 1416 if (fru) {
1418 1417 if (fru->label)
1419 1418 (void) printf("\"%s\" (%s) ",
1420 1419 fru->label, fru->name);
1421 1420 else
1422 1421 (void) printf("%s ",
1423 1422 fru->name);
1424 1423 break;
1425 1424 }
1426 1425 slp = slp->next;
1427 1426 } while (slp != end);
1428 1427
1429 1428 slp = tp->status_rec_list;
1430 1429 end = slp;
1431 1430 status = 0;
1432 1431 do {
1433 1432 srp = slp->status_record;
1434 1433 if (!srp->not_suppressed) {
1435 1434 slp = slp->next;
1436 1435 continue;
1437 1436 }
1438 1437 fru = srp->fru;
1439 1438 while (fru) {
1440 1439 if (strcmp(tp->resource,
1441 1440 fru->name) == 0)
1442 1441 status |= fru->status;
1443 1442 fru = fru->next;
1444 1443 if (fru == srp->fru)
1445 1444 break;
1446 1445 }
1447 1446 slp = slp->next;
1448 1447 } while (slp != end);
1449 1448 if (status & FM_SUSPECT_NOT_PRESENT)
1450 1449 (void) printf(dgettext("FMD", "not present"));
1451 1450 else if (status & FM_SUSPECT_FAULTY)
1452 1451 (void) printf(dgettext("FMD", "faulty"));
1453 1452 else if (status & FM_SUSPECT_REPLACED)
1454 1453 (void) printf(dgettext("FMD", "replaced"));
1455 1454 else if (status & FM_SUSPECT_REPAIRED)
1456 1455 (void) printf(dgettext("FMD",
1457 1456 "repair attempted"));
1458 1457 else if (status & FM_SUSPECT_ACQUITTED)
1459 1458 (void) printf(dgettext("FMD", "acquitted"));
1460 1459 else
1461 1460 (void) printf(dgettext("FMD", "removed"));
1462 1461
1463 1462 if (tp->injected)
1464 1463 (void) printf(dgettext("FMD", " injected\n"));
1465 1464 else
1466 1465 (void) printf(dgettext("FMD", "\n"));
1467 1466
1468 1467 slp = tp->status_rec_list;
1469 1468 end = slp;
1470 1469 do {
1471 1470 srp = slp->status_record;
1472 1471 if (!srp->not_suppressed) {
1473 1472 slp = slp->next;
1474 1473 continue;
1475 1474 }
1476 1475 uurp = srp->uurec;
1477 1476 fru = find_fru(srp, tp->resource);
1478 1477 if (fru) {
1479 1478 if (opt_i) {
1480 1479 ari_list = uurp->ari_uuid_list;
1481 1480 while (ari_list) {
1482 1481 print_fru_line(fru,
1483 1482 ari_list->ari_uuid);
1484 1483 ari_list =
1485 1484 ari_list->next;
1486 1485 }
1487 1486 } else {
1488 1487 print_fru_line(fru, uurp->uuid);
1489 1488 }
1490 1489 }
1491 1490 slp = slp->next;
1492 1491 } while (slp != end);
1493 1492 if (!summary) {
1494 1493 slp = tp->status_rec_list;
1495 1494 end = slp;
1496 1495 do {
1497 1496 srp = slp->status_record;
1498 1497 if (!srp->not_suppressed) {
1499 1498 slp = slp->next;
1500 1499 continue;
1501 1500 }
1502 1501 if (srp->serial &&
1503 1502 !serial_in_fru(srp->fru,
1504 1503 srp->serial)) {
1505 1504 print_name_list(srp->serial,
1506 1505 dgettext("FMD",
1507 1506 "Serial ID. :"),
1508 1507 0, 0, NULL, 1);
1509 1508 break;
1510 1509 }
1511 1510 slp = slp->next;
1512 1511 } while (slp != end);
1513 1512 }
1514 1513 }
1515 1514 tp = tp->next;
1516 1515 if (tp == status_fru_list)
1517 1516 break;
1518 1517 }
1519 1518 }
1520 1519
1521 1520 static void
1522 1521 print_asru(int opt_a)
1523 1522 {
1524 1523 resource_list_t *tp = status_asru_list;
1525 1524 status_record_t *srp;
1526 1525 sr_list_t *slp, *end;
1527 1526 char *msg;
1528 1527 int status;
1529 1528 name_list_t *asru;
1530 1529
1531 1530 while (tp) {
1532 1531 if (opt_a || tp->not_suppressed) {
1533 1532 status = 0;
1534 1533 slp = tp->status_rec_list;
1535 1534 end = slp;
1536 1535 do {
1537 1536 srp = slp->status_record;
1538 1537 if (!srp->not_suppressed) {
1539 1538 slp = slp->next;
1540 1539 continue;
1541 1540 }
1542 1541 asru = srp->asru;
1543 1542 while (asru) {
1544 1543 if (strcmp(tp->resource,
1545 1544 asru->name) == 0)
1546 1545 status |= asru->status;
1547 1546 asru = asru->next;
1548 1547 if (asru == srp->asru)
1549 1548 break;
1550 1549 }
1551 1550 slp = slp->next;
1552 1551 } while (slp != end);
1553 1552 switch (status) {
1554 1553 case 0:
1555 1554 msg = dgettext("FMD", "ok");
1556 1555 break;
1557 1556 case FM_SUSPECT_DEGRADED:
1558 1557 msg = dgettext("FMD", "degraded");
1559 1558 break;
1560 1559 case FM_SUSPECT_FAULTY | FM_SUSPECT_DEGRADED:
1561 1560 msg = dgettext("FMD", "degraded");
1562 1561 break;
1563 1562 case FM_SUSPECT_FAULTY:
1564 1563 msg = dgettext("FMD", "degraded");
1565 1564 break;
1566 1565 case FM_SUSPECT_UNUSABLE:
1567 1566 msg = dgettext("FMD", "unknown");
1568 1567 break;
1569 1568 case FM_SUSPECT_FAULTY | FM_SUSPECT_UNUSABLE:
1570 1569 msg = dgettext("FMD", "faulted");
1571 1570 break;
1572 1571 default:
1573 1572 msg = "";
1574 1573 break;
1575 1574 }
1576 1575 (void) printf("%-69s %s", tp->resource, msg);
1577 1576 if (tp->injected)
1578 1577 (void) printf(dgettext("FMD", " injected\n"));
1579 1578 else
1580 1579 (void) printf(dgettext("FMD", "\n"));
1581 1580 }
1582 1581 tp = tp->next;
1583 1582 if (tp == status_asru_list)
1584 1583 break;
1585 1584 }
1586 1585 }
1587 1586
1588 1587 static int
1589 1588 uuid_in_list(char *uuid, uurec_select_t *uurecp)
1590 1589 {
1591 1590 while (uurecp) {
1592 1591 if (strcmp(uuid, uurecp->uuid) == 0)
1593 1592 return (1);
1594 1593 uurecp = uurecp->next;
1595 1594 }
1596 1595 return (0);
1597 1596 }
1598 1597
1599 1598 static int
1600 1599 dfault_rec(const fmd_adm_caseinfo_t *acp, void *arg)
1601 1600 {
1602 1601 int64_t *diag_time;
1603 1602 uint_t nelem;
1604 1603 int rt = 0;
1605 1604 char *uuid = "-";
1606 1605 uurec_select_t *uurecp = (uurec_select_t *)arg;
1607 1606
1608 1607 if (nvlist_lookup_int64_array(acp->aci_event, FM_SUSPECT_DIAG_TIME,
1609 1608 &diag_time, &nelem) == 0 && nelem >= 2) {
1610 1609 (void) nvlist_lookup_string(acp->aci_event, FM_SUSPECT_UUID,
1611 1610 &uuid);
1612 1611 if (uurecp == NULL || uuid_in_list(uuid, uurecp))
1613 1612 add_fault_record_to_catalog(acp->aci_event, *diag_time,
1614 1613 uuid);
1615 1614 } else {
1616 1615 rt = -1;
1617 1616 }
1618 1617 return (rt);
1619 1618 }
1620 1619
1621 1620 /*ARGSUSED*/
1622 1621 static int
1623 1622 dstatus_rec(const fmd_adm_rsrcinfo_t *ari, void *unused)
1624 1623 {
1625 1624 update_asru_state_in_catalog(ari->ari_case, ari->ari_uuid);
1626 1625 return (0);
1627 1626 }
1628 1627
1629 1628 static int
1630 1629 get_cases_from_fmd(fmd_adm_t *adm, uurec_select_t *uurecp, int opt_i)
1631 1630 {
1632 1631 int rt = FMADM_EXIT_SUCCESS;
1633 1632
1634 1633 /*
1635 1634 * These calls may fail with Protocol error if message payload is
1636 1635 * too big
1637 1636 */
1638 1637 if (fmd_adm_case_iter(adm, NULL, dfault_rec, uurecp) != 0)
1639 1638 die("failed to get case list from fmd");
1640 1639 if (opt_i && fmd_adm_rsrc_iter(adm, 1, dstatus_rec, NULL) != 0)
1641 1640 die("failed to get case status from fmd");
1642 1641 return (rt);
1643 1642 }
1644 1643
1645 1644 /*
1646 1645 * fmadm faulty command
1647 1646 *
1648 1647 * -a show hidden fault records
1649 1648 * -f show faulty fru's
1650 1649 * -g force grouping of similar faults on the same fru
1651 1650 * -n number of fault records to display
1652 1651 * -p pipe output through pager
1653 1652 * -r show faulty asru's
1654 1653 * -s print summary of first fault
1655 1654 * -u print listed uuid's only
1656 1655 * -v full output
1657 1656 */
1658 1657
1659 1658 int
1660 1659 cmd_faulty(fmd_adm_t *adm, int argc, char *argv[])
1661 1660 {
1662 1661 int opt_a = 0, opt_v = 0, opt_p = 0, opt_s = 0, opt_r = 0, opt_f = 0;
1663 1662 int opt_i = 0;
1664 1663 char *pager;
1665 1664 FILE *fp;
1666 1665 int rt, c, stat;
1667 1666 uurec_select_t *tp;
1668 1667 uurec_select_t *uurecp = NULL;
1669 1668
1670 1669 while ((c = getopt(argc, argv, "afgin:prsu:v")) != EOF) {
1671 1670 switch (c) {
1672 1671 case 'a':
1673 1672 opt_a++;
1674 1673 break;
1675 1674 case 'f':
1676 1675 opt_f++;
1677 1676 break;
1678 1677 case 'g':
1679 1678 opt_g++;
1680 1679 break;
1681 1680 case 'i':
1682 1681 opt_i++;
1683 1682 break;
1684 1683 case 'n':
1685 1684 max_fault = atoi(optarg);
1686 1685 break;
1687 1686 case 'p':
1688 1687 opt_p++;
1689 1688 break;
1690 1689 case 'r':
1691 1690 opt_r++;
1692 1691 break;
1693 1692 case 's':
1694 1693 opt_s++;
1695 1694 break;
1696 1695 case 'u':
1697 1696 tp = (uurec_select_t *)malloc(sizeof (uurec_select_t));
1698 1697 tp->uuid = optarg;
1699 1698 tp->next = uurecp;
1700 1699 uurecp = tp;
1701 1700 opt_a = 1;
1702 1701 break;
1703 1702 case 'v':
1704 1703 opt_v++;
1705 1704 break;
1706 1705 default:
1707 1706 return (FMADM_EXIT_USAGE);
1708 1707 }
1709 1708 }
1710 1709 if (optind < argc)
1711 1710 return (FMADM_EXIT_USAGE);
1712 1711
1713 1712 if ((fmadm_msghdl = fmd_msg_init(NULL, FMD_MSG_VERSION)) == NULL)
1714 1713 return (FMADM_EXIT_ERROR);
1715 1714 rt = get_cases_from_fmd(adm, uurecp, opt_i);
1716 1715 if (opt_p) {
1717 1716 if ((pager = getenv("PAGER")) == NULL)
1718 1717 pager = "/usr/bin/more";
1719 1718 fp = popen(pager, "w");
1720 1719 if (fp == NULL) {
1721 1720 rt = FMADM_EXIT_ERROR;
1722 1721 opt_p = 0;
1723 1722 } else {
1724 1723 (void) dup2(fileno(fp), 1);
1725 1724 setbuf(stdout, NULL);
1726 1725 (void) fclose(fp);
1727 1726 }
1728 1727 }
1729 1728 max_display = max_fault;
1730 1729 if (opt_f)
1731 1730 print_fru(opt_s, opt_a, opt_i, opt_p && !opt_s);
1732 1731 if (opt_r)
1733 1732 print_asru(opt_a);
1734 1733 if (opt_f == 0 && opt_r == 0)
1735 1734 print_catalog(opt_s, opt_a, opt_v, opt_i, opt_p && !opt_s);
1736 1735 fmd_msg_fini(fmadm_msghdl);
1737 1736 if (topo_handle)
1738 1737 topo_close(topo_handle);
1739 1738 if (opt_p) {
1740 1739 (void) fclose(stdout);
1741 1740 (void) wait(&stat);
1742 1741 }
1743 1742 return (rt);
1744 1743 }
1745 1744
1746 1745 int
1747 1746 cmd_flush(fmd_adm_t *adm, int argc, char *argv[])
1748 1747 {
1749 1748 int i, status = FMADM_EXIT_SUCCESS;
1750 1749
1751 1750 if (argc < 2 || (i = getopt(argc, argv, "")) != EOF)
1752 1751 return (FMADM_EXIT_USAGE);
1753 1752
1754 1753 for (i = 1; i < argc; i++) {
1755 1754 if (fmd_adm_rsrc_flush(adm, argv[i]) != 0) {
1756 1755 warn("failed to flush %s", argv[i]);
1757 1756 status = FMADM_EXIT_ERROR;
1758 1757 } else
1759 1758 note("flushed resource history for %s\n", argv[i]);
1760 1759 }
1761 1760
1762 1761 return (status);
1763 1762 }
1764 1763
1765 1764 int
1766 1765 cmd_repair(fmd_adm_t *adm, int argc, char *argv[])
1767 1766 {
1768 1767 int err;
1769 1768
1770 1769 if (getopt(argc, argv, "") != EOF)
1771 1770 return (FMADM_EXIT_USAGE);
1772 1771
1773 1772 if (argc - optind != 1)
1774 1773 return (FMADM_EXIT_USAGE);
1775 1774
1776 1775 /*
1777 1776 * argument could be a uuid, an fmri (asru, fru or resource)
1778 1777 * or a label. Try uuid first, If that fails try the others.
1779 1778 */
1780 1779 err = fmd_adm_case_repair(adm, argv[optind]);
1781 1780 if (err != 0)
1782 1781 err = fmd_adm_rsrc_repaired(adm, argv[optind]);
1783 1782
1784 1783 if (err != 0)
1785 1784 die("failed to record repair to %s", argv[optind]);
1786 1785
1787 1786 note("recorded repair to %s\n", argv[optind]);
1788 1787 return (FMADM_EXIT_SUCCESS);
1789 1788 }
1790 1789
1791 1790 int
1792 1791 cmd_repaired(fmd_adm_t *adm, int argc, char *argv[])
1793 1792 {
1794 1793 int err;
1795 1794
1796 1795 if (getopt(argc, argv, "") != EOF)
1797 1796 return (FMADM_EXIT_USAGE);
1798 1797
1799 1798 if (argc - optind != 1)
1800 1799 return (FMADM_EXIT_USAGE);
1801 1800
1802 1801 /*
1803 1802 * argument could be an fmri (asru, fru or resource) or a label.
1804 1803 */
1805 1804 err = fmd_adm_rsrc_repaired(adm, argv[optind]);
1806 1805 if (err != 0)
1807 1806 die("failed to record repair to %s", argv[optind]);
1808 1807
1809 1808 note("recorded repair to of %s\n", argv[optind]);
1810 1809 return (FMADM_EXIT_SUCCESS);
1811 1810 }
1812 1811
1813 1812 int
1814 1813 cmd_replaced(fmd_adm_t *adm, int argc, char *argv[])
1815 1814 {
1816 1815 int err;
1817 1816
1818 1817 if (getopt(argc, argv, "") != EOF)
1819 1818 return (FMADM_EXIT_USAGE);
1820 1819
1821 1820 if (argc - optind != 1)
1822 1821 return (FMADM_EXIT_USAGE);
1823 1822
1824 1823 /*
1825 1824 * argument could be an fmri (asru, fru or resource) or a label.
1826 1825 */
1827 1826 err = fmd_adm_rsrc_replaced(adm, argv[optind]);
1828 1827 if (err != 0)
1829 1828 die("failed to record replacement of %s", argv[optind]);
1830 1829
1831 1830 note("recorded replacement of %s\n", argv[optind]);
1832 1831 return (FMADM_EXIT_SUCCESS);
1833 1832 }
1834 1833
1835 1834 int
1836 1835 cmd_acquit(fmd_adm_t *adm, int argc, char *argv[])
1837 1836 {
1838 1837 int err;
1839 1838
1840 1839 if (getopt(argc, argv, "") != EOF)
1841 1840 return (FMADM_EXIT_USAGE);
1842 1841
1843 1842 if (argc - optind != 1 && argc - optind != 2)
1844 1843 return (FMADM_EXIT_USAGE);
1845 1844
1846 1845 /*
1847 1846 * argument could be a uuid, an fmri (asru, fru or resource)
1848 1847 * or a label. Or it could be a uuid and an fmri or label.
1849 1848 */
1850 1849 if (argc - optind == 2) {
1851 1850 err = fmd_adm_rsrc_acquit(adm, argv[optind], argv[optind + 1]);
1852 1851 if (err != 0)
1853 1852 err = fmd_adm_rsrc_acquit(adm, argv[optind + 1],
1854 1853 argv[optind]);
1855 1854 } else {
1856 1855 err = fmd_adm_case_acquit(adm, argv[optind]);
1857 1856 if (err != 0)
1858 1857 err = fmd_adm_rsrc_acquit(adm, argv[optind], "");
1859 1858 }
1860 1859
1861 1860 if (err != 0)
1862 1861 die("failed to record acquital of %s", argv[optind]);
1863 1862
1864 1863 note("recorded acquital of %s\n", argv[optind]);
1865 1864 return (FMADM_EXIT_SUCCESS);
1866 1865 }
↓ open down ↓ |
1807 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX