fmd_case.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (the "License"). You may not use this file except in compliance
* with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <alloca.h>
#include <fmd_alloc.h>
#include <fmd_module.h>
#include <fmd_error.h>
#include <fmd_conf.h>
#include <fmd_case.h>
#include <fmd_string.h>
#include <fmd_subr.h>
#include <fmd_protocol.h>
#include <fmd_event.h>
#include <fmd_eventq.h>
#include <fmd_dispq.h>
#include <fmd_buf.h>
#include <fmd_log.h>
#include <fmd_asru.h>
#include <fmd.h>
static const char *const _fmd_case_snames[] = {
"UNSOLVED", /* FMD_CASE_UNSOLVED */
"SOLVED", /* FMD_CASE_SOLVED */
"CLOSED", /* FMD_CASE_CLOSED */
};
fmd_case_hash_create(void)
{
return (chp);
}
/*
* Destroy the case hash. Unlike most of our hash tables, no active references
* are kept by the case hash because cases are destroyed when modules unload.
* The hash must be destroyed after all modules are unloaded; if anything was
* present in the hash it would be by definition a reference count leak.
*/
void
{
}
static nvlist_t *
{
const char *s;
boolean_t b;
/*
* For each suspect associated with the case, store its fault event
* nvlist in 'nva' and its fault class in 'keys'. We also look to see
* if any of the suspect faults have asked not to be messaged. If any
* of them have made such a request, propagate that to the suspect list.
*/
keyp++;
FM_SUSPECT_MESSAGE, &b) == 0 && b == B_FALSE)
}
/*
* Look up the diagcode corresponding to this suspect list. If
* no suspects were defined for this case or if the lookup
* fails, the dictionary or module code is busted or not set up
* properly. Emit the event with our precomputed default code.
*/
}
}
/*
* Publish appropriate events based on the specified case state. For a case
* that is FMD_CASE_SOLVED, we send ci_event. For a case that is
* FMD_CASE_CLOSED, we send a case-closed event to the owner module.
*/
static void
{
fmd_event_t *e;
char *class;
switch (state) {
case FMD_CASE_SOLVED:
/*
* If ci_event is NULL, the event was not created because the
* case was restored from a checkpoint before _fmd_init() was
* called. Now that the module is ready, create the event.
*/
break;
case FMD_CASE_CLOSED:
break;
}
}
/*
* Refresh all of the cases by publishing events for each case if appropriate.
* We do this once during startup to trigger case close and list.suspect events
* for cases restored by checkpoints. By holding the read lock on the case
* hash, we ensure that we only refresh the current set of cases. New cases
* created in response to the events will block in fmd_case_hash_insert().
*/
void
{
uint_t i;
for (i = 0; i < chp->ch_hashlen; i++) {
}
}
{
uint_t h;
break;
}
else
(void) fmd_set_errno(EFMD_CASE_INVAL);
return ((fmd_case_t *)cip);
}
static fmd_case_impl_t *
{
uint_t h;
return (NULL); /* uuid already present */
}
}
return (cip);
}
static void
{
uint_t h;
else
break;
}
fmd_panic("case %p (%s) not found on hash chain %u\n",
}
}
{
/*
* Calling libuuid: get a clue. The library interfaces cleverly do not
* define any constant for the length of an unparse string, and do not
* permit the caller to specify a buffer length for safety. The spec
* says it will be 36 bytes, but we make it tunable just in case.
*/
/*
* We expect this loop to execute only once, but code it defensively
* against the possibility of libuuid bugs. Keep generating uuids and
* attempting to do a hash insert until we get a unique one.
*/
do {
return ((fmd_case_t *)cip);
}
{
return (NULL);
}
return ((fmd_case_t *)cip);
}
void
{
}
}
/*
* Unlike other case functions, fmd_case_destroy() can be called from
* fmd_module_unload() after the module is unregistered and mod_stats
* has been destroyed. As such we must check for NULL mod_stats here.
*/
}
void
{
}
void
{
else
}
void
{
else
}
void
{
else
}
void
{
cip->ci_nsuspects++;
}
void
{
}
cip->ci_nsuspects = 0;
}
void
{
/*
* Grab ci_lock and update the case state and set the dirty bit. If we
* are solving the case, create a list.suspects event as cip->ci_event
* and iterate over all the case events and mark them as DIAGNOSED.
*/
return; /* already in specified state */
}
switch (state) {
case FMD_CASE_SOLVED: {
/*
* If the module has been initialized, then fill in ci_event.
* If not, we are being called from the checkpoint code, in
* in which case fmd_case_hash_refresh() will create and
* publish the event later once the module has initialized.
*/
}
break;
}
case FMD_CASE_CLOSED: {
break; /* don't change ASRUs if repair closed case */
/*
* For each fault event in the suspect list, attempt to look up
* the corresponding ASRU in the ASRU dictionary. If the ASRU
* is found there and is marked faulty, we now mark it unusable
* and record the case meta-data and fault event with the ASRU.
*/
(void) fmd_asru_setflags(asru,
}
}
break;
}
}
/*
* If the module has been initialized, then publish the appropriate
* event for the new case state. If not, we are being called from
* the checkpoint code, in which case fmd_case_hash_refresh() will
* publish the event later once all the modules have initialized.
*/
}
void
{
}
void
{
}
void
{
}
}
/*
* Indicate that the case may need to change state because one or more of the
* ASRUs named as a suspect has changed state. We examine all the suspects
* and if none are still faulty, we initiate a case close transition.
*/
void
{
int state = 0;
return; /* update is not yet appropriate */
}
}
}
if (!(state & FMD_ASRU_FAULTY))
if (!(state & FMD_ASRU_FAULTY))
}
/*
* Indicate that the problem corresponding to a case has been repaired by
* clearing the faulty bit on each ASRU named as a suspect. If the case has
* not already been closed, this function initiates the case close transition.
*/
int
{
return (fmd_set_errno(EFMD_CASE_STATE));
}
(void) fmd_asru_clrflags(asru,
}
}
return (0);
}
int
{
int rv = 0;
else
break;
}
if (rv != 0)
return (rv);
}