fmd_dr.c revision 07312882d9573a94daa8260c0744011540574003
27c478bdstevel@tonic-gate * CDDL HEADER START
37c478bdstevel@tonic-gate *
47c478bdstevel@tonic-gate * The contents of this file are subject to the terms of the
5724365fsethg * Common Development and Distribution License (the "License").
6724365fsethg * You may not use this file except in compliance with the License.
77c478bdstevel@tonic-gate *
87c478bdstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bdstevel@tonic-gate * or
107c478bdstevel@tonic-gate * See the License for the specific language governing permissions
117c478bdstevel@tonic-gate * and limitations under the License.
127c478bdstevel@tonic-gate *
137c478bdstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bdstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bdstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bdstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bdstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bdstevel@tonic-gate *
197c478bdstevel@tonic-gate * CDDL HEADER END
207c478bdstevel@tonic-gate */
22e5dcf7bRobert Johnston * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bdstevel@tonic-gate * Use is subject to license terms.
247c478bdstevel@tonic-gate */
277c478bdstevel@tonic-gate * FMD Dynamic Reconfiguration (DR) Event Handling
287c478bdstevel@tonic-gate *
297c478bdstevel@tonic-gate * Fault manager scheme plug-ins must track characteristics of individual
307c478bdstevel@tonic-gate * pieces of hardware.  As these components can be added or removed by a DR
317c478bdstevel@tonic-gate * operation, we need to provide a means by which plug-ins can determine when
327c478bdstevel@tonic-gate * they need to re-examine the current configuration.  We provide a simple
337c478bdstevel@tonic-gate * mechanism whereby this task can be implemented using lazy evaluation: a
347c478bdstevel@tonic-gate * simple 64-bit generation counter is maintained and incremented on *any* DR.
357c478bdstevel@tonic-gate * Schemes can store the generation number in scheme-specific data structures,
367c478bdstevel@tonic-gate * and then revalidate their contents if the current generation number has
377c478bdstevel@tonic-gate * changed since the resource information was cached.  This method saves time,
387c478bdstevel@tonic-gate * avoids the complexity of direct participation in DR, avoids the need for
397c478bdstevel@tonic-gate * resource-specific processing of DR events, and is relatively easy to port
407c478bdstevel@tonic-gate * to other systems that support dynamic reconfiguration.
4124db464eschrock *
4224db464eschrock * The dr generation is only incremented in response to hardware changes.  Since
4324db464eschrock * ASRUs can be in any scheme, including the device scheme, we must also be
4424db464eschrock * aware of software configuration changes which may affect the resource cache.
4524db464eschrock * In addition, we take a snapshot of the topology whenever a reconfiguration
4624db464eschrock * event occurs and notify any modules of the change.
477c478bdstevel@tonic-gate */
497c478bdstevel@tonic-gate#include <sys/types.h>
5024db464eschrock#include <sys/sunddi.h>
517c478bdstevel@tonic-gate#include <sys/sysevent/dr.h>
527c478bdstevel@tonic-gate#include <sys/sysevent/eventdefs.h>
547c478bdstevel@tonic-gate#include <stdio.h>
5524db464eschrock#include <string.h>
56d9638e5mws#include <unistd.h>
577c478bdstevel@tonic-gate#include <libsysevent.h>
597c478bdstevel@tonic-gate#undef MUTEX_HELD
607c478bdstevel@tonic-gate#undef RW_READ_HELD
617c478bdstevel@tonic-gate#undef RW_WRITE_HELD
63724365fsethg#include <fmd_asru.h>
647c478bdstevel@tonic-gate#include <fmd_error.h>
6524db464eschrock#include <fmd_event.h>
66724365fsethg#include <fmd_fmri.h>
6724db464eschrock#include <fmd_module.h>
687c478bdstevel@tonic-gate#include <fmd_subr.h>
6924db464eschrock#include <fmd_topo.h>
707c478bdstevel@tonic-gate#include <fmd.h>
7324db464eschrockfmd_dr_event(sysevent_t *sep)
7524db464eschrock	uint64_t gen;
7624db464eschrock	fmd_event_t *e;
7724db464eschrock	const char *class = sysevent_get_class_name(sep);
789af3851eschrock	const char *subclass = sysevent_get_subclass_name(sep);
7924db464eschrock	hrtime_t evtime;
8024db464eschrock	fmd_topo_t *ftp, *prev;
8124db464eschrock	boolean_t update_topo = B_FALSE;
8324db464eschrock	if (strcmp(class, EC_DR) == 0) {
849af3851eschrock		if (strcmp(subclass, ESC_DR_AP_STATE_CHANGE) != 0 &&
859af3851eschrock		    strcmp(subclass, ESC_DR_TARGET_STATE_CHANGE) != 0)
869af3851eschrock			return;
889af3851eschrock		/*
899af3851eschrock		 * The DR generation is only changed in response to DR events.
909af3851eschrock		 */
9124db464eschrock		update_topo = B_TRUE;
9324db464eschrock		(void) pthread_mutex_lock(&fmd.d_stats_lock);
9424db464eschrock		gen = fmd.d_stats->ds_dr_gen.fmds_value.ui64++;
9524db464eschrock		(void) pthread_mutex_unlock(&fmd.d_stats_lock);
9724db464eschrock		TRACE((FMD_DBG_XPRT, "dr event %p, gen=%llu",
9824db464eschrock		    (void *)sep, gen));
999af3851eschrock	} else if (strcmp(class, EC_DEVFS) == 0) {
1009af3851eschrock		/*
1019af3851eschrock		 * A devfs configuration event can change the topology,
1029af3851eschrock		 * as disk nodes only exist when the device is configured.
1039af3851eschrock		 */
1049af3851eschrock		update_topo = B_TRUE;
105e5dcf7bRobert Johnston	} else if (strcmp(class, EC_PLATFORM) == 0) {
106e5dcf7bRobert Johnston		if (strcmp(subclass, ESC_PLATFORM_SP_RESET) == 0) {
107e5dcf7bRobert Johnston			/*
108e5dcf7bRobert Johnston			 * Since we rely on the SP to enumerate fans,
109e5dcf7bRobert Johnston			 * power-supplies and sensors/leds, it would be prudent
110e5dcf7bRobert Johnston			 * to take a new snapshot if the SP resets.
111e5dcf7bRobert Johnston			 */
112e5dcf7bRobert Johnston			update_topo = B_TRUE;
113e5dcf7bRobert Johnston		}
1149af3851eschrock	} else if (strcmp(class, EC_ZFS) == 0) {
1159af3851eschrock		/*
1169af3851eschrock		 * These events can change the resource cache.
1179af3851eschrock		 */
1189af3851eschrock		if (strcmp(subclass, ESC_ZFS_VDEV_CLEAR) != 0 &&
1199af3851eschrock		    strcmp(subclass, ESC_ZFS_VDEV_REMOVE) != 0 &&
1209af3851eschrock		    strcmp(subclass, ESC_ZFS_POOL_DESTROY) != 0)
1219af3851eschrock			return;
1229af3851eschrock	} else if (strcmp(class, EC_DEV_ADD) == 0 ||
1239af3851eschrock	    strcmp(class, EC_DEV_REMOVE) == 0) {
1249af3851eschrock		if (strcmp(subclass, ESC_DISK) != 0)
1259af3851eschrock			return;
1260731288Eric Schrock
1270731288Eric Schrock		update_topo = B_TRUE;
12824db464eschrock	}
130724365fsethg	/*
13124db464eschrock	 * Take a topo snapshot and notify modules of the change.  Picking an
13224db464eschrock	 * accurate time here is difficult.  On one hand, we have the timestamp
13324db464eschrock	 * of the underlying sysevent, indicating when the reconfiguration event
13424db464eschrock	 * occurred.  On the other hand, we are taking the topo snapshot
13524db464eschrock	 * asynchronously, and hence the timestamp of the snapshot is the
13624db464eschrock	 * current time.  Pretending this topo snapshot was valid at the time
13724db464eschrock	 * the sysevent was posted seems wrong, so we instead opt for the
13824db464eschrock	 * current time as an upper bound on the snapshot validity.
13924db464eschrock	 *
14024db464eschrock	 * Along these lines, we keep track of the last time we dispatched a
14124db464eschrock	 * topo snapshot.  If the sysevent occurred before the last topo
14224db464eschrock	 * snapshot, then don't bother dispatching another topo change event.
14324db464eschrock	 * We've already indicated (to the best of our ability) the change in
14424db464eschrock	 * topology.  This prevents endless topo snapshots in response to a
14524db464eschrock	 * flurry of sysevents.
146724365fsethg	 */
14724db464eschrock	sysevent_get_time(sep, &evtime);
14824db464eschrock	prev = fmd_topo_hold();
1490731288Eric Schrock	if (evtime <= prev->ft_time_begin &&
15024db464eschrock	    fmd.d_clockops == &fmd_timeops_native) {
15124db464eschrock		fmd_topo_rele(prev);
15224db464eschrock		return;
15324db464eschrock	}
15424db464eschrock	fmd_topo_rele(prev);
15624db464eschrock	if (update_topo)
15724db464eschrock		fmd_topo_update();
15924db464eschrock	ftp = fmd_topo_hold();
1600731288Eric Schrock	e = fmd_event_create(FMD_EVT_TOPO, ftp->ft_time_end, NULL, ftp);
16124db464eschrock	fmd_modhash_dispatch(fmd.d_mod_hash, e);