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