schg_mgr.c revision 184cd04c26b064536977dfbb913a1240eaf6f708
/*
* 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 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
#include <string.h>
#include <inttypes.h>
#include <atomic.h>
#include "disk_monitor.h"
#include "schg_mgr.h"
#include "hotplug_mgr.h"
#include "topo_gather.h"
#include "dm_platform.h"
/* State-change event processing thread data */
static pthread_t g_schg_tid;
/*
* Each disk state change is described by an instance of the following
* structure (which includes the disk object and the new state)
*/
typedef struct disk_statechg {
static disk_statechg_t *
{
/*
* The states are additive -- we don't need to preserve
* the current faulted state in the newstate:
*/
return (dscp);
}
static void
free_statechange(void *dscp)
{
}
static void
{
}
static const char *
{
break;
}
}
return (str);
}
void
{
const char *astring;
/*
* No need to execute redundant indicator actions
*/
if (istate == INDICATOR_UNKNOWN ||
== 0);
return;
}
if (dm_platform_indicator_execute(astring) != 0) {
log_warn("[Disk in %s] Action `%s' did not complete "
"successfully.\n",
astring);
} else {
"successfully\n", astring);
}
}
}
static void
{
const char *astring;
/*
* Find the list of actions that correspond to this state change.
* If the old state is UNKNOWN, then we'll match to first action
* whose transition state is the new state.
*/
if ((oldstate == HPS_UNKNOWN ||
break;
}
/* Now we have a set of actions to perform: */
if (dm_platform_indicator_execute(astring) != 0) {
log_warn("[Disk in %s][State transition from "
"%s to %s] Action `%s' did not complete "
"successfully.\n",
astring);
} else
"Action `%s' executed successfully\n",
astring);
}
}
}
static void
{
return;
}
log_warn("Error updating FRU information for disk in %s.\n",
}
}
static void
{
if (diskp->initial_configuration ||
else
log_warn("frup unexpectedly went away: not updating "
} else {
log_warn_e("Error retrieving FRU information "
}
}
void
{
}
void
{
}
static void
{
/*
* Grab the current state of the attachment point to initialize the
* initial disk state. Create a disk state change with this new
* state so it will be processed in the loop below. If we can't get
* the initial state for some reason, then we'll just end up doing it
* later when we get a state change from the hotplug monitor or the
* fault monitor.
*/
if (firststate != HPS_UNKNOWN)
/*
* The fault indicators will be updated when faults are replayed
* based on the state of the disk as faulty in the fmd resource cache.
* A FAULTED state change will come from the _recv function when the
* fault component event is replayed.
*/
}
static void
{
const char *pth;
/*
* Perform startup activities to initialize the state of the
* indicators for each disk.
*/
}
if (g_schgt_state != TS_EXIT_REQUESTED) {
}
while (g_schgt_state != TS_EXIT_REQUESTED) {
== NULL) {
continue;
}
/*
* If the new state is the faulted state, add that state to
* the disk's current state.
*/
/*
* If the disk wasn't previously in the faulted state,
* execute the generic fault action. Even if we're
* in the faulted state, accept additional faults.
*/
/*
* If the new state is ABSENT, forget any faults
*/
} else
/*
* When a new disk is inserted and reaches the CONFIGURED state,
* the following actions must be done in the following order:
*
* (1) Execute the configuration-specified action on the
* state change.
* (2) Retreive the FRU information from the disk and execute
* the FRU-update action specified,
* (3) Initialize the fault monitor state associated with
* the new drive.
*
* Once the disk is no longer "new" (a disk is "new" when it
* has not yet reached the CONFIGURED state), subsequent
* transitions away and back to CONFIGURED (as long as the
* disk is not physically removed) will result in the
* execution of the predefined action ONLY.
*
*/
}
if (!diskp->configured_yet &&
/*
* If this state transition is lagging the true
* state of the system (e.g. if the true state of
* the disk is UNCONFIGURED, there's another
* state change somewhere later in the queue), then
* it's possible for the disk path property to not
* exist.
*/
DISK_PROP_DEVPATH) == NULL) {
"Processed stale state change "
} else {
}
}
/*
* Make the new state visible to all observers
*/
/*
* Now, update the diskmon if the disk is now absent -- it's
* essential to do this after the state is set (above) so that
* state observers in other threads don't try to access the
* data structures that we're freeing here.
*/
if (diskp->configured_yet &&
/*
* When the disk is removed, the fault monitor state is
* useless, so discard it.
*/
}
"[State change #%d][%s]: Disk path = %s\n",
"[State change #%d][%s]: New state = %s%s\n",
/* The caller is responsible for freeing the state change: */
}
}
static void
{
/* Enqueue a new state change for the state-change thread */
}
void
{
}
int
{
/* new_queue() is guaranteed to succeed */
/*
* Now, wait for the thread to enter the TS_RUNNING state. This
* is important because we want the state-change thread to pull the
* initial state of the disks on startup (without the wait, we could
* have the hotplug event handler race and deliver a state change
* before the state-change thread initialized the initial disk state).
*/
while (g_schgt_state != TS_RUNNING) {
(void) pthread_cond_wait(&g_schgt_state_cvar,
}
return (0);
}
/*ARGSUSED*/
void
{
if (g_schgt_state != TS_RUNNING)
return;
while (g_schgt_state != TS_EXITED)
&g_schgt_state_mutex) == 0);
}