fmd.c revision 7ee93e3bbce920c0d0742deb6632b0939e30b783
/*
* 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 <sys/systeminfo.h>
#include <limits.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <stdio.h>
#include <fmd_conf.h>
#include <fmd_dispq.h>
#include <fmd_timerq.h>
#include <fmd_subr.h>
#include <fmd_error.h>
#include <fmd_module.h>
#include <fmd_thread.h>
#include <fmd_alloc.h>
#include <fmd_string.h>
#include <fmd_transport.h>
#include <fmd_builtin.h>
#include <fmd_ustat.h>
#include <fmd_protocol.h>
#include <fmd_scheme.h>
#include <fmd_asru.h>
#include <fmd_case.h>
#include <fmd_log.h>
#include <fmd_rpc.h>
#include <fmd_dr.h>
#include <fmd.h>
/*
* Note: the configuration file path is ordered from most common to most host-
* module paths are in the opposite order, from most specific to most common,
* because once a module is loaded fmd will not try to load over the same name.
*/
static const char _fmd_conf_path[] =
static const char _fmd_agent_path[] =
static const char _fmd_plugin_path[] =
static const char _fmd_scheme_path[] =
static const fmd_conf_mode_t _fmd_cerror_modes[] = {
};
static const fmd_conf_mode_t _fmd_dbout_modes[] = {
};
static const fmd_conf_mode_t _fmd_debug_modes[] = {
};
static int
{
}
static int
{
}
static int
{
if (err == 0)
return (err);
}
static int
{
else
return (fmd_set_errno(EFMD_CONF_INVAL));
return (0);
}
static void
{
}
static int
{
const fmd_timeops_t *ops;
else
return (fmd_set_errno(EFMD_CONF_INVAL));
return (0);
}
static void
{
}
static const fmd_conf_ops_t fmd_cerror_ops = {
};
static const fmd_conf_ops_t fmd_dbout_ops = {
};
static const fmd_conf_ops_t fmd_debug_ops = {
};
static const fmd_conf_ops_t fmd_trmode_ops = {
};
static const fmd_conf_ops_t fmd_clkmode_ops = {
};
static const fmd_conf_formal_t _fmd_conf[] = {
#ifdef DEBUG
#else
#endif
};
/*
* Statistics maintained by fmd itself on behalf of various global subsystems.
* NOTE: FMD_TYPE_STRING statistics should not be used here. If they are
* required in the future, the FMD_ADM_MODGSTAT service routine must change.
*/
static fmd_statistics_t _fmd_stats = {
};
void
{
const char *name;
fmd_stat_t *sp;
int i;
/*
* A small number of properties must be set manually before we open
* the root configuration file. These include any settings for our
* memory allocator and path expansion token values, because these
* values are needed by the routines in fmd_conf.c itself. After
* the root configuration file is processed, we reset these properties
* based upon the latest values from the configuration file.
*/
"failed to load required configuration properties\n");
}
/*
* Manually specified rootdirs override config files, so only update
* d_rootdir based on the config files we parsed if no 'root' was set.
*/
else
/*
* Once the base conf file properties are loaded, lookup the values
* of $conf_path and $conf_file and merge in any other conf files.
*/
}
/*
* Update the value of fmd.d_fg based on "fg". We cache this property
* because it must be accessed deep within fmd at fmd_verror() time.
*/
/*
* Initialize our custom libnvpair allocator and create an nvlist for
* authority elements corresponding to this instance of the daemon.
*/
/*
* The fmd_module_t for the root module must be created manually. Most
* of it remains unused and zero, except for the few things we fill in.
*/
/*
* In addition to inserting the _fmd_stats collection of program-wide
* statistics, we also insert a statistic named after each of our
* errors and update these counts in fmd_verror() (see fmd_subr.c).
*/
}
}
void
{
int core;
fmd_rpc_fini();
fmd_dr_fini();
/*
* Unload the self-diagnosis module first. This ensures that it does
* not get confused as we start unloading other modules, etc. We must
* hold the dispq lock as a writer while doing so since it uses d_self.
*/
}
/*
* Unload modules in reverse order *except* for the root module, which
* is first in the list. This allows it to keep its thread and trace.
*/
}
}
/*
* Close both log files now that modules are no longer active. We must
* set these pointers to NULL in case any subsequent errors occur.
*/
}
}
/*
* Now that all data structures that refer to modules are torn down,
* no modules should be remaining on the module list except for d_rmod.
* If we trip one of these assertions, we're missing a rele somewhere.
*/
/*
* Now destroy the root module. We clear its thread key first so any
* calls to fmd_trace() inside of the module code will be ignored.
*/
}
if (core)
fmd_panic("forcing core dump at user request\n");
}
/*ARGSUSED*/
static void
{
if (id != 0) {
}
}
/*
* Events are committed to the errlog after cases are checkpointed. If fmd
* crashes before an event is ever associated with a module, this function will
* be called to replay it to all subscribers. If fmd crashes in between the
* subscriber checkpointing and committing the event in the error log, the
* module will have seen the event and we don't want to replay it. So we look
* for the event in all modules and transition it to the proper state. If
* it is found, we commit it to the error log and do not replay it. The in-
* memory case search used by fmd_module_contains() et al isn't particularly
* efficient, but it is faster than doing read i/o's on every case event to
* check their status or write i/o's on every event to replay to update states.
* We can improve the efficiency of this lookup algorithm later if necessary.
*/
/*ARGSUSED*/
static void
{
fmd_stat_t *sp;
break;
}
}
} else {
}
}
/*
* This signal handler is installed for the client.thrsig signal to be used to
* force an auxiliary thread to wake up from a system call and return EINTR in
* response to a module's use of fmd_thr_signal(). We also trace the event.
*/
static void
fmd_signal(int sig)
{
}
void
{
char nodc_str[128];
int status = FMD_EXIT_SUCCESS;
const char *name;
int dbout;
/*
* Cache all the current debug property settings in d_fmd_debug,
* d_fmd_dbout, d_hdl_debug, and d_hdl_dbout. If a given debug mask
* is non-zero and the corresponding dbout mask is zero, set dbout
* to a sensible default value based on whether we have daemonized.
*/
else
else
/*
* Initialize remaining major program data structures such as the event
* transport, dispatch queues, log files, module hash collections, etc.
* This work is done here rather than in fmd_create() to permit the -o
* command-line option to modify properties after fmd_create() is done.
* Note that our event transport will remain blocked until we broadcast
* to threads blocked on d_xprt_cv at the end of this function.
*/
fmd_rpc_init();
fmd_dr_init();
/*
* Once our subsystems that use signals have been set up, install the
* signal handler for the fmd_thr_signal() API. Verify that the signal
* being used for this purpose doesn't conflict with something else.
*/
}
}
/*
* Now that we're running, if a pipe fd was specified, write an exit
* status to it to indicate that our parent process can safely detach.
*/
if (pfd >= 0)
/*
* Once all data structures are initialized, we load all of our modules
* in order according to class in order to load up any subscriptions.
*/
/*
* Before activating the inbound event transport, we first replay any
* fault events from the ASRU cache, any case events from the case hash
* associated with restored case checkpoints, and any error events from
* the errlog that did not finish processing the last time we ran. Then
* we replay any pending events from the event transport itself.
*/
/*
* Finally, awaken any threads associated with receiving events from
* our main ereport event transport that are sleeping on d_xprt_wait.
*/
dp->d_xprt_wait--;
}
void
{
const fmd_conf_mode_t *cmp;
}