1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * FMD Dynamic Reconfiguration (DR) Event Handling 30 * 31 * Fault manager scheme plug-ins must track characteristics of individual 32 * pieces of hardware. As these components can be added or removed by a DR 33 * operation, we need to provide a means by which plug-ins can determine when 34 * they need to re-examine the current configuration. We provide a simple 35 * mechanism whereby this task can be implemented using lazy evaluation: a 36 * simple 64-bit generation counter is maintained and incremented on *any* DR. 37 * Schemes can store the generation number in scheme-specific data structures, 38 * and then revalidate their contents if the current generation number has 39 * changed since the resource information was cached. This method saves time, 40 * avoids the complexity of direct participation in DR, avoids the need for 41 * resource-specific processing of DR events, and is relatively easy to port 42 * to other systems that support dynamic reconfiguration. 43 * 44 * The dr generation is only incremented in response to hardware changes. Since 45 * ASRUs can be in any scheme, including the device scheme, we must also be 46 * aware of software configuration changes which may affect the resource cache. 47 * In addition, we take a snapshot of the topology whenever a reconfiguration 48 * event occurs and notify any modules of the change. 49 */ 50 51 #include <sys/types.h> 52 #include <sys/sunddi.h> 53 #include <sys/sysevent/dr.h> 54 #include <sys/sysevent/eventdefs.h> 55 56 #include <stdio.h> 57 #include <string.h> 58 #include <unistd.h> 59 #include <libsysevent.h> 60 61 #undef MUTEX_HELD 62 #undef RW_READ_HELD 63 #undef RW_WRITE_HELD 64 65 #include <fmd_asru.h> 66 #include <fmd_error.h> 67 #include <fmd_event.h> 68 #include <fmd_fmri.h> 69 #include <fmd_module.h> 70 #include <fmd_subr.h> 71 #include <fmd_topo.h> 72 #include <fmd.h> 73 74 static void 75 fmd_dr_event(sysevent_t *sep) 76 { 77 uint64_t gen; 78 fmd_event_t *e; 79 const char *class = sysevent_get_class_name(sep); 80 hrtime_t evtime; 81 fmd_topo_t *ftp, *prev; 82 boolean_t update_topo = B_FALSE; 83 84 /* 85 * The dr generation is only changed in response to DR events. 86 */ 87 if (strcmp(class, EC_DR) == 0) { 88 update_topo = B_TRUE; 89 90 (void) pthread_mutex_lock(&fmd.d_stats_lock); 91 gen = fmd.d_stats->ds_dr_gen.fmds_value.ui64++; 92 (void) pthread_mutex_unlock(&fmd.d_stats_lock); 93 94 TRACE((FMD_DBG_XPRT, "dr event %p, gen=%llu", 95 (void *)sep, gen)); 96 } 97 98 /* 99 * Take a topo snapshot and notify modules of the change. Picking an 100 * accurate time here is difficult. On one hand, we have the timestamp 101 * of the underlying sysevent, indicating when the reconfiguration event 102 * occurred. On the other hand, we are taking the topo snapshot 103 * asynchronously, and hence the timestamp of the snapshot is the 104 * current time. Pretending this topo snapshot was valid at the time 105 * the sysevent was posted seems wrong, so we instead opt for the 106 * current time as an upper bound on the snapshot validity. 107 * 108 * Along these lines, we keep track of the last time we dispatched a 109 * topo snapshot. If the sysevent occurred before the last topo 110 * snapshot, then don't bother dispatching another topo change event. 111 * We've already indicated (to the best of our ability) the change in 112 * topology. This prevents endless topo snapshots in response to a 113 * flurry of sysevents. 114 */ 115 sysevent_get_time(sep, &evtime); 116 prev = fmd_topo_hold(); 117 if (evtime <= prev->ft_time && 118 fmd.d_clockops == &fmd_timeops_native) { 119 fmd_topo_rele(prev); 120 return; 121 } 122 fmd_topo_rele(prev); 123 124 if (update_topo) 125 fmd_topo_update(); 126 127 ftp = fmd_topo_hold(); 128 e = fmd_event_create(FMD_EVT_TOPO, ftp->ft_time, NULL, ftp); 129 fmd_modhash_dispatch(fmd.d_mod_hash, e); 130 } 131 132 void 133 fmd_dr_init(void) 134 { 135 const char *dr_subclasses[] = { 136 ESC_DR_AP_STATE_CHANGE 137 }; 138 const char *zfs_subclasses[] = { 139 ESC_ZFS_VDEV_CLEAR, 140 ESC_ZFS_VDEV_REMOVE, 141 ESC_ZFS_POOL_DESTROY 142 }; 143 const char *dev_subclasses[] = { 144 EC_SUB_ALL 145 }; 146 147 if (geteuid() != 0) 148 return; /* legacy sysevent mechanism is still root-only */ 149 150 if ((fmd.d_dr_hdl = sysevent_bind_handle(fmd_dr_event)) == NULL) 151 fmd_error(EFMD_EXIT, "failed to bind handle for DR sysevent"); 152 153 if (sysevent_subscribe_event(fmd.d_dr_hdl, EC_DR, 154 dr_subclasses, sizeof (dr_subclasses) / sizeof (char *)) == -1) 155 fmd_error(EFMD_EXIT, "failed to subscribe to DR sysevents"); 156 157 if (sysevent_subscribe_event(fmd.d_dr_hdl, EC_DEVFS, 158 dev_subclasses, sizeof (dev_subclasses) / sizeof (char *)) == -1) 159 fmd_error(EFMD_EXIT, "failed to subscribe to devfs sysevents"); 160 161 if (sysevent_subscribe_event(fmd.d_dr_hdl, EC_ZFS, 162 zfs_subclasses, sizeof (zfs_subclasses) / sizeof (char *)) == -1) 163 fmd_error(EFMD_EXIT, "failed to subscribe to ZFS sysevents"); 164 } 165 166 void 167 fmd_dr_fini(void) 168 { 169 if (fmd.d_dr_hdl != NULL) { 170 sysevent_unsubscribe_event(fmd.d_dr_hdl, EC_DR); 171 sysevent_unbind_handle(fmd.d_dr_hdl); 172 } 173 } 174