17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 59dd0f810Scindi * Common Development and Distribution License (the "License"). 69dd0f810Scindi * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 21d9638e54Smws 227c478bd9Sstevel@tonic-gate /* 23*97c04605Scy152378 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #include <sys/fm/protocol.h> 287c478bd9Sstevel@tonic-gate #include <limits.h> 297c478bd9Sstevel@tonic-gate 307c478bd9Sstevel@tonic-gate #include <fmd_alloc.h> 317c478bd9Sstevel@tonic-gate #include <fmd_subr.h> 327c478bd9Sstevel@tonic-gate #include <fmd_event.h> 337c478bd9Sstevel@tonic-gate #include <fmd_string.h> 34d9638e54Smws #include <fmd_module.h> 357c478bd9Sstevel@tonic-gate #include <fmd_case.h> 367c478bd9Sstevel@tonic-gate #include <fmd_log.h> 377c478bd9Sstevel@tonic-gate #include <fmd_time.h> 3824db4641Seschrock #include <fmd_topo.h> 397c478bd9Sstevel@tonic-gate #include <fmd_ctl.h> 407c478bd9Sstevel@tonic-gate 417c478bd9Sstevel@tonic-gate #include <fmd.h> 427c478bd9Sstevel@tonic-gate 43d9638e54Smws static void 44d9638e54Smws fmd_event_nvwrap(fmd_event_impl_t *ep) 45d9638e54Smws { 46d9638e54Smws (void) nvlist_remove_all(ep->ev_nvl, FMD_EVN_TTL); 47d9638e54Smws (void) nvlist_remove_all(ep->ev_nvl, FMD_EVN_TOD); 48d9638e54Smws 49d9638e54Smws (void) nvlist_add_uint8(ep->ev_nvl, 50d9638e54Smws FMD_EVN_TTL, ep->ev_ttl); 51d9638e54Smws (void) nvlist_add_uint64_array(ep->ev_nvl, 52d9638e54Smws FMD_EVN_TOD, (uint64_t *)&ep->ev_time, 2); 53d9638e54Smws } 54d9638e54Smws 55d9638e54Smws static void 56d9638e54Smws fmd_event_nvunwrap(fmd_event_impl_t *ep, const fmd_timeval_t *tp) 57d9638e54Smws { 58d9638e54Smws uint64_t *tod; 59d9638e54Smws uint_t n; 60d9638e54Smws 61d9638e54Smws if (nvlist_lookup_uint8(ep->ev_nvl, FMD_EVN_TTL, &ep->ev_ttl) != 0) { 62d9638e54Smws ep->ev_flags |= FMD_EVF_LOCAL; 63d9638e54Smws ep->ev_ttl = (uint8_t)fmd.d_xprt_ttl; 64d9638e54Smws } 65d9638e54Smws 66d9638e54Smws if (tp != NULL) 67d9638e54Smws ep->ev_time = *tp; 68d9638e54Smws else if (nvlist_lookup_uint64_array(ep->ev_nvl, 69d9638e54Smws FMD_EVN_TOD, &tod, &n) == 0 && n >= 2) 70d9638e54Smws ep->ev_time = *(const fmd_timeval_t *)tod; 71d9638e54Smws else 72d9638e54Smws fmd_time_sync(&ep->ev_time, &ep->ev_hrt, 1); 73d9638e54Smws } 74d9638e54Smws 757c478bd9Sstevel@tonic-gate fmd_event_t * 767c478bd9Sstevel@tonic-gate fmd_event_recreate(uint_t type, const fmd_timeval_t *tp, 777c478bd9Sstevel@tonic-gate nvlist_t *nvl, void *data, fmd_log_t *lp, off64_t off, size_t len) 787c478bd9Sstevel@tonic-gate { 797c478bd9Sstevel@tonic-gate fmd_event_impl_t *ep = fmd_alloc(sizeof (fmd_event_impl_t), FMD_SLEEP); 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate fmd_timeval_t tod; 827c478bd9Sstevel@tonic-gate hrtime_t hr0; 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate (void) pthread_mutex_init(&ep->ev_lock, NULL); 857c478bd9Sstevel@tonic-gate ep->ev_refs = 0; 867c478bd9Sstevel@tonic-gate ASSERT(type < FMD_EVT_NTYPES); 87d9638e54Smws ep->ev_type = (uint8_t)type; 887c478bd9Sstevel@tonic-gate ep->ev_state = FMD_EVS_RECEIVED; 897c478bd9Sstevel@tonic-gate ep->ev_flags = FMD_EVF_REPLAY; 907c478bd9Sstevel@tonic-gate ep->ev_nvl = nvl; 917c478bd9Sstevel@tonic-gate ep->ev_data = data; 927c478bd9Sstevel@tonic-gate ep->ev_log = lp; 937c478bd9Sstevel@tonic-gate ep->ev_off = off; 947c478bd9Sstevel@tonic-gate ep->ev_len = len; 957c478bd9Sstevel@tonic-gate 96d9638e54Smws fmd_event_nvunwrap(ep, tp); 97d9638e54Smws 987c478bd9Sstevel@tonic-gate /* 997c478bd9Sstevel@tonic-gate * If we're not restoring from a log, the event is marked volatile. If 1007c478bd9Sstevel@tonic-gate * we are restoring from a log, then hold the log pointer and increment 1017c478bd9Sstevel@tonic-gate * the pending count. If we're using a log but no offset and data len 1027c478bd9Sstevel@tonic-gate * are specified, it's a checkpoint event: don't replay or set pending. 1037c478bd9Sstevel@tonic-gate */ 1047c478bd9Sstevel@tonic-gate if (lp == NULL) 1057c478bd9Sstevel@tonic-gate ep->ev_flags |= FMD_EVF_VOLATILE; 1067c478bd9Sstevel@tonic-gate else if (off != 0 && len != 0) 1077c478bd9Sstevel@tonic-gate fmd_log_hold_pending(lp); 1087c478bd9Sstevel@tonic-gate else { 1097c478bd9Sstevel@tonic-gate ep->ev_flags &= ~FMD_EVF_REPLAY; 1107c478bd9Sstevel@tonic-gate fmd_log_hold(lp); 1117c478bd9Sstevel@tonic-gate } 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate /* 1147c478bd9Sstevel@tonic-gate * Sample a (TOD, hrtime) pair from the current system clocks and then 115d9638e54Smws * compute ev_hrt by taking the delta between this TOD and ev_time. 1167c478bd9Sstevel@tonic-gate */ 1177c478bd9Sstevel@tonic-gate fmd_time_sync(&tod, &hr0, 1); 118d9638e54Smws fmd_time_tod2hrt(hr0, &tod, &ep->ev_time, &ep->ev_hrt); 1197c478bd9Sstevel@tonic-gate 120d9638e54Smws fmd_event_nvwrap(ep); 1217c478bd9Sstevel@tonic-gate return ((fmd_event_t *)ep); 1227c478bd9Sstevel@tonic-gate } 1237c478bd9Sstevel@tonic-gate 1247c478bd9Sstevel@tonic-gate fmd_event_t * 1257c478bd9Sstevel@tonic-gate fmd_event_create(uint_t type, hrtime_t hrt, nvlist_t *nvl, void *data) 1267c478bd9Sstevel@tonic-gate { 1277c478bd9Sstevel@tonic-gate fmd_event_impl_t *ep = fmd_alloc(sizeof (fmd_event_impl_t), FMD_SLEEP); 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate fmd_timeval_t tod; 1307c478bd9Sstevel@tonic-gate hrtime_t hr0; 1317c478bd9Sstevel@tonic-gate const char *p; 1327c478bd9Sstevel@tonic-gate uint64_t ena; 1337c478bd9Sstevel@tonic-gate 1347c478bd9Sstevel@tonic-gate (void) pthread_mutex_init(&ep->ev_lock, NULL); 1357c478bd9Sstevel@tonic-gate ep->ev_refs = 0; 1367c478bd9Sstevel@tonic-gate ASSERT(type < FMD_EVT_NTYPES); 137d9638e54Smws ep->ev_type = (uint8_t)type; 1387c478bd9Sstevel@tonic-gate ep->ev_state = FMD_EVS_RECEIVED; 139d9638e54Smws ep->ev_flags = FMD_EVF_VOLATILE | FMD_EVF_REPLAY | FMD_EVF_LOCAL; 140d9638e54Smws ep->ev_ttl = (uint8_t)fmd.d_xprt_ttl; 1417c478bd9Sstevel@tonic-gate ep->ev_nvl = nvl; 1427c478bd9Sstevel@tonic-gate ep->ev_data = data; 1437c478bd9Sstevel@tonic-gate ep->ev_log = NULL; 1447c478bd9Sstevel@tonic-gate ep->ev_off = 0; 1457c478bd9Sstevel@tonic-gate ep->ev_len = 0; 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate /* 1487c478bd9Sstevel@tonic-gate * Sample TOD and then set ev_time to the earlier TOD corresponding to 1497c478bd9Sstevel@tonic-gate * the input hrtime value. This needs to be improved later: hrestime 1507c478bd9Sstevel@tonic-gate * should be sampled by the transport and passed as an input parameter. 1517c478bd9Sstevel@tonic-gate */ 1527c478bd9Sstevel@tonic-gate fmd_time_sync(&tod, &hr0, 1); 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate if (hrt == FMD_HRT_NOW) 1557c478bd9Sstevel@tonic-gate hrt = hr0; /* use hrtime sampled by fmd_time_sync() */ 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate /* 1587c478bd9Sstevel@tonic-gate * If this is an FMA protocol event of class "ereport.*" that contains 1597c478bd9Sstevel@tonic-gate * valid ENA, we can compute a more precise bound on the event time. 1607c478bd9Sstevel@tonic-gate */ 1617c478bd9Sstevel@tonic-gate if (type == FMD_EVT_PROTOCOL && (p = strchr(data, '.')) != NULL && 1627c478bd9Sstevel@tonic-gate strncmp(data, FM_EREPORT_CLASS, (size_t)(p - (char *)data)) == 0 && 1637c478bd9Sstevel@tonic-gate nvlist_lookup_uint64(nvl, FM_EREPORT_ENA, &ena) == 0 && 1647c478bd9Sstevel@tonic-gate fmd.d_clockops == &fmd_timeops_native) 1657c478bd9Sstevel@tonic-gate hrt = fmd_time_ena2hrt(hrt, ena); 1667c478bd9Sstevel@tonic-gate 1677c478bd9Sstevel@tonic-gate fmd_time_hrt2tod(hr0, &tod, hrt, &ep->ev_time); 1687c478bd9Sstevel@tonic-gate ep->ev_hrt = hrt; 1697c478bd9Sstevel@tonic-gate 170d9638e54Smws fmd_event_nvwrap(ep); 1717c478bd9Sstevel@tonic-gate return ((fmd_event_t *)ep); 1727c478bd9Sstevel@tonic-gate } 1737c478bd9Sstevel@tonic-gate 1747c478bd9Sstevel@tonic-gate void 1757c478bd9Sstevel@tonic-gate fmd_event_destroy(fmd_event_t *e) 1767c478bd9Sstevel@tonic-gate { 1777c478bd9Sstevel@tonic-gate fmd_event_impl_t *ep = (fmd_event_impl_t *)e; 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate ASSERT(MUTEX_HELD(&ep->ev_lock)); 1807c478bd9Sstevel@tonic-gate ASSERT(ep->ev_refs == 0); 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate /* 1837c478bd9Sstevel@tonic-gate * If the current state is RECEIVED (i.e. no module has accepted the 1847c478bd9Sstevel@tonic-gate * event) and the event was logged, then change the state to DISCARDED. 1857c478bd9Sstevel@tonic-gate */ 1867c478bd9Sstevel@tonic-gate if (ep->ev_state == FMD_EVS_RECEIVED) 1877c478bd9Sstevel@tonic-gate ep->ev_state = FMD_EVS_DISCARDED; 1887c478bd9Sstevel@tonic-gate 1897c478bd9Sstevel@tonic-gate /* 1907c478bd9Sstevel@tonic-gate * If the current state is DISCARDED, ACCEPTED, or DIAGNOSED and the 1917c478bd9Sstevel@tonic-gate * event has not yet been commited, then attempt to commit it now. 1927c478bd9Sstevel@tonic-gate */ 1937c478bd9Sstevel@tonic-gate if (ep->ev_state != FMD_EVS_RECEIVED && (ep->ev_flags & ( 1947c478bd9Sstevel@tonic-gate FMD_EVF_VOLATILE | FMD_EVF_REPLAY)) == FMD_EVF_REPLAY) 1957c478bd9Sstevel@tonic-gate fmd_log_commit(ep->ev_log, e); 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate if (ep->ev_log != NULL) { 1987c478bd9Sstevel@tonic-gate if (ep->ev_flags & FMD_EVF_REPLAY) 1997c478bd9Sstevel@tonic-gate fmd_log_decommit(ep->ev_log, e); 2007c478bd9Sstevel@tonic-gate fmd_log_rele(ep->ev_log); 2017c478bd9Sstevel@tonic-gate } 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate /* 2047c478bd9Sstevel@tonic-gate * Perform any event type-specific cleanup activities, and then free 2057c478bd9Sstevel@tonic-gate * the name-value pair list and underlying event data structure. 2067c478bd9Sstevel@tonic-gate */ 2077c478bd9Sstevel@tonic-gate switch (ep->ev_type) { 208d9638e54Smws case FMD_EVT_TIMEOUT: 209d9638e54Smws fmd_free(ep->ev_data, sizeof (fmd_modtimer_t)); 210d9638e54Smws break; 2117c478bd9Sstevel@tonic-gate case FMD_EVT_CLOSE: 212d9638e54Smws case FMD_EVT_PUBLISH: 2137c478bd9Sstevel@tonic-gate fmd_case_rele(ep->ev_data); 2147c478bd9Sstevel@tonic-gate break; 2157c478bd9Sstevel@tonic-gate case FMD_EVT_CTL: 2167c478bd9Sstevel@tonic-gate fmd_ctl_fini(ep->ev_data); 2177c478bd9Sstevel@tonic-gate break; 21824db4641Seschrock case FMD_EVT_TOPO: 21924db4641Seschrock fmd_topo_rele(ep->ev_data); 22024db4641Seschrock break; 2217c478bd9Sstevel@tonic-gate } 2227c478bd9Sstevel@tonic-gate 2237c478bd9Sstevel@tonic-gate nvlist_free(ep->ev_nvl); 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate fmd_free(ep, sizeof (fmd_event_impl_t)); 2267c478bd9Sstevel@tonic-gate } 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate void 2297c478bd9Sstevel@tonic-gate fmd_event_hold(fmd_event_t *e) 2307c478bd9Sstevel@tonic-gate { 2317c478bd9Sstevel@tonic-gate fmd_event_impl_t *ep = (fmd_event_impl_t *)e; 2327c478bd9Sstevel@tonic-gate 2337c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&ep->ev_lock); 2347c478bd9Sstevel@tonic-gate ep->ev_refs++; 2357c478bd9Sstevel@tonic-gate ASSERT(ep->ev_refs != 0); 2367c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&ep->ev_lock); 2377c478bd9Sstevel@tonic-gate 2387c478bd9Sstevel@tonic-gate if (ep->ev_type == FMD_EVT_CTL) 2397c478bd9Sstevel@tonic-gate fmd_ctl_hold(ep->ev_data); 2407c478bd9Sstevel@tonic-gate } 2417c478bd9Sstevel@tonic-gate 2427c478bd9Sstevel@tonic-gate void 2437c478bd9Sstevel@tonic-gate fmd_event_rele(fmd_event_t *e) 2447c478bd9Sstevel@tonic-gate { 2457c478bd9Sstevel@tonic-gate fmd_event_impl_t *ep = (fmd_event_impl_t *)e; 2467c478bd9Sstevel@tonic-gate 2477c478bd9Sstevel@tonic-gate if (ep->ev_type == FMD_EVT_CTL) 2487c478bd9Sstevel@tonic-gate fmd_ctl_rele(ep->ev_data); 2497c478bd9Sstevel@tonic-gate 2507c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&ep->ev_lock); 2517c478bd9Sstevel@tonic-gate ASSERT(ep->ev_refs != 0); 2527c478bd9Sstevel@tonic-gate 2537c478bd9Sstevel@tonic-gate if (--ep->ev_refs == 0) 2547c478bd9Sstevel@tonic-gate fmd_event_destroy(e); 2557c478bd9Sstevel@tonic-gate else 2567c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&ep->ev_lock); 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate /* 2607c478bd9Sstevel@tonic-gate * Transition event from its current state to the specified state. The states 2617c478bd9Sstevel@tonic-gate * for events are defined in fmd_event.h and work according to the diagram: 2627c478bd9Sstevel@tonic-gate * 2637c478bd9Sstevel@tonic-gate * ------------- ------------- State Description 2647c478bd9Sstevel@tonic-gate * ( RECEIVED =1 )-->( ACCEPTED =2 ) ---------- --------------------------- 2657c478bd9Sstevel@tonic-gate * -----+-------\ ------+------ DISCARDED No active references in fmd 2667c478bd9Sstevel@tonic-gate * | \ | RECEIVED Active refs in fmd, no case 2677c478bd9Sstevel@tonic-gate * -----v------- \ ------v------ ACCEPTED Active refs, case assigned 2687c478bd9Sstevel@tonic-gate * ( DISCARDED=0 ) v( DIAGNOSED=3 ) DIAGNOSED Active refs, case solved 2697c478bd9Sstevel@tonic-gate * ------------- ------------- 2707c478bd9Sstevel@tonic-gate * 2717c478bd9Sstevel@tonic-gate * Since events are reference counted on behalf of multiple subscribers, any 2727c478bd9Sstevel@tonic-gate * attempt to transition an event to an "earlier" or "equal" state (as defined 2737c478bd9Sstevel@tonic-gate * by the numeric state values shown in the diagram) is silently ignored. 2747c478bd9Sstevel@tonic-gate * An event begins life in the RECEIVED state, so the RECEIVED -> DISCARDED 2757c478bd9Sstevel@tonic-gate * transition is handled by fmd_event_destroy() when no references remain. 2767c478bd9Sstevel@tonic-gate */ 2777c478bd9Sstevel@tonic-gate void 2787c478bd9Sstevel@tonic-gate fmd_event_transition(fmd_event_t *e, uint_t state) 2797c478bd9Sstevel@tonic-gate { 2807c478bd9Sstevel@tonic-gate fmd_event_impl_t *ep = (fmd_event_impl_t *)e; 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&ep->ev_lock); 2837c478bd9Sstevel@tonic-gate 2847c478bd9Sstevel@tonic-gate TRACE((FMD_DBG_EVT, "event %p transition %u -> %u", 2857c478bd9Sstevel@tonic-gate (void *)ep, ep->ev_state, state)); 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate if (state <= ep->ev_state) { 2887c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&ep->ev_lock); 2897c478bd9Sstevel@tonic-gate return; /* no state change necessary */ 2907c478bd9Sstevel@tonic-gate } 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate if (ep->ev_state < FMD_EVS_RECEIVED || ep->ev_state > FMD_EVS_DIAGNOSED) 2937c478bd9Sstevel@tonic-gate fmd_panic("illegal transition %u -> %u\n", ep->ev_state, state); 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate ep->ev_state = state; 2967c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&ep->ev_lock); 2977c478bd9Sstevel@tonic-gate } 2987c478bd9Sstevel@tonic-gate 2997c478bd9Sstevel@tonic-gate /* 3007c478bd9Sstevel@tonic-gate * If the specified event is DISCARDED, ACCEPTED, OR DIAGNOSED and it has been 3017c478bd9Sstevel@tonic-gate * written to a log but is still marked for replay, attempt to commit it to the 3027c478bd9Sstevel@tonic-gate * log so that it will not be replayed. If fmd_log_commit() is successful, it 3037c478bd9Sstevel@tonic-gate * will clear the FMD_EVF_REPLAY flag on the event for us. 3047c478bd9Sstevel@tonic-gate */ 3057c478bd9Sstevel@tonic-gate void 3067c478bd9Sstevel@tonic-gate fmd_event_commit(fmd_event_t *e) 3077c478bd9Sstevel@tonic-gate { 3087c478bd9Sstevel@tonic-gate fmd_event_impl_t *ep = (fmd_event_impl_t *)e; 3097c478bd9Sstevel@tonic-gate 3107c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&ep->ev_lock); 3117c478bd9Sstevel@tonic-gate 3127c478bd9Sstevel@tonic-gate if (ep->ev_state != FMD_EVS_RECEIVED && (ep->ev_flags & ( 3137c478bd9Sstevel@tonic-gate FMD_EVF_VOLATILE | FMD_EVF_REPLAY)) == FMD_EVF_REPLAY) 3147c478bd9Sstevel@tonic-gate fmd_log_commit(ep->ev_log, e); 3157c478bd9Sstevel@tonic-gate 3167c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&ep->ev_lock); 3177c478bd9Sstevel@tonic-gate } 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate /* 3207c478bd9Sstevel@tonic-gate * Compute the delta between events in nanoseconds. To account for very old 3217c478bd9Sstevel@tonic-gate * events which are replayed, we must handle the case where ev_hrt is negative. 3227c478bd9Sstevel@tonic-gate * We convert the hrtime_t's to unsigned 64-bit integers and then handle the 3237c478bd9Sstevel@tonic-gate * case where 'old' is greater than 'new' (i.e. high-res time has wrapped). 3247c478bd9Sstevel@tonic-gate */ 3257c478bd9Sstevel@tonic-gate hrtime_t 3267c478bd9Sstevel@tonic-gate fmd_event_delta(fmd_event_t *e1, fmd_event_t *e2) 3277c478bd9Sstevel@tonic-gate { 3287c478bd9Sstevel@tonic-gate uint64_t old = ((fmd_event_impl_t *)e1)->ev_hrt; 3297c478bd9Sstevel@tonic-gate uint64_t new = ((fmd_event_impl_t *)e2)->ev_hrt; 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate return (new >= old ? new - old : (UINT64_MAX - old) + new + 1); 3327c478bd9Sstevel@tonic-gate } 3337c478bd9Sstevel@tonic-gate 3347c478bd9Sstevel@tonic-gate hrtime_t 3357c478bd9Sstevel@tonic-gate fmd_event_hrtime(fmd_event_t *ep) 3367c478bd9Sstevel@tonic-gate { 3377c478bd9Sstevel@tonic-gate return (((fmd_event_impl_t *)ep)->ev_hrt); 3387c478bd9Sstevel@tonic-gate } 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate int 341d9638e54Smws fmd_event_match(fmd_event_t *e, uint_t type, const void *data) 3427c478bd9Sstevel@tonic-gate { 3437c478bd9Sstevel@tonic-gate fmd_event_impl_t *ep = (fmd_event_impl_t *)e; 3447c478bd9Sstevel@tonic-gate 345*97c04605Scy152378 if (ep->ev_type != type) 346*97c04605Scy152378 return (0); 347*97c04605Scy152378 3487c478bd9Sstevel@tonic-gate if (type == FMD_EVT_PROTOCOL) 349*97c04605Scy152378 return (fmd_strmatch(ep->ev_data, data)); 3509dd0f810Scindi else if (type == FMD_EVT_TIMEOUT) 3519dd0f810Scindi return ((id_t)data == ((fmd_modtimer_t *)ep->ev_data)->mt_id); 3527c478bd9Sstevel@tonic-gate else 353*97c04605Scy152378 return (ep->ev_data == data); 3547c478bd9Sstevel@tonic-gate } 3557c478bd9Sstevel@tonic-gate 3567c478bd9Sstevel@tonic-gate int 3577c478bd9Sstevel@tonic-gate fmd_event_equal(fmd_event_t *e1, fmd_event_t *e2) 3587c478bd9Sstevel@tonic-gate { 3597c478bd9Sstevel@tonic-gate fmd_event_impl_t *ep1 = (fmd_event_impl_t *)e1; 3607c478bd9Sstevel@tonic-gate fmd_event_impl_t *ep2 = (fmd_event_impl_t *)e2; 3617c478bd9Sstevel@tonic-gate 3627c478bd9Sstevel@tonic-gate return (ep1->ev_log != NULL && 3637c478bd9Sstevel@tonic-gate ep1->ev_log == ep2->ev_log && ep1->ev_off == ep2->ev_off); 3647c478bd9Sstevel@tonic-gate } 365