sfx4500-disk.c revision 724365f7556fc4201fdb11766ebc6bd918523130
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (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 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Sun Fire X4500 Disk Diagnosis Engine
*/
#include <fcntl.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <stdarg.h>
#include <errno.h>
#include <signal.h>
#include <unistd.h>
#include <pthread.h>
#include <assert.h>
#include <libnvpair.h>
#include <fm/fmd_fmri.h>
#include "sfx4500-disk.h"
#include "fault_mgr.h"
#include "hotplug_mgr.h"
#include "schg_mgr.h"
#include "plugin_mgr.h"
#include "fm_disk_events.h"
#include "topo_gather.h"
#define THIS_FMD_MODULE_NAME "sfx4500-disk"
static enum sfx4500_init_state {
INIT_STATE_NONE = 0,
PLUGIN_MGR_INITTED = 1,
HOTPLUG_MGR_INITTED = 4,
typedef enum {
/*
* Global verbosity flag -- controls chattiness of debug messages and
* warnings. Its value is determined by the fmd property "log-level"
* settable in the DE's .conf file.
*/
log_class_t g_verbose = 0;
static const fmd_prop_t fmd_props[];
static void
diskmon_teardown_all(void)
{
/*
* Cleanup the fault manager first -- it depends
* on the state change manager and may race with
* its cleanup if left around.
*/
config_fini();
}
static int
{
int i = 0;
i++;
}
return (i);
}
static int
diskmon_init(void)
{
if (init_plugin_manager() != 0)
goto cleanup;
else
if (init_hotplug_manager() != 0)
goto cleanup;
else
if (init_state_change_manager(config_data) != 0)
goto cleanup;
else
if (init_fault_manager(config_data) != 0)
goto cleanup;
else
return (E_SUCCESS);
/*
* The cleanup order here does matter, due to dependencies between the
* managers.
*/
if (g_init_state & FAULT_MGR_INITTED)
if (g_init_state & HOTPLUG_MGR_INITTED)
if (g_init_state & PLUGIN_MGR_INITTED)
return (E_ERROR);
}
static boolean_t
{
char *modname;
return (B_FALSE);
else
return (B_TRUE);
}
static disk_flt_src_e
{
return (DISK_FAULT_SOURCE_OVERTEMP);
return (DISK_FAULT_SOURCE_SELFTEST);
return (DISK_FAULT_SOURCE_INFO_EXCPT);
return (DISK_FAULT_SOURCE_NONE);
}
static void
{
const char *action_prop = NULL;
const char *action_string;
/*
* The predictive failure action is the activation of the fault
* indicator.
*/
switch (fsrc) {
break;
break;
}
if (action_prop != NULL &&
!= NULL) {
if (rv != DMPE_SUCCESS) {
log_warn("Fault action `%s' did not successfully "
"complete.\n", action_string);
}
}
}
static void
{
int err = 0;
switch (list_type) {
case LT_REPAIRED:
if (err != 0)
return;
while (nvc-- != 0) {
&fmri) != 0)
continue;
continue;
}
break;
case LT_SUSPECT:
if (err != 0)
return;
&fmri) != 0)
continue;
continue;
/* Execute the actions associated with this fault */
/*
* If the fault wasn't generated by this module, send a
* state change event to the state change manager
*/
if (!dm_suspect_de_is_me(nvl))
/* Case is closed */
}
break;
}
}
/*ARGSUSED*/
static void
{
fmd_case_t *cs;
const char *fltclass;
/*
* Act on the fault suspect list or repaired list (embedded agent
* action).
*/
return;
return;
}
/*
* If we get any replayed faults, set the diskmon's faulted
* flag for the appropriate fault, then change the diskmon's state
* to faulted.
*/
&fmri) != 0)
return;
return;
/* Execute the actions associated with this fault */
/*
* If the fault wasn't generated by this module, send a
* state change event to the state change manager
*/
return;
}
if (!ismyereport) {
return;
}
return;
}
return;
fltclass =
/*
* Create and solve a new case by adding the ereport
* and its corresponding fault to the case and
* solving it. It'll be closed when we get the
* list.suspect event later.
*/
}
}
static const fmd_hdl_ops_t fmd_ops = {
diskmon_recv, /* fmdo_recv */
NULL, /* fmdo_timeout */
NULL, /* fmdo_close */
NULL, /* fmdo_stats */
NULL, /* fmdo_gc */
};
static const fmd_prop_t fmd_props[] = {
/*
* Default fault monitoring options are:
* (OPTION_SELFTEST_ERRS_ARE_FATAL |
* OPTION_OVERTEMP_ERRS_ARE_FATAL) == 0xC
*/
};
static const fmd_hdl_info_t fmd_info = {
"Sun Fire X4500 Disk Diagnosis Engine",
&fmd_ops,
};
void
{
fmd_case_t *cp;
int disk_count;
return;
}
if (config_init()) {
log_err("Could not initialize configuration!\n");
return;
}
config_fini();
log_err("Could not retrieve configuration from libtopo!\n");
return;
}
/*
* If there are no disks to monitor, bail out
*/
config_fini();
return;
}
if (diskmon_init() == E_ERROR) {
g_xprt_hdl = NULL;
config_fini();
return;
}
/*
* Iterate over all active cases.
* Since we automatically solve all cases, these cases must have
* had the fault added, but the DE must have been interrupted
* before they were solved.
*/
}
}
void
{
g_xprt_hdl = NULL;
}