fmd_asru.c revision d9638e547d8811f2c689977f8dd2a353938b61fd
/*
* 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 2005 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <dirent.h>
#include <limits.h>
#include <unistd.h>
#include <alloca.h>
#include <fmd_alloc.h>
#include <fmd_string.h>
#include <fmd_error.h>
#include <fmd_subr.h>
#include <fmd_protocol.h>
#include <fmd_event.h>
#include <fmd_conf.h>
#include <fmd_fmri.h>
#include <fmd_dispq.h>
#include <fmd_case.h>
#include <fmd_module.h>
#include <fmd_asru.h>
#include <fmd.h>
static const char *const _fmd_asru_events[] = {
};
static const char *const _fmd_asru_snames[] = {
"uf", "uF", "Uf", "UF" /* same order as above */
};
static fmd_asru_t *
{
char *s;
ap->asru_flags = 0;
strcmp(s, FM_FMRI_SCHEME_FMD) == 0)
return (ap);
}
static void
{
}
static void
{
}
static fmd_asru_t *
{
return (ap);
}
/*
* Lookup an asru in the hash by name and place a hold on it. If the asru is
* not found, no entry is created and NULL is returned. This internal function
* is for callers who have the ah_lock held and is used by lookup_name below.
*/
{
fmd_asru_t *ap;
uint_t h;
break;
}
(void) fmd_asru_hold(ap);
else
(void) fmd_set_errno(EFMD_ASRU_NOENT);
return (ap);
}
static void
{
fmd_event_t *e;
char *class;
boolean_t f, u, m;
fmd_asru_t *ap;
/*
* Extract the resource FMRI and most recent values of 'faulty' and
* 'unusable' from the event log. If the event is malformed, return.
*/
return;
}
/*
* Check to see if the resource is still present in the system. If
* so, then update the value of the unusable bit based on the current
* system configuration. If not, then either keep the entry in our
* cache if it is recent, or return and discard it if it is too old.
*/
return;
}
if (ps) {
u = FMD_B_FALSE;
} else
u = us != 0;
u = FMD_B_TRUE; /* not present; set unusable */
} else
return; /* too old; discard this log */
/*
* In order to insert the ASRU into our hash, convert the FMRI from
* nvlist form into a string form and assign this name to the ASRU.
*/
return;
}
/*
* Look to see if the ASRU already exists in the hash: if it does and
* the existing ASRU entry is unusable but the duplicate is not, then
* delete the existing entry and continue on using the new entry; if
* the new entry is no "better", return an error and ignore it.
*/
} else {
return;
}
}
if (f)
if (u)
FM_SUSPECT_MESSAGE, &m) == 0 && m == B_FALSE)
/*
* If the ASRU is present and the Faulty bit is set and a case event is
* saved in the log, attempt to recreate the case in the CLOSED state.
* If the case is already present, fmd_case_recreate() will return it.
* If not, we'll create a new orphaned case, in which case we use the
* ASRU event to insert a suspect into the partially-restored case.
*/
}
}
/*
* If the resource is present and faulty but not unusable, replay the
* fault event that caused it be marked faulty. This will cause the
* agent subscribing to this fault class to again disable the resource.
*/
}
}
static void
{
if (err != 0)
else
}
/*
* Open a saved log file and restore it into the ASRU hash. If we can't even
* open the log, rename the log file to <uuid>- to indicate it is corrupt. If
* fmd_log_replay() fails, we either delete the file (if it has reached the
* upper limit on cache age) or rename it for debugging if it was corrupted.
*/
static void
{
uint_t n;
return;
}
}
void
{
int zero;
return;
}
continue; /* skip "." and ".." */
if (zero)
}
}
{
return (ahp);
}
void
{
uint_t i;
for (i = 0; i < ahp->ah_hashlen; i++) {
}
}
}
/*
* Take a snapshot of the ASRU database by placing an additional hold on each
* member in an auxiliary array, and then call 'func' for each ASRU.
*/
void
{
for (i = 0; i < ahp->ah_hashlen; i++) {
}
for (i = 0; i < apc; i++) {
}
}
/*
* Lookup an asru in the hash by name and place a hold on it. If the asru is
* not found, no entry is created and NULL is returned.
*/
{
fmd_asru_t *ap;
return (ap);
}
/*
* Lookup an asru in the hash and place a hold on it. If 'create' is true, an
* absent entry will be created for the caller; otherwise NULL is returned.
*/
{
fmd_asru_t *ap;
uint_t h;
/*
* In order to lookup the ASRU in our hash, convert the FMRI from
* nvlist form into a string form using the scheme module.
*/
return (NULL);
}
/*
* If we must create the asru, grab the rwlock as a writer; otherwise
* reader is sufficient. Then search the hash for the given asru name.
* If we didn't find the asru in the hash and we need to create it,
* create and insert the asru with ahp->ah_lock held and hash it in.
* We'll then drop the rwlock and proceed to initializing the asru.
*/
if (create)
else
break;
}
} else
/*
* If 'create' is still true, then we need to initialize the asru log;
* If 'create' is false and an asru was found, we must cond_wait for
* the FMD_ASRU_VALID bit to be set before returning. In both cases,
* we increment asru_refs for the caller.
*/
if (create == FMD_B_TRUE) {
/*
* Generate a UUID for the ASRU. libuuid cleverly gives us no
* interface for specifying or learning the buffer size. Sigh.
* The spec says 36 bytes but we use a tunable just to be safe.
*/
}
return (ap);
}
/*
* Release the reference count on an asru obtained using fmd_asru_hash_lookup.
* We take 'ahp' for symmetry and in case we need to use it in future work.
*/
/*ARGSUSED*/
void
{
else
}
int
{
uint_t h;
break;
else
}
}
return (fmd_set_errno(EFMD_ASRU_NOENT));
/*
* If we found a matching ASRU, unlink its log file and then release
* the hash entry. Note that it may still be referenced if another
* thread is manipulating it; this is ok because once we unlink, the
* log file will not be restored, and the log data will be freed when
* all of the referencing threads release their respective references.
*/
return (0);
}
static void
{
fmd_event_t *e;
char *class;
return; /* can't log events if we can't open the log */
fmd_event_hold(e);
fmd_event_rele(e);
/*
* For now, we close the log file after every update to conserve file
* descriptors and daemon overhead. If this becomes a performance
* issue this code can change to keep a fixed-size LRU cache of logs.
*/
}
int
{
return (0);
}
}
return (1);
}
int
{
return (0);
}
}
}
}
return (1);
}
/*
* Report the current known state of the ASRU by refreshing its unusable status
* based upon the routines provided by the scheme module. If the unusable bit
* is different, we do *not* generate a state change here because that change
* may be unrelated to fmd activities and therefore we have no case or event.
* The absence of the transition is harmless as this function is only provided
* for RPC observability and fmd's clients are only concerned with ASRU_FAULTY.
*/
int
{
return (0); /* do not report non-fmd non-present resources */
if (us > 0)
st |= FMD_ASRU_UNUSABLE;
else if (us == 0)
st &= ~FMD_ASRU_UNUSABLE;
return (st);
}