Print this page
6659 nvlist_free(NULL) is a no-op
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/fm/modules/common/sw-diag-response/subsidiary/panic/panic_diag.c
+++ new/usr/src/cmd/fm/modules/common/sw-diag-response/subsidiary/panic/panic_diag.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 /*
23 23 * Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
24 24 */
25 25
26 26 /*
27 27 * Panic software-diagnosis subsidiary
28 28 *
29 29 * We model a system panic as a defect diagnosis in FMA. When a system
30 30 * panicks, savecore publishes events which we subscribe to here.
31 31 *
32 32 * Our driving events are all raised by savecore, run either from
33 33 * startup of the dumpadm service or interactively at the command line.
34 34 * The following describes the logic for the handling of these events.
35 35 *
36 36 * On reboot after panic we will run savecore as part of the dumpadm
37 37 * service startup; we run savecore even if savecore is otherwise
38 38 * disabled (ie dumpadm -n in effect) - we run savecore -c to check for
39 39 * a valid dump and raise the initial event.
40 40 *
41 41 * If savecore (or savecore -c) observes a valid dump pending on the
42 42 * device, it raises a "dump_pending_on_device" event provided this
43 43 * was not an FMA-initiated panic (for those we will replay ereports
44 44 * from the dump device as usual and make a diagnosis from those; we do
45 45 * not need to open a case for the panic). We subscribe to the
46 46 * "dump_pending_on_device" event and use that to open a case; we
47 47 * open a case requesting the same case uuid as the panic dump image
48 48 * has for the OS instance uuid - if that fails because of a duplicate
49 49 * uuid then we have already opened a case for this panic so no need
50 50 * to open another.
51 51 *
52 52 * Included in the "dump_pending_on_device" event is an indication of
53 53 * whether or not dumpadm is enabled. If not (dumpadm -n in effect)
54 54 * then we do not expect any further events regarding this panic
55 55 * until such time as the admin runs savecore manually (if ever).
56 56 * So in this case we solve the case immediately after open. If/when
57 57 * subsequent events arrive when savecore is run manually, we will toss
58 58 * them.
59 59 *
60 60 * If dumpadm is enabled then savecore, run from dumpadm service startup,
61 61 * will attempt to process the dump - either to copy it off the dump
62 62 * device (if saving compressed) or to uncompress it off the dump device.
63 63 * If this succeeds savecore raises a "dump_available" event which
64 64 * includes information on the directory it was saved in, the instance
65 65 * number, image uuid, compressed form or not, and whether the dump
66 66 * was complete (as per the dumphdr). If the savecore fails for
67 67 * some reason then it exits and raises a "savecore_failure" event.
68 68 * These two events are raised even for FMA-initiated panics.
69 69 *
70 70 * We subscribe to both the "dump_available" and "savecore_failed" events,
71 71 * and in the handling thereof we will close the case opened earlier (if
72 72 * this is not an FMA-initiated panic). On receipt of the initial
73 73 * "dump_available" event we also arm a timer for +10 minutes if
74 74 * dumpadm is enabled - if no "dump_available" or "savecore_failed" arrives
75 75 * in that time we will solve the case on timeout.
76 76 *
77 77 * When the timer fires we check whether the initial event for each panic
78 78 * case was received more than 30 minutes ago; if it was we solve the case
79 79 * with what we have. If we're still within the waiting period we rearm
80 80 * for a further 10 minutes. The timer is shared by all cases that we
81 81 * create, which is why the fire interval is shorter than the maximum time
82 82 * we are prepared to wait.
83 83 */
84 84
85 85 #include <strings.h>
86 86 #include <sys/panic.h>
87 87 #include <alloca.h>
88 88 #include <zone.h>
89 89
90 90 #include "../../common/sw.h"
91 91 #include "panic.h"
92 92
93 93 #define MAX_STRING_LEN 160
94 94
95 95 static id_t myid;
96 96
97 97 static id_t mytimerid;
98 98
99 99 /*
100 100 * Our serialization structure type.
101 101 */
102 102 #define SWDE_PANIC_CASEDATA_VERS 1
103 103
104 104 typedef struct swde_panic_casedata {
105 105 uint32_t scd_vers; /* must be first member */
106 106 uint64_t scd_receive_time; /* when we first knew of this panic */
107 107 size_t scd_nvlbufsz; /* size of following buffer */
108 108 /* packed attr nvlist follows */
109 109 } swde_panic_casedata_t;
110 110
111 111 static struct {
112 112 fmd_stat_t swde_panic_diagnosed;
113 113 fmd_stat_t swde_panic_badclass;
114 114 fmd_stat_t swde_panic_noattr;
115 115 fmd_stat_t swde_panic_unexpected_fm_panic;
116 116 fmd_stat_t swde_panic_badattr;
117 117 fmd_stat_t swde_panic_badfmri;
118 118 fmd_stat_t swde_panic_noinstance;
119 119 fmd_stat_t swde_panic_nouuid;
120 120 fmd_stat_t swde_panic_dupuuid;
121 121 fmd_stat_t swde_panic_nocase;
122 122 fmd_stat_t swde_panic_notime;
123 123 fmd_stat_t swde_panic_nopanicstr;
124 124 fmd_stat_t swde_panic_nodumpdir;
125 125 fmd_stat_t swde_panic_nostack;
126 126 fmd_stat_t swde_panic_incomplete;
127 127 fmd_stat_t swde_panic_failed;
128 128 fmd_stat_t swde_panic_basecasedata;
129 129 fmd_stat_t swde_panic_failsrlz;
130 130 } swde_panic_stats = {
131 131 { "swde_panic_diagnosed", FMD_TYPE_UINT64,
132 132 "panic defects published" },
133 133 { "swde_panic_badclass", FMD_TYPE_UINT64,
134 134 "incorrect event class received" },
135 135 { "swde_panic_noattr", FMD_TYPE_UINT64,
136 136 "malformed event - missing attr nvlist" },
137 137 { "swde_panic_unexpected_fm_panic", FMD_TYPE_UINT64,
138 138 "dump available for an fm_panic()" },
139 139 { "swde_panic_badattr", FMD_TYPE_UINT64,
140 140 "malformed event - invalid attr list" },
141 141 { "swde_panic_badfmri", FMD_TYPE_UINT64,
142 142 "malformed event - fmri2str fails" },
143 143 { "swde_panic_noinstance", FMD_TYPE_UINT64,
144 144 "malformed event - no instance number" },
145 145 { "swde_panic_nouuid", FMD_TYPE_UINT64,
146 146 "malformed event - missing uuid" },
147 147 { "swde_panic_dupuuid", FMD_TYPE_UINT64,
148 148 "duplicate events received" },
149 149 { "swde_panic_nocase", FMD_TYPE_UINT64,
150 150 "case missing for uuid" },
151 151 { "swde_panic_notime", FMD_TYPE_UINT64,
152 152 "missing crash dump time" },
153 153 { "swde_panic_nopanicstr", FMD_TYPE_UINT64,
154 154 "missing panic string" },
155 155 { "swde_panic_nodumpdir", FMD_TYPE_UINT64,
156 156 "missing crashdump save directory" },
157 157 { "swde_panic_nostack", FMD_TYPE_UINT64,
158 158 "missing panic stack" },
159 159 { "swde_panic_incomplete", FMD_TYPE_UINT64,
160 160 "missing panic incomplete" },
161 161 { "swde_panic_failed", FMD_TYPE_UINT64,
162 162 "missing panic failed" },
163 163 { "swde_panic_badcasedata", FMD_TYPE_UINT64,
164 164 "bad case data during timeout" },
165 165 { "swde_panic_failsrlz", FMD_TYPE_UINT64,
166 166 "failures to serialize case data" },
167 167 };
168 168
169 169 #define BUMPSTAT(stat) swde_panic_stats.stat.fmds_value.ui64++
170 170
171 171 static nvlist_t *
172 172 panic_sw_fmri(fmd_hdl_t *hdl, char *object)
173 173 {
174 174 nvlist_t *fmri;
↓ open down ↓ |
174 lines elided |
↑ open up ↑ |
175 175 nvlist_t *sw_obj;
176 176 int err = 0;
177 177
178 178 fmri = fmd_nvl_alloc(hdl, FMD_SLEEP);
179 179 err |= nvlist_add_uint8(fmri, FM_VERSION, FM_SW_SCHEME_VERSION);
180 180 err |= nvlist_add_string(fmri, FM_FMRI_SCHEME, FM_FMRI_SCHEME_SW);
181 181
182 182 sw_obj = fmd_nvl_alloc(hdl, FMD_SLEEP);
183 183 err |= nvlist_add_string(sw_obj, FM_FMRI_SW_OBJ_PATH, object);
184 184 err |= nvlist_add_nvlist(fmri, FM_FMRI_SW_OBJ, sw_obj);
185 - if (sw_obj)
186 - nvlist_free(sw_obj);
185 + nvlist_free(sw_obj);
187 186 if (!err)
188 187 return (fmri);
189 188 else
190 189 return (0);
191 190 }
192 191
193 192 static const char *dumpfiles[2] = { "unix.%lld", "vmcore.%lld" };
194 193 static const char *dumpfiles_comp[2] = { "vmdump.%lld", NULL};
195 194
196 195 static void
197 196 swde_panic_solve(fmd_hdl_t *hdl, fmd_case_t *cp,
198 197 nvlist_t *attr, fmd_event_t *ep, boolean_t savecore_success)
199 198 {
200 199 char *dumpdir, *path, *uuid;
201 200 nvlist_t *defect, *rsrc;
202 201 nvpair_t *nvp;
203 202 int i;
204 203
205 204 /*
206 205 * Attribute members to include in event-specific defect
207 206 * payload. Some attributes will not be present for some
208 207 * cases - e.g., if we timed out and solved the case without
209 208 * a "dump_available" report.
210 209 */
211 210 const char *toadd[] = {
212 211 "os-instance-uuid", /* same as case uuid */
213 212 "panicstr", /* for initial classification work */
214 213 "panicstack", /* for initial classification work */
215 214 "crashtime", /* in epoch time */
216 215 "panic-time", /* Formatted crash time */
217 216 };
218 217
219 218 if (ep != NULL)
220 219 fmd_case_add_ereport(hdl, cp, ep);
221 220 /*
222 221 * As a temporary solution we create and fmri in the sw scheme
223 222 * in panic_sw_fmri. This should become a generic fmri constructor
224 223 *
225 224 * We need to user a resource FMRI which will have a sufficiently
226 225 * unique string representation such that fmd will not see
227 226 * repeated panic diagnoses (all using the same defect class)
228 227 * as duplicates and discard later cases. We can't actually diagnose
229 228 * the panic to anything specific (e.g., a path to a module and
230 229 * function/line etc therein). We could pick on a generic
231 230 * representative such as /kernel/genunix but that could lead
232 231 * to misunderstanding. So we choose a path based on <dumpdir>
233 232 * and the OS instance UUID - "<dumpdir>/.<os-instance-uuid>".
234 233 * There's no file at that path (*) but no matter. We can't use
235 234 * <dumpdir>/vmdump.N or similar because if savecore is disabled
236 235 * or failed we don't have any file or instance number.
237 236 *
238 237 * (*) Some day it would seem tidier to keep all files to do
239 238 * with a single crash (unix/vmcore/vmdump, analysis output etc)
240 239 * in a distinct directory, and <dumpdir>/.<uuid> seems like a good
241 240 * choice. For compatability we'd symlink into it. So that is
242 241 * another reason for this choice - some day it may exist!
243 242 */
244 243 (void) nvlist_lookup_string(attr, "dumpdir", &dumpdir);
245 244 (void) nvlist_lookup_string(attr, "os-instance-uuid", &uuid);
246 245 path = alloca(strlen(dumpdir) + 1 + 1 + 36 + 1);
247 246 /* LINTED: E_SEC_SPRINTF_UNBOUNDED_COPY */
248 247 (void) sprintf(path, "%s/.%s", dumpdir, uuid);
249 248 rsrc = panic_sw_fmri(hdl, path);
250 249
251 250 defect = fmd_nvl_create_defect(hdl, SW_SUNOS_PANIC_DEFECT,
252 251 100, rsrc, NULL, rsrc);
253 252 nvlist_free(rsrc);
254 253
255 254 (void) nvlist_add_boolean_value(defect, "savecore-succcess",
256 255 savecore_success);
257 256
258 257 if (savecore_success) {
259 258 boolean_t compressed;
260 259 int64_t instance;
261 260 const char **pathfmts;
262 261 char buf[2][32];
263 262 int files = 0;
264 263 char *arr[2];
265 264 int i;
266 265
267 266 (void) nvlist_lookup_int64(attr, "instance", &instance);
268 267 (void) nvlist_lookup_boolean_value(attr, "compressed",
269 268 &compressed);
270 269
271 270 pathfmts = compressed ? &dumpfiles_comp[0] : &dumpfiles[0];
272 271
273 272 for (i = 0; i < 2; i++) {
274 273 if (pathfmts[i] == NULL) {
275 274 arr[i] = NULL;
276 275 continue;
277 276 }
278 277
279 278 (void) snprintf(buf[i], 32, pathfmts[i], instance);
280 279 arr[i] = buf[i];
281 280 files++;
282 281 }
283 282
284 283 (void) nvlist_add_string(defect, "dump-dir", dumpdir);
285 284 (void) nvlist_add_string_array(defect, "dump-files", arr,
286 285 files);
287 286 } else {
288 287 char *rsn;
289 288
290 289 if (nvlist_lookup_string(attr, "failure-reason", &rsn) == 0)
291 290 (void) nvlist_add_string(defect, "failure-reason", rsn);
292 291 }
293 292
294 293 /*
295 294 * Not all attributes will necessarily be available - eg if
296 295 * dumpadm was not enabled there'll be no instance and dumpdir.
297 296 */
298 297 for (i = 0; i < sizeof (toadd) / sizeof (toadd[0]); i++) {
299 298 if (nvlist_lookup_nvpair(attr, toadd[i], &nvp) == 0)
300 299 (void) nvlist_add_nvpair(defect, nvp);
301 300 }
302 301
303 302 fmd_case_add_suspect(hdl, cp, defect);
304 303 fmd_case_solve(hdl, cp);
305 304
306 305 /*
307 306 * Close the case. Do no free casedata - framework does that for us
308 307 * on closure callback.
309 308 */
310 309 fmd_case_close(hdl, cp);
311 310 BUMPSTAT(swde_panic_diagnosed);
312 311 }
313 312
314 313 /*ARGSUSED*/
315 314 static void
316 315 swde_panic_timeout(fmd_hdl_t *hdl, id_t timerid, void *data)
317 316 {
318 317 fmd_case_t *cp = swde_case_first(hdl, myid);
319 318 swde_panic_casedata_t *cdp;
320 319 time_t now = time(NULL);
321 320 nvlist_t *attr;
322 321 int remain = 0;
323 322 uint32_t vers;
324 323
325 324 while (cp != NULL) {
326 325 cdp = swde_case_data(hdl, cp, &vers);
327 326 if (vers != SWDE_PANIC_CASEDATA_VERS)
328 327 fmd_hdl_abort(hdl, "case data version confused\n");
329 328
330 329 if (now > cdp->scd_receive_time + 30 * 60) {
331 330 if (nvlist_unpack((char *)cdp + sizeof (*cdp),
332 331 cdp->scd_nvlbufsz, &attr, 0) == 0) {
333 332 swde_panic_solve(hdl, cp, attr, NULL, B_FALSE);
334 333 nvlist_free(attr);
335 334 } else {
336 335 BUMPSTAT(swde_panic_basecasedata);
337 336 fmd_case_close(hdl, cp);
338 337 }
339 338 } else {
340 339 remain++;
341 340 }
342 341
343 342
344 343 cp = swde_case_next(hdl, cp);
345 344 }
346 345
347 346 if (remain) {
348 347 mytimerid = sw_timer_install(hdl, myid, NULL, NULL,
349 348 10ULL * NANOSEC * 60);
350 349 }
351 350 }
352 351
353 352 /*
354 353 * Our verify entry point is called for each of our open cases during
355 354 * module load. We must return 0 for the case to be closed by our caller,
356 355 * or 1 to keep it (or if we have already closed it during this call).
357 356 */
358 357 static int
359 358 swde_panic_vrfy(fmd_hdl_t *hdl, fmd_case_t *cp)
360 359 {
361 360 swde_panic_casedata_t *cdp;
362 361 time_t now = time(NULL);
363 362 nvlist_t *attr;
364 363 uint32_t vers;
365 364
366 365 cdp = swde_case_data(hdl, cp, &vers);
367 366
368 367 if (vers != SWDE_PANIC_CASEDATA_VERS)
369 368 return (0); /* case will be closed */
370 369
371 370 if (now > cdp->scd_receive_time + 30 * 60) {
372 371 if (nvlist_unpack((char *)cdp + sizeof (*cdp),
373 372 cdp->scd_nvlbufsz, &attr, 0) == 0) {
374 373 swde_panic_solve(hdl, cp, attr, NULL, B_FALSE);
375 374 nvlist_free(attr);
376 375 return (1); /* case already closed */
377 376 } else {
378 377 return (0); /* close case */
379 378 }
380 379 }
381 380
382 381 if (mytimerid != 0)
383 382 mytimerid = sw_timer_install(hdl, myid,
384 383 NULL, NULL, 10ULL * NANOSEC * 60);
385 384
386 385 return (1); /* retain case */
387 386 }
388 387
389 388 /*
390 389 * Handler for ireport.os.sunos.panic.dump_pending_on_device.
391 390 *
392 391 * A future RFE should try adding a means of avoiding diagnosing repeated
393 392 * defects on panic loops, which would just add to the mayhem and potentially
394 393 * log lots of calls through ASR. Panics with similar enough panic
395 394 * strings and/or stacks should not diagnose to new defects with some
396 395 * period of time, for example.
397 396 */
398 397
399 398 /*ARGSUSED*/
400 399 void
401 400 swde_panic_detected(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
402 401 const char *class, void *arg)
403 402 {
404 403 boolean_t fm_panic, expect_savecore;
405 404 swde_panic_casedata_t *cdp;
406 405 nvlist_t *attr;
407 406 fmd_case_t *cp;
408 407 char *fmribuf;
409 408 char *uuid;
410 409 size_t sz;
411 410
412 411 fmd_hdl_debug(hdl, "swde_panic_detected\n");
413 412
414 413 if (nvlist_lookup_nvlist(nvl, FM_IREPORT_ATTRIBUTES, &attr) != 0) {
415 414 BUMPSTAT(swde_panic_noattr);
416 415 return;
417 416 }
418 417
419 418 if (nvlist_lookup_string(attr, "os-instance-uuid", &uuid) != 0) {
420 419 BUMPSTAT(swde_panic_nouuid);
421 420 return;
422 421 }
423 422
424 423 fmd_hdl_debug(hdl, "swde_panic_detected: OS instance %s\n", uuid);
425 424
426 425 if (nvlist_lookup_boolean_value(attr, "fm-panic", &fm_panic) != 0 ||
427 426 fm_panic == B_TRUE) {
428 427 BUMPSTAT(swde_panic_unexpected_fm_panic);
429 428 return;
430 429 }
431 430
432 431 /*
433 432 * Prepare serialization data to be associated with a new
434 433 * case. Our serialization data consists of a swde_panic_casedata_t
435 434 * structure followed by a packed nvlist of the attributes of
436 435 * the initial event.
437 436 */
438 437 if (nvlist_size(attr, &sz, NV_ENCODE_NATIVE) != 0) {
439 438 BUMPSTAT(swde_panic_failsrlz);
440 439 return;
441 440 }
442 441
443 442 cdp = fmd_hdl_zalloc(hdl, sizeof (*cdp) + sz, FMD_SLEEP);
444 443 fmribuf = (char *)cdp + sizeof (*cdp);
445 444 cdp->scd_vers = SWDE_PANIC_CASEDATA_VERS;
446 445 cdp->scd_receive_time = time(NULL);
447 446 cdp->scd_nvlbufsz = sz;
448 447
449 448 /*
450 449 * Open a case with UUID matching the the panicking kernel, add this
451 450 * event to the case.
452 451 */
453 452 if ((cp = swde_case_open(hdl, myid, uuid, SWDE_PANIC_CASEDATA_VERS,
454 453 cdp, sizeof (*cdp) + sz)) == NULL) {
455 454 BUMPSTAT(swde_panic_dupuuid);
456 455 fmd_hdl_debug(hdl, "swde_case_open returned NULL - dup?\n");
457 456 fmd_hdl_free(hdl, cdp, sizeof (*cdp) + sz);
458 457 return;
459 458 }
460 459
461 460 fmd_case_setprincipal(hdl, cp, ep);
462 461
463 462 if (nvlist_lookup_boolean_value(attr, "will-attempt-savecore",
464 463 &expect_savecore) != 0 || expect_savecore == B_FALSE) {
465 464 fmd_hdl_debug(hdl, "savecore not being attempted - "
466 465 "solve now\n");
467 466 swde_panic_solve(hdl, cp, attr, ep, B_FALSE);
468 467 return;
469 468 }
470 469
471 470 /*
472 471 * We expect to see either a "dump_available" or a "savecore_failed"
473 472 * event before too long. In case that never shows up, for whatever
474 473 * reason, we want to be able to solve the case anyway.
475 474 */
476 475 fmd_case_add_ereport(hdl, cp, ep);
477 476 (void) nvlist_pack(attr, &fmribuf, &sz, NV_ENCODE_NATIVE, 0);
478 477 swde_case_data_write(hdl, cp);
479 478
480 479 if (mytimerid == 0) {
481 480 mytimerid = sw_timer_install(hdl, myid, NULL, ep,
482 481 10ULL * NANOSEC * 60);
483 482 fmd_hdl_debug(hdl, "armed timer\n");
484 483 } else {
485 484 fmd_hdl_debug(hdl, "timer already armed\n");
486 485 }
487 486 }
488 487
489 488 /*
490 489 * savecore has now run and saved a crash dump to the filesystem. It is
491 490 * either a compressed dump (vmdump.n) or uncompressed {unix.n, vmcore.n}
492 491 * Savecore has raised an ireport to say the dump is there.
493 492 */
494 493
495 494 /*ARGSUSED*/
496 495 void
497 496 swde_panic_savecore_done(fmd_hdl_t *hdl, fmd_event_t *ep, nvlist_t *nvl,
498 497 const char *class, void *arg)
499 498 {
500 499 boolean_t savecore_success = (arg != NULL);
501 500 boolean_t fm_panic;
502 501 nvlist_t *attr;
503 502 fmd_case_t *cp;
504 503 char *uuid;
505 504
506 505 fmd_hdl_debug(hdl, "savecore_done (%s)\n", savecore_success ?
507 506 "success" : "fail");
508 507
509 508 if (nvlist_lookup_nvlist(nvl, FM_IREPORT_ATTRIBUTES, &attr) != 0) {
510 509 BUMPSTAT(swde_panic_noattr);
511 510 return;
512 511 }
513 512
514 513 if (nvlist_lookup_boolean_value(attr, "fm-panic", &fm_panic) != 0 ||
515 514 fm_panic == B_TRUE) {
516 515 return; /* not expected, but just in case */
517 516 }
518 517
519 518 if (nvlist_lookup_string(attr, "os-instance-uuid", &uuid) != 0) {
520 519 BUMPSTAT(swde_panic_nouuid);
521 520 return;
522 521 }
523 522
524 523 /*
525 524 * Find the case related to the panicking kernel; our cases have
526 525 * the same uuid as the crashed OS image.
527 526 */
528 527 cp = fmd_case_uulookup(hdl, uuid);
529 528 if (!cp) {
530 529 /* Unable to find the case. */
531 530 fmd_hdl_debug(hdl, "savecore_done: can't find case for "
532 531 "image %s\n", uuid);
533 532 BUMPSTAT(swde_panic_nocase);
534 533 return;
535 534 }
536 535
537 536 fmd_hdl_debug(hdl, "savecore_done: solving case %s\n", uuid);
538 537 swde_panic_solve(hdl, cp, attr, ep, savecore_success);
539 538 }
540 539
541 540 const struct sw_disp swde_panic_disp[] = {
542 541 { SW_SUNOS_PANIC_DETECTED, swde_panic_detected, NULL },
543 542 { SW_SUNOS_PANIC_AVAIL, swde_panic_savecore_done, (void *)1 },
544 543 { SW_SUNOS_PANIC_FAILURE, swde_panic_savecore_done, NULL },
545 544 /*
546 545 * Something has to subscribe to every fault
547 546 * or defect diagnosed in fmd. We do that here, but throw it away.
548 547 */
549 548 { SW_SUNOS_PANIC_DEFECT, NULL, NULL },
550 549 { NULL, NULL, NULL }
551 550 };
552 551
553 552 /*ARGSUSED*/
554 553 int
555 554 swde_panic_init(fmd_hdl_t *hdl, id_t id, const struct sw_disp **dpp,
556 555 int *nelemp)
557 556 {
558 557 myid = id;
559 558
560 559 if (getzoneid() != GLOBAL_ZONEID)
561 560 return (SW_SUB_INIT_FAIL_VOLUNTARY);
562 561
563 562 (void) fmd_stat_create(hdl, FMD_STAT_NOALLOC,
564 563 sizeof (swde_panic_stats) / sizeof (fmd_stat_t),
565 564 (fmd_stat_t *)&swde_panic_stats);
566 565
567 566 fmd_hdl_subscribe(hdl, SW_SUNOS_PANIC_DETECTED);
568 567 fmd_hdl_subscribe(hdl, SW_SUNOS_PANIC_FAILURE);
569 568 fmd_hdl_subscribe(hdl, SW_SUNOS_PANIC_AVAIL);
570 569
571 570 *dpp = &swde_panic_disp[0];
572 571 *nelemp = sizeof (swde_panic_disp) / sizeof (swde_panic_disp[0]);
573 572 return (SW_SUB_INIT_SUCCESS);
574 573 }
575 574
576 575 void
577 576 swde_panic_fini(fmd_hdl_t *hdl)
578 577 {
579 578 if (mytimerid)
580 579 sw_timer_remove(hdl, myid, mytimerid);
581 580 }
582 581
583 582 const struct sw_subinfo panic_diag_info = {
584 583 "panic diagnosis", /* swsub_name */
585 584 SW_CASE_PANIC, /* swsub_casetype */
586 585 swde_panic_init, /* swsub_init */
587 586 swde_panic_fini, /* swsub_fini */
588 587 swde_panic_timeout, /* swsub_timeout */
589 588 NULL, /* swsub_case_close */
590 589 swde_panic_vrfy, /* swsub_case_vrfy */
591 590 };
↓ open down ↓ |
395 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX