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 580ab886dSwesolows * Common Development and Distribution License (the "License"). 680ab886dSwesolows * 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*f6e214c7SGavin Maltby * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #include <sys/types.h> 277c478bd9Sstevel@tonic-gate #include <sys/fm/protocol.h> 28b7d3956bSstephh #include <fm/topo_hc.h> 29*f6e214c7SGavin Maltby #include <uuid/uuid.h> 307c478bd9Sstevel@tonic-gate 317c478bd9Sstevel@tonic-gate #include <unistd.h> 327c478bd9Sstevel@tonic-gate #include <signal.h> 337c478bd9Sstevel@tonic-gate #include <limits.h> 347c478bd9Sstevel@tonic-gate #include <syslog.h> 357c478bd9Sstevel@tonic-gate #include <alloca.h> 3624db4641Seschrock #include <stddef.h> 37*f6e214c7SGavin Maltby #include <door.h> 387c478bd9Sstevel@tonic-gate 397c478bd9Sstevel@tonic-gate #include <fmd_module.h> 407c478bd9Sstevel@tonic-gate #include <fmd_api.h> 417c478bd9Sstevel@tonic-gate #include <fmd_string.h> 427c478bd9Sstevel@tonic-gate #include <fmd_subr.h> 437c478bd9Sstevel@tonic-gate #include <fmd_error.h> 447c478bd9Sstevel@tonic-gate #include <fmd_event.h> 457c478bd9Sstevel@tonic-gate #include <fmd_eventq.h> 467c478bd9Sstevel@tonic-gate #include <fmd_dispq.h> 477c478bd9Sstevel@tonic-gate #include <fmd_timerq.h> 487c478bd9Sstevel@tonic-gate #include <fmd_thread.h> 497c478bd9Sstevel@tonic-gate #include <fmd_ustat.h> 507c478bd9Sstevel@tonic-gate #include <fmd_case.h> 517c478bd9Sstevel@tonic-gate #include <fmd_protocol.h> 527c478bd9Sstevel@tonic-gate #include <fmd_buf.h> 537c478bd9Sstevel@tonic-gate #include <fmd_asru.h> 547c478bd9Sstevel@tonic-gate #include <fmd_fmri.h> 550eb822a1Scindi #include <fmd_topo.h> 567c478bd9Sstevel@tonic-gate #include <fmd_ckpt.h> 57d9638e54Smws #include <fmd_xprt.h> 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate #include <fmd.h> 607c478bd9Sstevel@tonic-gate 617c478bd9Sstevel@tonic-gate /* 627c478bd9Sstevel@tonic-gate * Table of configuration file variable types ops-vector pointers. We use this 637c478bd9Sstevel@tonic-gate * to convert from the property description array specified by the module to an 647c478bd9Sstevel@tonic-gate * array of fmd_conf_formal_t's. The order of this array must match the order 657c478bd9Sstevel@tonic-gate * of #define values specified in <fmd_api.h> (i.e. FMD_TYPE_BOOL must be 0). 667c478bd9Sstevel@tonic-gate * For now, the fmd_conf_list and fmd_conf_path types are not supported as we 677c478bd9Sstevel@tonic-gate * do not believe modules need them and they would require more complexity. 687c478bd9Sstevel@tonic-gate */ 697c478bd9Sstevel@tonic-gate static const fmd_conf_ops_t *const _fmd_prop_ops[] = { 707c478bd9Sstevel@tonic-gate &fmd_conf_bool, /* FMD_TYPE_BOOL */ 717c478bd9Sstevel@tonic-gate &fmd_conf_int32, /* FMD_TYPE_INT32 */ 727c478bd9Sstevel@tonic-gate &fmd_conf_uint32, /* FMD_TYPE_UINT32 */ 737c478bd9Sstevel@tonic-gate &fmd_conf_int64, /* FMD_TYPE_INT64 */ 747c478bd9Sstevel@tonic-gate &fmd_conf_uint64, /* FMD_TYPE_UINT64 */ 757c478bd9Sstevel@tonic-gate &fmd_conf_string, /* FMD_TYPE_STRING */ 767c478bd9Sstevel@tonic-gate &fmd_conf_time, /* FMD_TYPE_TIME */ 777c478bd9Sstevel@tonic-gate &fmd_conf_size, /* FMD_TYPE_SIZE */ 787c478bd9Sstevel@tonic-gate }; 797c478bd9Sstevel@tonic-gate 8080ab886dSwesolows static void fmd_api_verror(fmd_module_t *, int, const char *, va_list) 8180ab886dSwesolows __NORETURN; 8280ab886dSwesolows static void fmd_api_error(fmd_module_t *, int, const char *, ...) __NORETURN; 8380ab886dSwesolows 847c478bd9Sstevel@tonic-gate /* 857c478bd9Sstevel@tonic-gate * fmd_api_vxerror() provides the engine underlying the fmd_hdl_[v]error() API 867c478bd9Sstevel@tonic-gate * calls and the fmd_api_[v]error() utility routine defined below. The routine 877c478bd9Sstevel@tonic-gate * formats the error, optionally associated with a particular errno code 'err', 887c478bd9Sstevel@tonic-gate * and logs it as an ereport associated with the calling module. Depending on 897c478bd9Sstevel@tonic-gate * other optional properties, we also emit a message to stderr and to syslog. 907c478bd9Sstevel@tonic-gate */ 917c478bd9Sstevel@tonic-gate static void 927c478bd9Sstevel@tonic-gate fmd_api_vxerror(fmd_module_t *mp, int err, const char *format, va_list ap) 937c478bd9Sstevel@tonic-gate { 94d9638e54Smws int raw_err = err; 957c478bd9Sstevel@tonic-gate nvlist_t *nvl; 967c478bd9Sstevel@tonic-gate fmd_event_t *e; 977c478bd9Sstevel@tonic-gate char *class, *msg; 987c478bd9Sstevel@tonic-gate size_t len1, len2; 997c478bd9Sstevel@tonic-gate char c; 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate /* 1027c478bd9Sstevel@tonic-gate * fmd_api_vxerror() counts as both an error of class EFMD_MODULE 1037c478bd9Sstevel@tonic-gate * as well as an instance of 'err' w.r.t. our internal bean counters. 1047c478bd9Sstevel@tonic-gate */ 1057c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&fmd.d_err_lock); 1067c478bd9Sstevel@tonic-gate fmd.d_errstats[EFMD_MODULE - EFMD_UNKNOWN].fmds_value.ui64++; 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate if (err > EFMD_UNKNOWN && err < EFMD_END) 1097c478bd9Sstevel@tonic-gate fmd.d_errstats[err - EFMD_UNKNOWN].fmds_value.ui64++; 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&fmd.d_err_lock); 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate /* 1147c478bd9Sstevel@tonic-gate * Format the message using vsnprintf(). As usual, if the format has a 1157c478bd9Sstevel@tonic-gate * newline in it, it is printed alone; otherwise strerror() is added. 1167c478bd9Sstevel@tonic-gate */ 1177c478bd9Sstevel@tonic-gate if (strchr(format, '\n') != NULL) 1187c478bd9Sstevel@tonic-gate err = 0; /* err is not relevant in the message */ 1197c478bd9Sstevel@tonic-gate 1207c478bd9Sstevel@tonic-gate len1 = vsnprintf(&c, 1, format, ap); 1217c478bd9Sstevel@tonic-gate len2 = err != 0 ? snprintf(&c, 1, ": %s\n", fmd_strerror(err)) : 0; 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate msg = fmd_alloc(len1 + len2 + 1, FMD_SLEEP); 1247c478bd9Sstevel@tonic-gate (void) vsnprintf(msg, len1 + 1, format, ap); 1257c478bd9Sstevel@tonic-gate 1267c478bd9Sstevel@tonic-gate if (err != 0) { 1277c478bd9Sstevel@tonic-gate (void) snprintf(&msg[len1], len2 + 1, 1287c478bd9Sstevel@tonic-gate ": %s\n", fmd_strerror(err)); 1297c478bd9Sstevel@tonic-gate } 1307c478bd9Sstevel@tonic-gate 1317c478bd9Sstevel@tonic-gate /* 1327c478bd9Sstevel@tonic-gate * Create an error event corresponding to the error, insert it into the 1337c478bd9Sstevel@tonic-gate * error log, and dispatch it to the fmd-self-diagnosis engine. 1347c478bd9Sstevel@tonic-gate */ 135d9638e54Smws if (mp != fmd.d_self && (raw_err != EFMD_HDL_ABORT || fmd.d_running)) { 1367c478bd9Sstevel@tonic-gate if ((c = msg[len1 + len2 - 1]) == '\n') 1377c478bd9Sstevel@tonic-gate msg[len1 + len2 - 1] = '\0'; /* strip \n for event */ 1387c478bd9Sstevel@tonic-gate 1397c478bd9Sstevel@tonic-gate nvl = fmd_protocol_moderror(mp, err, msg); 1407c478bd9Sstevel@tonic-gate 1417c478bd9Sstevel@tonic-gate if (c == '\n') 1427c478bd9Sstevel@tonic-gate msg[len1 + len2 - 1] = c; 1437c478bd9Sstevel@tonic-gate 1447c478bd9Sstevel@tonic-gate (void) nvlist_lookup_string(nvl, FM_CLASS, &class); 1457c478bd9Sstevel@tonic-gate e = fmd_event_create(FMD_EVT_PROTOCOL, FMD_HRT_NOW, nvl, class); 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate (void) pthread_rwlock_rdlock(&fmd.d_log_lock); 1487c478bd9Sstevel@tonic-gate fmd_log_append(fmd.d_errlog, e, NULL); 1497c478bd9Sstevel@tonic-gate (void) pthread_rwlock_unlock(&fmd.d_log_lock); 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate fmd_event_transition(e, FMD_EVS_ACCEPTED); 1527c478bd9Sstevel@tonic-gate fmd_event_commit(e); 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate fmd_dispq_dispatch(fmd.d_disp, e, class); 1557c478bd9Sstevel@tonic-gate } 1567c478bd9Sstevel@tonic-gate 1577c478bd9Sstevel@tonic-gate /* 1587c478bd9Sstevel@tonic-gate * Similar to fmd_vdebug(), if the debugging switches are enabled we 1597c478bd9Sstevel@tonic-gate * echo the module name and message to stderr and/or syslog. Unlike 1607c478bd9Sstevel@tonic-gate * fmd_vdebug(), we also print to stderr if foreground mode is enabled. 161d9638e54Smws * We also print the message if a built-in module is aborting before 162d9638e54Smws * fmd has detached from its parent (e.g. default transport failure). 1637c478bd9Sstevel@tonic-gate */ 164d9638e54Smws if (fmd.d_fg || (fmd.d_hdl_dbout & FMD_DBOUT_STDERR) || ( 165d9638e54Smws raw_err == EFMD_HDL_ABORT && !fmd.d_running)) { 1667c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&fmd.d_err_lock); 1677c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s: %s: %s", 1687c478bd9Sstevel@tonic-gate fmd.d_pname, mp->mod_name, msg); 1697c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&fmd.d_err_lock); 1707c478bd9Sstevel@tonic-gate } 1717c478bd9Sstevel@tonic-gate 1727c478bd9Sstevel@tonic-gate if (fmd.d_hdl_dbout & FMD_DBOUT_SYSLOG) { 1737c478bd9Sstevel@tonic-gate syslog(LOG_ERR | LOG_DAEMON, "%s ERROR: %s: %s", 1747c478bd9Sstevel@tonic-gate fmd.d_pname, mp->mod_name, msg); 1757c478bd9Sstevel@tonic-gate } 1767c478bd9Sstevel@tonic-gate 1777c478bd9Sstevel@tonic-gate fmd_free(msg, len1 + len2 + 1); 1787c478bd9Sstevel@tonic-gate } 1797c478bd9Sstevel@tonic-gate 1807c478bd9Sstevel@tonic-gate /*PRINTFLIKE3*/ 1817c478bd9Sstevel@tonic-gate static void 1827c478bd9Sstevel@tonic-gate fmd_api_xerror(fmd_module_t *mp, int err, const char *format, ...) 1837c478bd9Sstevel@tonic-gate { 1847c478bd9Sstevel@tonic-gate va_list ap; 1857c478bd9Sstevel@tonic-gate 1867c478bd9Sstevel@tonic-gate va_start(ap, format); 1877c478bd9Sstevel@tonic-gate fmd_api_vxerror(mp, err, format, ap); 1887c478bd9Sstevel@tonic-gate va_end(ap); 1897c478bd9Sstevel@tonic-gate } 1907c478bd9Sstevel@tonic-gate 1917c478bd9Sstevel@tonic-gate /* 1927c478bd9Sstevel@tonic-gate * fmd_api_verror() is a wrapper around fmd_api_vxerror() for API subroutines. 1937c478bd9Sstevel@tonic-gate * It calls fmd_module_unlock() on behalf of its caller, logs the error, and 1947c478bd9Sstevel@tonic-gate * then aborts the API call and the surrounding module entry point by doing an 1957c478bd9Sstevel@tonic-gate * fmd_module_abort(), which longjmps to the place where we entered the module. 1967c478bd9Sstevel@tonic-gate */ 1977c478bd9Sstevel@tonic-gate static void 1987c478bd9Sstevel@tonic-gate fmd_api_verror(fmd_module_t *mp, int err, const char *format, va_list ap) 1997c478bd9Sstevel@tonic-gate { 2007c478bd9Sstevel@tonic-gate if (fmd_module_locked(mp)) 2017c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate fmd_api_vxerror(mp, err, format, ap); 2047c478bd9Sstevel@tonic-gate fmd_module_abort(mp, err); 2057c478bd9Sstevel@tonic-gate } 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate /*PRINTFLIKE3*/ 2087c478bd9Sstevel@tonic-gate static void 2097c478bd9Sstevel@tonic-gate fmd_api_error(fmd_module_t *mp, int err, const char *format, ...) 2107c478bd9Sstevel@tonic-gate { 2117c478bd9Sstevel@tonic-gate va_list ap; 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate va_start(ap, format); 2147c478bd9Sstevel@tonic-gate fmd_api_verror(mp, err, format, ap); 2157c478bd9Sstevel@tonic-gate va_end(ap); 2167c478bd9Sstevel@tonic-gate } 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate /* 219d9638e54Smws * Common code for fmd_api_module_lock() and fmd_api_transport_impl(). This 220d9638e54Smws * code verifies that the handle is valid and associated with a proper thread. 2217c478bd9Sstevel@tonic-gate */ 2227c478bd9Sstevel@tonic-gate static fmd_module_t * 223d9638e54Smws fmd_api_module(fmd_hdl_t *hdl) 2247c478bd9Sstevel@tonic-gate { 2257c478bd9Sstevel@tonic-gate fmd_thread_t *tp; 2267c478bd9Sstevel@tonic-gate fmd_module_t *mp; 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate /* 2297c478bd9Sstevel@tonic-gate * If our TSD is not present at all, this is either a serious bug or 2307c478bd9Sstevel@tonic-gate * someone has created a thread behind our back and is using fmd's API. 2317c478bd9Sstevel@tonic-gate * We can't call fmd_api_error() because we can't be sure that we can 2327c478bd9Sstevel@tonic-gate * unwind our state back to an enclosing fmd_module_dispatch(), so we 2337c478bd9Sstevel@tonic-gate * must panic instead. This is likely a module design or coding error. 2347c478bd9Sstevel@tonic-gate */ 2357c478bd9Sstevel@tonic-gate if ((tp = pthread_getspecific(fmd.d_key)) == NULL) { 2367c478bd9Sstevel@tonic-gate fmd_panic("fmd module api call made using " 2377c478bd9Sstevel@tonic-gate "client handle %p from unknown thread\n", (void *)hdl); 2387c478bd9Sstevel@tonic-gate } 2397c478bd9Sstevel@tonic-gate 240d9638e54Smws /* 241*f6e214c7SGavin Maltby * If our TSD refers to the root module and is a non-private 242*f6e214c7SGavin Maltby * door server thread, then it was created asynchronously at the 243*f6e214c7SGavin Maltby * request of a module but is using now the module API as an 244*f6e214c7SGavin Maltby * auxiliary module thread. We reset tp->thr_mod to the module 245*f6e214c7SGavin Maltby * handle so it can act as a module thread. 246*f6e214c7SGavin Maltby * 247*f6e214c7SGavin Maltby * If more than one module uses non-private doors then the 248*f6e214c7SGavin Maltby * "client handle is not valid" check below can fail since 249*f6e214c7SGavin Maltby * door server threads for such doors can service *any* 250*f6e214c7SGavin Maltby * non-private door. We use non-private door for legacy sysevent 251*f6e214c7SGavin Maltby * alone. 252d9638e54Smws */ 253d9638e54Smws if (tp->thr_mod == fmd.d_rmod && tp->thr_func == &fmd_door_server) 254d9638e54Smws tp->thr_mod = (fmd_module_t *)hdl; 255d9638e54Smws 2567c478bd9Sstevel@tonic-gate if ((mp = tp->thr_mod) != (fmd_module_t *)hdl) { 2577c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_HDL_INVAL, 2587c478bd9Sstevel@tonic-gate "client handle %p is not valid\n", (void *)hdl); 2597c478bd9Sstevel@tonic-gate } 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate if (mp->mod_flags & FMD_MOD_FAIL) { 2627c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_MOD_FAIL, 2637c478bd9Sstevel@tonic-gate "module has experienced an unrecoverable error\n"); 2647c478bd9Sstevel@tonic-gate } 2657c478bd9Sstevel@tonic-gate 266d9638e54Smws return (mp); 267d9638e54Smws } 268d9638e54Smws 269d9638e54Smws /* 270d9638e54Smws * fmd_api_module_lock() is used as a wrapper around fmd_module_lock() and a 271d9638e54Smws * common prologue to each fmd_api.c routine. It verifies that the handle is 272d9638e54Smws * valid and owned by the current server thread, locks the handle, and then 273d9638e54Smws * verifies that the caller is performing an operation on a registered handle. 274d9638e54Smws * If any tests fail, the entire API call is aborted by fmd_api_error(). 275d9638e54Smws */ 276d9638e54Smws static fmd_module_t * 277d9638e54Smws fmd_api_module_lock(fmd_hdl_t *hdl) 278d9638e54Smws { 279d9638e54Smws fmd_module_t *mp = fmd_api_module(hdl); 280d9638e54Smws 2817c478bd9Sstevel@tonic-gate fmd_module_lock(mp); 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate if (mp->mod_info == NULL) { 2847c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_HDL_NOTREG, 2857c478bd9Sstevel@tonic-gate "client handle %p has not been registered\n", (void *)hdl); 2867c478bd9Sstevel@tonic-gate } 2877c478bd9Sstevel@tonic-gate 2887c478bd9Sstevel@tonic-gate return (mp); 2897c478bd9Sstevel@tonic-gate } 2907c478bd9Sstevel@tonic-gate 2917c478bd9Sstevel@tonic-gate /* 2927c478bd9Sstevel@tonic-gate * Utility function for API entry points that accept fmd_case_t's. We cast cp 2937c478bd9Sstevel@tonic-gate * to fmd_case_impl_t and check to make sure the case is owned by the caller. 2947c478bd9Sstevel@tonic-gate */ 2957c478bd9Sstevel@tonic-gate static fmd_case_impl_t * 2967c478bd9Sstevel@tonic-gate fmd_api_case_impl(fmd_module_t *mp, fmd_case_t *cp) 2977c478bd9Sstevel@tonic-gate { 2987c478bd9Sstevel@tonic-gate fmd_case_impl_t *cip = (fmd_case_impl_t *)cp; 2997c478bd9Sstevel@tonic-gate 3007c478bd9Sstevel@tonic-gate if (cip == NULL || cip->ci_mod != mp) { 3017c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_CASE_OWNER, 302d9638e54Smws "case %p is invalid or not owned by caller\n", (void *)cip); 3037c478bd9Sstevel@tonic-gate } 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate return (cip); 3067c478bd9Sstevel@tonic-gate } 3077c478bd9Sstevel@tonic-gate 3087c478bd9Sstevel@tonic-gate /* 309d9638e54Smws * Utility function for API entry points that accept fmd_xprt_t's. We cast xp 310d9638e54Smws * to fmd_transport_t and check to make sure the case is owned by the caller. 311d9638e54Smws * Note that we could make this check safer by actually walking mp's transport 312d9638e54Smws * list, but that requires holding the module lock and this routine needs to be 313d9638e54Smws * MT-hot w.r.t. auxiliary module threads. Ultimately any loadable module can 314d9638e54Smws * cause us to crash anyway, so we optimize for scalability over safety here. 315d9638e54Smws */ 316d9638e54Smws static fmd_xprt_impl_t * 317d9638e54Smws fmd_api_transport_impl(fmd_hdl_t *hdl, fmd_xprt_t *xp) 318d9638e54Smws { 319d9638e54Smws fmd_module_t *mp = fmd_api_module(hdl); 320d9638e54Smws fmd_xprt_impl_t *xip = (fmd_xprt_impl_t *)xp; 321d9638e54Smws 322d9638e54Smws if (xip == NULL || xip->xi_queue->eq_mod != mp) { 323d9638e54Smws fmd_api_error(mp, EFMD_XPRT_OWNER, 324d9638e54Smws "xprt %p is invalid or not owned by caller\n", (void *)xp); 325d9638e54Smws } 326d9638e54Smws 327d9638e54Smws return (xip); 328d9638e54Smws } 329d9638e54Smws 330d9638e54Smws /* 3317c478bd9Sstevel@tonic-gate * fmd_hdl_register() is the one function which cannot use fmd_api_error() to 3327c478bd9Sstevel@tonic-gate * report errors, because that routine causes the module to abort. Failure to 3337c478bd9Sstevel@tonic-gate * register is instead handled by having fmd_hdl_register() return an error to 3347c478bd9Sstevel@tonic-gate * the _fmd_init() function and then detecting no registration when it returns. 3357c478bd9Sstevel@tonic-gate * So we use this routine for fmd_hdl_register() error paths instead. 3367c478bd9Sstevel@tonic-gate */ 3377c478bd9Sstevel@tonic-gate static int 3387c478bd9Sstevel@tonic-gate fmd_hdl_register_error(fmd_module_t *mp, int err) 3397c478bd9Sstevel@tonic-gate { 3407c478bd9Sstevel@tonic-gate if (fmd_module_locked(mp)) 3417c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate fmd_api_xerror(mp, err, "failed to register"); 3447c478bd9Sstevel@tonic-gate return (fmd_set_errno(err)); 3457c478bd9Sstevel@tonic-gate } 3467c478bd9Sstevel@tonic-gate 3477c478bd9Sstevel@tonic-gate static void 3487c478bd9Sstevel@tonic-gate fmd_hdl_nop(void) 3497c478bd9Sstevel@tonic-gate { 3507c478bd9Sstevel@tonic-gate /* empty function for use with unspecified module entry points */ 3517c478bd9Sstevel@tonic-gate } 3527c478bd9Sstevel@tonic-gate 3537c478bd9Sstevel@tonic-gate int 3547c478bd9Sstevel@tonic-gate fmd_hdl_register(fmd_hdl_t *hdl, int version, const fmd_hdl_info_t *mip) 3557c478bd9Sstevel@tonic-gate { 3567c478bd9Sstevel@tonic-gate fmd_thread_t *tp = pthread_getspecific(fmd.d_key); 3577c478bd9Sstevel@tonic-gate fmd_module_t *mp = tp->thr_mod; 3587c478bd9Sstevel@tonic-gate 3597c478bd9Sstevel@tonic-gate const fmd_prop_t *prop; 3607c478bd9Sstevel@tonic-gate const fmd_conf_path_t *pap; 3617c478bd9Sstevel@tonic-gate fmd_conf_formal_t *cfp; 362d9638e54Smws fmd_hdl_ops_t ops; 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate const char *conf = NULL; 3657c478bd9Sstevel@tonic-gate char buf[PATH_MAX]; 3667c478bd9Sstevel@tonic-gate int i; 3677c478bd9Sstevel@tonic-gate 3687c478bd9Sstevel@tonic-gate if (mp != (fmd_module_t *)hdl) 3697c478bd9Sstevel@tonic-gate return (fmd_hdl_register_error(mp, EFMD_HDL_INVAL)); 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate fmd_module_lock(mp); 3727c478bd9Sstevel@tonic-gate 3737c478bd9Sstevel@tonic-gate /* 3747c478bd9Sstevel@tonic-gate * First perform some sanity checks on our input. The API version must 3757c478bd9Sstevel@tonic-gate * be supported by FMD and the handle can only be registered once by 3767c478bd9Sstevel@tonic-gate * the module thread to which we assigned this client handle. The info 3777c478bd9Sstevel@tonic-gate * provided for the handle must be valid and have the minimal settings. 3787c478bd9Sstevel@tonic-gate */ 379*f6e214c7SGavin Maltby if (version > FMD_API_VERSION_5) 3807c478bd9Sstevel@tonic-gate return (fmd_hdl_register_error(mp, EFMD_VER_NEW)); 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate if (version < FMD_API_VERSION_1) 3837c478bd9Sstevel@tonic-gate return (fmd_hdl_register_error(mp, EFMD_VER_OLD)); 3847c478bd9Sstevel@tonic-gate 3857c478bd9Sstevel@tonic-gate if (mp->mod_conf != NULL) 3867c478bd9Sstevel@tonic-gate return (fmd_hdl_register_error(mp, EFMD_HDL_REG)); 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate if (pthread_self() != mp->mod_thread->thr_tid) 3897c478bd9Sstevel@tonic-gate return (fmd_hdl_register_error(mp, EFMD_HDL_TID)); 3907c478bd9Sstevel@tonic-gate 391d9638e54Smws if (mip == NULL || mip->fmdi_desc == NULL || 392d9638e54Smws mip->fmdi_vers == NULL || mip->fmdi_ops == NULL) 3937c478bd9Sstevel@tonic-gate return (fmd_hdl_register_error(mp, EFMD_HDL_INFO)); 3947c478bd9Sstevel@tonic-gate 3957c478bd9Sstevel@tonic-gate /* 396d9638e54Smws * Copy the module's ops vector into a local variable to account for 397d9638e54Smws * changes in the module ABI. Then if any of the optional entry points 398d9638e54Smws * are NULL, set them to nop so we don't have to check before calling. 399d9638e54Smws */ 400d9638e54Smws bzero(&ops, sizeof (ops)); 401d9638e54Smws 402d9638e54Smws if (version < FMD_API_VERSION_3) 40324db4641Seschrock bcopy(mip->fmdi_ops, &ops, offsetof(fmd_hdl_ops_t, fmdo_send)); 40424db4641Seschrock else if (version < FMD_API_VERSION_4) 40524db4641Seschrock bcopy(mip->fmdi_ops, &ops, 40624db4641Seschrock offsetof(fmd_hdl_ops_t, fmdo_topo)); 407d9638e54Smws else 408d9638e54Smws bcopy(mip->fmdi_ops, &ops, sizeof (ops)); 409d9638e54Smws 410d9638e54Smws if (ops.fmdo_recv == NULL) 411d9638e54Smws ops.fmdo_recv = (void (*)())fmd_hdl_nop; 412d9638e54Smws if (ops.fmdo_timeout == NULL) 413d9638e54Smws ops.fmdo_timeout = (void (*)())fmd_hdl_nop; 414d9638e54Smws if (ops.fmdo_close == NULL) 415d9638e54Smws ops.fmdo_close = (void (*)())fmd_hdl_nop; 416d9638e54Smws if (ops.fmdo_stats == NULL) 417d9638e54Smws ops.fmdo_stats = (void (*)())fmd_hdl_nop; 418d9638e54Smws if (ops.fmdo_gc == NULL) 419d9638e54Smws ops.fmdo_gc = (void (*)())fmd_hdl_nop; 420d9638e54Smws if (ops.fmdo_send == NULL) 421d9638e54Smws ops.fmdo_send = (int (*)())fmd_hdl_nop; 42224db4641Seschrock if (ops.fmdo_topo == NULL) 42324db4641Seschrock ops.fmdo_topo = (void (*)())fmd_hdl_nop; 424d9638e54Smws 425d9638e54Smws /* 4267c478bd9Sstevel@tonic-gate * Make two passes through the property array to initialize the formals 4277c478bd9Sstevel@tonic-gate * to use for processing the module's .conf file. In the first pass, 4287c478bd9Sstevel@tonic-gate * we validate the types and count the number of properties. In the 4297c478bd9Sstevel@tonic-gate * second pass we copy the strings and fill in the appropriate ops. 4307c478bd9Sstevel@tonic-gate */ 4317c478bd9Sstevel@tonic-gate for (prop = mip->fmdi_props, i = 0; prop != NULL && 4327c478bd9Sstevel@tonic-gate prop->fmdp_name != NULL; prop++, i++) { 4337c478bd9Sstevel@tonic-gate if (prop->fmdp_type >= 4347c478bd9Sstevel@tonic-gate sizeof (_fmd_prop_ops) / sizeof (_fmd_prop_ops[0])) { 4357c478bd9Sstevel@tonic-gate fmd_api_xerror(mp, EFMD_HDL_PROP, 4367c478bd9Sstevel@tonic-gate "property %s uses invalid type %u\n", 4377c478bd9Sstevel@tonic-gate prop->fmdp_name, prop->fmdp_type); 4387c478bd9Sstevel@tonic-gate return (fmd_hdl_register_error(mp, EFMD_HDL_PROP)); 4397c478bd9Sstevel@tonic-gate } 4407c478bd9Sstevel@tonic-gate } 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate mp->mod_argc = i; 4437c478bd9Sstevel@tonic-gate mp->mod_argv = fmd_zalloc(sizeof (fmd_conf_formal_t) * i, FMD_SLEEP); 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate prop = mip->fmdi_props; 4467c478bd9Sstevel@tonic-gate cfp = mp->mod_argv; 4477c478bd9Sstevel@tonic-gate 4487c478bd9Sstevel@tonic-gate for (i = 0; i < mp->mod_argc; i++, prop++, cfp++) { 4497c478bd9Sstevel@tonic-gate cfp->cf_name = fmd_strdup(prop->fmdp_name, FMD_SLEEP); 4507c478bd9Sstevel@tonic-gate cfp->cf_ops = _fmd_prop_ops[prop->fmdp_type]; 4517c478bd9Sstevel@tonic-gate cfp->cf_default = fmd_strdup(prop->fmdp_defv, FMD_SLEEP); 4527c478bd9Sstevel@tonic-gate } 4537c478bd9Sstevel@tonic-gate 4547c478bd9Sstevel@tonic-gate /* 4557c478bd9Sstevel@tonic-gate * If this module came from an on-disk file, compute the name of the 4567c478bd9Sstevel@tonic-gate * corresponding .conf file and parse properties from it if it exists. 4577c478bd9Sstevel@tonic-gate */ 4587c478bd9Sstevel@tonic-gate if (mp->mod_path != NULL) { 4597c478bd9Sstevel@tonic-gate (void) strlcpy(buf, mp->mod_path, sizeof (buf)); 4607c478bd9Sstevel@tonic-gate (void) fmd_strdirname(buf); 4617c478bd9Sstevel@tonic-gate 4627c478bd9Sstevel@tonic-gate (void) strlcat(buf, "/", sizeof (buf)); 4637c478bd9Sstevel@tonic-gate (void) strlcat(buf, mp->mod_name, sizeof (buf)); 4647c478bd9Sstevel@tonic-gate (void) strlcat(buf, ".conf", sizeof (buf)); 4657c478bd9Sstevel@tonic-gate 4667c478bd9Sstevel@tonic-gate if (access(buf, F_OK) == 0) 4677c478bd9Sstevel@tonic-gate conf = buf; 4687c478bd9Sstevel@tonic-gate } 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate if ((mp->mod_conf = fmd_conf_open(conf, 471d9638e54Smws mp->mod_argc, mp->mod_argv, 0)) == NULL) 4727c478bd9Sstevel@tonic-gate return (fmd_hdl_register_error(mp, EFMD_MOD_CONF)); 4737c478bd9Sstevel@tonic-gate 474d9638e54Smws fmd_conf_propagate(fmd.d_conf, mp->mod_conf, mp->mod_name); 475d9638e54Smws 4767c478bd9Sstevel@tonic-gate /* 4777c478bd9Sstevel@tonic-gate * Look up the list of the libdiagcode dictionaries associated with the 4787c478bd9Sstevel@tonic-gate * module. If none were specified, use the value from daemon's config. 4797c478bd9Sstevel@tonic-gate * We only fail if the module specified an explicit dictionary. 4807c478bd9Sstevel@tonic-gate */ 4817c478bd9Sstevel@tonic-gate (void) fmd_conf_getprop(mp->mod_conf, FMD_PROP_DICTIONARIES, &pap); 4827c478bd9Sstevel@tonic-gate if (pap->cpa_argc == 0 && mp->mod_ops == &fmd_bltin_ops) 4837c478bd9Sstevel@tonic-gate (void) fmd_conf_getprop(fmd.d_conf, "self.dict", &pap); 4847c478bd9Sstevel@tonic-gate 4857c478bd9Sstevel@tonic-gate for (i = 0; i < pap->cpa_argc; i++) { 4867c478bd9Sstevel@tonic-gate if (fmd_module_dc_opendict(mp, pap->cpa_argv[i]) != 0) { 4877c478bd9Sstevel@tonic-gate fmd_api_xerror(mp, errno, 4887c478bd9Sstevel@tonic-gate "failed to open dictionary %s", pap->cpa_argv[i]); 4897c478bd9Sstevel@tonic-gate return (fmd_hdl_register_error(mp, EFMD_MOD_CONF)); 4907c478bd9Sstevel@tonic-gate } 4917c478bd9Sstevel@tonic-gate } 4927c478bd9Sstevel@tonic-gate 4937c478bd9Sstevel@tonic-gate /* 4947c478bd9Sstevel@tonic-gate * Make a copy of the handle information and store it in mod_info. We 4957c478bd9Sstevel@tonic-gate * do not need to bother copying fmdi_props since they're already read. 4967c478bd9Sstevel@tonic-gate */ 4977c478bd9Sstevel@tonic-gate mp->mod_info = fmd_alloc(sizeof (fmd_hdl_info_t), FMD_SLEEP); 4987c478bd9Sstevel@tonic-gate mp->mod_info->fmdi_desc = fmd_strdup(mip->fmdi_desc, FMD_SLEEP); 4997c478bd9Sstevel@tonic-gate mp->mod_info->fmdi_vers = fmd_strdup(mip->fmdi_vers, FMD_SLEEP); 5007c478bd9Sstevel@tonic-gate mp->mod_info->fmdi_ops = fmd_alloc(sizeof (fmd_hdl_ops_t), FMD_SLEEP); 501d9638e54Smws bcopy(&ops, (void *)mp->mod_info->fmdi_ops, sizeof (fmd_hdl_ops_t)); 5027c478bd9Sstevel@tonic-gate mp->mod_info->fmdi_props = NULL; 5037c478bd9Sstevel@tonic-gate 5047c478bd9Sstevel@tonic-gate /* 50519e1255fScy152378 * Store a copy of module version in mp for fmd_scheme_fmd_present() 50619e1255fScy152378 */ 50719e1255fScy152378 if (mp->mod_vers == NULL) 50819e1255fScy152378 mp->mod_vers = fmd_strdup(mip->fmdi_vers, FMD_SLEEP); 50919e1255fScy152378 51019e1255fScy152378 /* 5117c478bd9Sstevel@tonic-gate * Allocate an FMRI representing this module. We'll use this later 5127c478bd9Sstevel@tonic-gate * if the module decides to publish any events (e.g. list.suspects). 5137c478bd9Sstevel@tonic-gate */ 5147c478bd9Sstevel@tonic-gate mp->mod_fmri = fmd_protocol_fmri_module(mp); 5157c478bd9Sstevel@tonic-gate 5167c478bd9Sstevel@tonic-gate /* 5177c478bd9Sstevel@tonic-gate * Any subscriptions specified in the conf file are now stored in the 5187c478bd9Sstevel@tonic-gate * corresponding property. Add all of these to the dispatch queue. 5197c478bd9Sstevel@tonic-gate */ 5207c478bd9Sstevel@tonic-gate (void) fmd_conf_getprop(mp->mod_conf, FMD_PROP_SUBSCRIPTIONS, &pap); 5217c478bd9Sstevel@tonic-gate 522d9638e54Smws for (i = 0; i < pap->cpa_argc; i++) { 523d9638e54Smws fmd_dispq_insert(fmd.d_disp, mp->mod_queue, pap->cpa_argv[i]); 524d9638e54Smws fmd_xprt_subscribe_all(pap->cpa_argv[i]); 525d9638e54Smws } 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate /* 5287c478bd9Sstevel@tonic-gate * Unlock the module and restore any pre-existing module checkpoint. 5297c478bd9Sstevel@tonic-gate * If the checkpoint is missing or corrupt, we just keep going. 5307c478bd9Sstevel@tonic-gate */ 5317c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 5327c478bd9Sstevel@tonic-gate fmd_ckpt_restore(mp); 5337c478bd9Sstevel@tonic-gate return (0); 5347c478bd9Sstevel@tonic-gate } 5357c478bd9Sstevel@tonic-gate 536d9638e54Smws /* 537d9638e54Smws * If an auxiliary thread exists for the specified module at unregistration 538d9638e54Smws * time, send it an asynchronous cancellation to force it to exit and then 539d9638e54Smws * join with it (we expect this to either succeed quickly or return ESRCH). 540d9638e54Smws * Once this is complete we can destroy the associated fmd_thread_t data. 541d9638e54Smws */ 542d9638e54Smws static void 543d9638e54Smws fmd_module_thrcancel(fmd_idspace_t *ids, id_t id, fmd_module_t *mp) 544d9638e54Smws { 545d9638e54Smws fmd_thread_t *tp = fmd_idspace_getspecific(ids, id); 546d9638e54Smws 547*f6e214c7SGavin Maltby /* 548*f6e214c7SGavin Maltby * Door service threads are not cancellable (worse - if they're 549*f6e214c7SGavin Maltby * waiting in door_return then that is interrupted, but they then spin 550*f6e214c7SGavin Maltby * endlessly!). Non-private door service threads are not tracked 551*f6e214c7SGavin Maltby * in the module thread idspace so it's only private server threads 552*f6e214c7SGavin Maltby * created via fmd_doorthr_create that we'll encounter. In most 553*f6e214c7SGavin Maltby * cases the module _fini should have tidied up (e.g., calling 554*f6e214c7SGavin Maltby * sysevent_evc_unbind which will cleanup door threads if 555*f6e214c7SGavin Maltby * sysevent_evc_xsubscribe was used). One case that does not 556*f6e214c7SGavin Maltby * clean up is sysev_fini which explicitly does not unbind the 557*f6e214c7SGavin Maltby * channel, so we must skip any remaining door threads here. 558*f6e214c7SGavin Maltby */ 559*f6e214c7SGavin Maltby if (tp->thr_isdoor) { 560*f6e214c7SGavin Maltby fmd_dprintf(FMD_DBG_MOD, "not cancelling %s private door " 561*f6e214c7SGavin Maltby "thread %u\n", mp->mod_name, tp->thr_tid); 562*f6e214c7SGavin Maltby fmd_thread_destroy(tp, FMD_THREAD_NOJOIN); 563*f6e214c7SGavin Maltby return; 564*f6e214c7SGavin Maltby } 565*f6e214c7SGavin Maltby 566d9638e54Smws fmd_dprintf(FMD_DBG_MOD, "cancelling %s auxiliary thread %u\n", 567d9638e54Smws mp->mod_name, tp->thr_tid); 568d9638e54Smws 569d9638e54Smws ASSERT(tp->thr_tid == id); 570d9638e54Smws (void) pthread_cancel(tp->thr_tid); 571d9638e54Smws (void) pthread_join(tp->thr_tid, NULL); 572d9638e54Smws 573d9638e54Smws fmd_thread_destroy(tp, FMD_THREAD_NOJOIN); 574d9638e54Smws } 575d9638e54Smws 5767c478bd9Sstevel@tonic-gate void 5777c478bd9Sstevel@tonic-gate fmd_module_unregister(fmd_module_t *mp) 5787c478bd9Sstevel@tonic-gate { 5797c478bd9Sstevel@tonic-gate fmd_conf_formal_t *cfp = mp->mod_argv; 5807c478bd9Sstevel@tonic-gate const fmd_conf_path_t *pap; 581d9638e54Smws fmd_case_t *cp; 582d9638e54Smws fmd_xprt_t *xp; 5837c478bd9Sstevel@tonic-gate int i; 5847c478bd9Sstevel@tonic-gate 5857c478bd9Sstevel@tonic-gate TRACE((FMD_DBG_MOD, "unregister %p (%s)", (void *)mp, mp->mod_name)); 5867c478bd9Sstevel@tonic-gate ASSERT(fmd_module_locked(mp)); 5877c478bd9Sstevel@tonic-gate 588d9638e54Smws /* 589d9638e54Smws * If any transports are still open, they have send threads that are 590d9638e54Smws * using the module handle: shut them down and join with these threads. 591d9638e54Smws */ 592d9638e54Smws while ((xp = fmd_list_next(&mp->mod_transports)) != NULL) 593d9638e54Smws fmd_xprt_destroy(xp); 594d9638e54Smws 595d9638e54Smws /* 596d9638e54Smws * If any auxiliary threads exist, they may be using our module handle, 597d9638e54Smws * and therefore could cause a fault as soon as we start destroying it. 598d9638e54Smws * Module writers should clean up any threads before unregistering: we 599d9638e54Smws * forcibly cancel any remaining auxiliary threads before proceeding. 600d9638e54Smws */ 601d9638e54Smws fmd_idspace_apply(mp->mod_threads, 602d9638e54Smws (void (*)())fmd_module_thrcancel, mp); 603d9638e54Smws 60433129b33Sayznaga if (mp->mod_error == 0) 60533129b33Sayznaga fmd_ckpt_save(mp); /* take one more checkpoint if needed */ 60633129b33Sayznaga 607d9638e54Smws /* 608d9638e54Smws * Delete any cases associated with the module (UNSOLVED, SOLVED, or 609d9638e54Smws * CLOSE_WAIT) as if fmdo_close() has finished processing them. 610d9638e54Smws */ 611d9638e54Smws while ((cp = fmd_list_next(&mp->mod_cases)) != NULL) 612d9638e54Smws fmd_case_delete(cp); 613d9638e54Smws 614d9638e54Smws fmd_ustat_delete_references(mp->mod_ustat); 6157c478bd9Sstevel@tonic-gate (void) fmd_conf_getprop(mp->mod_conf, FMD_PROP_SUBSCRIPTIONS, &pap); 6167c478bd9Sstevel@tonic-gate 617d9638e54Smws for (i = 0; i < pap->cpa_argc; i++) { 618d9638e54Smws fmd_xprt_unsubscribe_all(pap->cpa_argv[i]); 619d9638e54Smws fmd_dispq_delete(fmd.d_disp, mp->mod_queue, pap->cpa_argv[i]); 6207c478bd9Sstevel@tonic-gate } 6217c478bd9Sstevel@tonic-gate 6227c478bd9Sstevel@tonic-gate fmd_conf_close(mp->mod_conf); 6237c478bd9Sstevel@tonic-gate mp->mod_conf = NULL; 6247c478bd9Sstevel@tonic-gate 6257c478bd9Sstevel@tonic-gate for (i = 0; i < mp->mod_argc; i++, cfp++) { 6267c478bd9Sstevel@tonic-gate fmd_strfree((char *)cfp->cf_name); 6277c478bd9Sstevel@tonic-gate fmd_strfree((char *)cfp->cf_default); 6287c478bd9Sstevel@tonic-gate } 6297c478bd9Sstevel@tonic-gate 6307c478bd9Sstevel@tonic-gate fmd_free(mp->mod_argv, sizeof (fmd_conf_formal_t) * mp->mod_argc); 6317c478bd9Sstevel@tonic-gate mp->mod_argv = NULL; 6327c478bd9Sstevel@tonic-gate mp->mod_argc = 0; 6337c478bd9Sstevel@tonic-gate 6347c478bd9Sstevel@tonic-gate nvlist_free(mp->mod_fmri); 6357c478bd9Sstevel@tonic-gate mp->mod_fmri = NULL; 6367c478bd9Sstevel@tonic-gate 6377c478bd9Sstevel@tonic-gate fmd_strfree((char *)mp->mod_info->fmdi_desc); 6387c478bd9Sstevel@tonic-gate fmd_strfree((char *)mp->mod_info->fmdi_vers); 6397c478bd9Sstevel@tonic-gate fmd_free((void *)mp->mod_info->fmdi_ops, sizeof (fmd_hdl_ops_t)); 6407c478bd9Sstevel@tonic-gate fmd_free(mp->mod_info, sizeof (fmd_hdl_info_t)); 6417c478bd9Sstevel@tonic-gate mp->mod_info = NULL; 6427c478bd9Sstevel@tonic-gate 6437c478bd9Sstevel@tonic-gate fmd_eventq_abort(mp->mod_queue); 6447c478bd9Sstevel@tonic-gate } 6457c478bd9Sstevel@tonic-gate 6467c478bd9Sstevel@tonic-gate void 6477c478bd9Sstevel@tonic-gate fmd_hdl_unregister(fmd_hdl_t *hdl) 6487c478bd9Sstevel@tonic-gate { 6497c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 6507c478bd9Sstevel@tonic-gate fmd_module_unregister(mp); 6517c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 6527c478bd9Sstevel@tonic-gate } 6537c478bd9Sstevel@tonic-gate 6547c478bd9Sstevel@tonic-gate void 6557c478bd9Sstevel@tonic-gate fmd_hdl_subscribe(fmd_hdl_t *hdl, const char *class) 6567c478bd9Sstevel@tonic-gate { 6577c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 6587c478bd9Sstevel@tonic-gate 659d9638e54Smws if (fmd_conf_setprop(mp->mod_conf, 660d9638e54Smws FMD_PROP_SUBSCRIPTIONS, class) == 0) { 661d9638e54Smws fmd_dispq_insert(fmd.d_disp, mp->mod_queue, class); 662d9638e54Smws fmd_xprt_subscribe_all(class); 663d9638e54Smws } 6647c478bd9Sstevel@tonic-gate 6657c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 6667c478bd9Sstevel@tonic-gate } 6677c478bd9Sstevel@tonic-gate 668d9638e54Smws 6697c478bd9Sstevel@tonic-gate void 6707c478bd9Sstevel@tonic-gate fmd_hdl_unsubscribe(fmd_hdl_t *hdl, const char *class) 6717c478bd9Sstevel@tonic-gate { 6727c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 6737c478bd9Sstevel@tonic-gate 674d9638e54Smws if (fmd_conf_delprop(mp->mod_conf, 675d9638e54Smws FMD_PROP_SUBSCRIPTIONS, class) == 0) { 676d9638e54Smws fmd_xprt_unsubscribe_all(class); 677d9638e54Smws fmd_dispq_delete(fmd.d_disp, mp->mod_queue, class); 678d9638e54Smws } 6797c478bd9Sstevel@tonic-gate 6807c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 6817c478bd9Sstevel@tonic-gate fmd_eventq_cancel(mp->mod_queue, FMD_EVT_PROTOCOL, (void *)class); 6827c478bd9Sstevel@tonic-gate } 6837c478bd9Sstevel@tonic-gate 6847c478bd9Sstevel@tonic-gate void 6857c478bd9Sstevel@tonic-gate fmd_hdl_setspecific(fmd_hdl_t *hdl, void *spec) 6867c478bd9Sstevel@tonic-gate { 6877c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 6887c478bd9Sstevel@tonic-gate 6897c478bd9Sstevel@tonic-gate mp->mod_spec = spec; 6907c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 6917c478bd9Sstevel@tonic-gate } 6927c478bd9Sstevel@tonic-gate 6937c478bd9Sstevel@tonic-gate void * 6947c478bd9Sstevel@tonic-gate fmd_hdl_getspecific(fmd_hdl_t *hdl) 6957c478bd9Sstevel@tonic-gate { 6967c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 6977c478bd9Sstevel@tonic-gate void *spec = mp->mod_spec; 6987c478bd9Sstevel@tonic-gate 6997c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 7007c478bd9Sstevel@tonic-gate return (spec); 7017c478bd9Sstevel@tonic-gate } 7027c478bd9Sstevel@tonic-gate 7037c478bd9Sstevel@tonic-gate void 7047c478bd9Sstevel@tonic-gate fmd_hdl_opendict(fmd_hdl_t *hdl, const char *dict) 7057c478bd9Sstevel@tonic-gate { 7067c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 7077c478bd9Sstevel@tonic-gate const fmd_conf_path_t *pap; 7087c478bd9Sstevel@tonic-gate int i; 7097c478bd9Sstevel@tonic-gate 7107c478bd9Sstevel@tonic-gate /* 7117c478bd9Sstevel@tonic-gate * Update the dictionary property in order to preserve the list of 7127c478bd9Sstevel@tonic-gate * pathnames and expand any % tokens in the path. Then retrieve the 7137c478bd9Sstevel@tonic-gate * new dictionary names from cpa_argv[] and open them one at a time. 7147c478bd9Sstevel@tonic-gate */ 7157c478bd9Sstevel@tonic-gate (void) fmd_conf_setprop(mp->mod_conf, FMD_PROP_DICTIONARIES, dict); 7167c478bd9Sstevel@tonic-gate (void) fmd_conf_getprop(mp->mod_conf, FMD_PROP_DICTIONARIES, &pap); 7177c478bd9Sstevel@tonic-gate 7187c478bd9Sstevel@tonic-gate ASSERT(pap->cpa_argc > mp->mod_dictc); 7197c478bd9Sstevel@tonic-gate 7207c478bd9Sstevel@tonic-gate for (i = mp->mod_dictc; i < pap->cpa_argc; i++) { 7217c478bd9Sstevel@tonic-gate if (fmd_module_dc_opendict(mp, pap->cpa_argv[i]) != 0) { 7227c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_MOD_DICT, 7237c478bd9Sstevel@tonic-gate "failed to open dictionary %s for module %s", 7247c478bd9Sstevel@tonic-gate pap->cpa_argv[i], mp->mod_name); 7257c478bd9Sstevel@tonic-gate } 7267c478bd9Sstevel@tonic-gate } 7277c478bd9Sstevel@tonic-gate 7287c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 7297c478bd9Sstevel@tonic-gate } 7307c478bd9Sstevel@tonic-gate 7317aec1d6eScindi topo_hdl_t * 73224db4641Seschrock fmd_hdl_topo_hold(fmd_hdl_t *hdl, int v) 7337aec1d6eScindi { 7347aec1d6eScindi fmd_module_t *mp = fmd_api_module_lock(hdl); 7357aec1d6eScindi topo_hdl_t *thp; 7367aec1d6eScindi 7377aec1d6eScindi if (v != TOPO_VERSION) { 7387aec1d6eScindi fmd_api_error(mp, EFMD_MOD_TOPO, "libtopo version mismatch: " 7397aec1d6eScindi "fmd version %d != client version %d\n", TOPO_VERSION, v); 7407aec1d6eScindi } 7417aec1d6eScindi 74224db4641Seschrock thp = fmd_module_topo_hold(mp); 74324db4641Seschrock ASSERT(thp != NULL); 7440eb822a1Scindi 7457aec1d6eScindi fmd_module_unlock(mp); 7467aec1d6eScindi return (thp); 7477aec1d6eScindi } 7487aec1d6eScindi 74924db4641Seschrock void 75024db4641Seschrock fmd_hdl_topo_rele(fmd_hdl_t *hdl, topo_hdl_t *thp) 75124db4641Seschrock { 75224db4641Seschrock fmd_module_t *mp = fmd_api_module_lock(hdl); 75324db4641Seschrock 75424db4641Seschrock if (fmd_module_topo_rele(mp, thp) != 0) 75524db4641Seschrock fmd_api_error(mp, EFMD_MOD_TOPO, "failed to release invalid " 75624db4641Seschrock "topo handle: %p\n", (void *)thp); 75724db4641Seschrock 75824db4641Seschrock fmd_module_unlock(mp); 75924db4641Seschrock } 76024db4641Seschrock 7619af3851aSeschrock static void * 7629af3851aSeschrock fmd_hdl_alloc_locked(fmd_module_t *mp, size_t size, int flags) 7637c478bd9Sstevel@tonic-gate { 7647c478bd9Sstevel@tonic-gate void *data; 7657c478bd9Sstevel@tonic-gate 7667c478bd9Sstevel@tonic-gate if (mp->mod_stats->ms_memlimit.fmds_value.ui64 - 7677c478bd9Sstevel@tonic-gate mp->mod_stats->ms_memtotal.fmds_value.ui64 < size) { 7687c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_HDL_NOMEM, "%s's allocation of %lu " 7697c478bd9Sstevel@tonic-gate "bytes exceeds module memory limit (%llu)\n", 7707c478bd9Sstevel@tonic-gate mp->mod_name, (ulong_t)size, (u_longlong_t) 7717c478bd9Sstevel@tonic-gate mp->mod_stats->ms_memtotal.fmds_value.ui64); 7727c478bd9Sstevel@tonic-gate } 7737c478bd9Sstevel@tonic-gate 7747c478bd9Sstevel@tonic-gate if ((data = fmd_alloc(size, flags)) != NULL) 7757c478bd9Sstevel@tonic-gate mp->mod_stats->ms_memtotal.fmds_value.ui64 += size; 7767c478bd9Sstevel@tonic-gate 7779af3851aSeschrock return (data); 7789af3851aSeschrock } 7799af3851aSeschrock 7809af3851aSeschrock void * 7819af3851aSeschrock fmd_hdl_alloc(fmd_hdl_t *hdl, size_t size, int flags) 7829af3851aSeschrock { 7839af3851aSeschrock fmd_module_t *mp = fmd_api_module_lock(hdl); 7849af3851aSeschrock void *data; 7859af3851aSeschrock 7869af3851aSeschrock data = fmd_hdl_alloc_locked(mp, size, flags); 7879af3851aSeschrock 7887c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 7897c478bd9Sstevel@tonic-gate return (data); 7907c478bd9Sstevel@tonic-gate } 7917c478bd9Sstevel@tonic-gate 7927c478bd9Sstevel@tonic-gate void * 7937c478bd9Sstevel@tonic-gate fmd_hdl_zalloc(fmd_hdl_t *hdl, size_t size, int flags) 7947c478bd9Sstevel@tonic-gate { 7957c478bd9Sstevel@tonic-gate void *data = fmd_hdl_alloc(hdl, size, flags); 7967c478bd9Sstevel@tonic-gate 7977c478bd9Sstevel@tonic-gate if (data != NULL) 7987c478bd9Sstevel@tonic-gate bzero(data, size); 7997c478bd9Sstevel@tonic-gate 8007c478bd9Sstevel@tonic-gate return (data); 8017c478bd9Sstevel@tonic-gate } 8027c478bd9Sstevel@tonic-gate 8039af3851aSeschrock static void 8049af3851aSeschrock fmd_hdl_free_locked(fmd_module_t *mp, void *data, size_t size) 8059af3851aSeschrock { 8069af3851aSeschrock fmd_free(data, size); 8079af3851aSeschrock mp->mod_stats->ms_memtotal.fmds_value.ui64 -= size; 8089af3851aSeschrock } 8099af3851aSeschrock 8107c478bd9Sstevel@tonic-gate void 8117c478bd9Sstevel@tonic-gate fmd_hdl_free(fmd_hdl_t *hdl, void *data, size_t size) 8127c478bd9Sstevel@tonic-gate { 8137c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 8147c478bd9Sstevel@tonic-gate 8159af3851aSeschrock fmd_hdl_free_locked(mp, data, size); 8167c478bd9Sstevel@tonic-gate 8177c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 8187c478bd9Sstevel@tonic-gate } 8197c478bd9Sstevel@tonic-gate 8207c478bd9Sstevel@tonic-gate char * 8217c478bd9Sstevel@tonic-gate fmd_hdl_strdup(fmd_hdl_t *hdl, const char *s, int flags) 8227c478bd9Sstevel@tonic-gate { 8237c478bd9Sstevel@tonic-gate char *p; 8247c478bd9Sstevel@tonic-gate 8257c478bd9Sstevel@tonic-gate if (s != NULL) 8267c478bd9Sstevel@tonic-gate p = fmd_hdl_alloc(hdl, strlen(s) + 1, flags); 8277c478bd9Sstevel@tonic-gate else 8287c478bd9Sstevel@tonic-gate p = NULL; 8297c478bd9Sstevel@tonic-gate 8307c478bd9Sstevel@tonic-gate if (p != NULL) 8317c478bd9Sstevel@tonic-gate (void) strcpy(p, s); 8327c478bd9Sstevel@tonic-gate 8337c478bd9Sstevel@tonic-gate return (p); 8347c478bd9Sstevel@tonic-gate } 8357c478bd9Sstevel@tonic-gate 8367c478bd9Sstevel@tonic-gate void 8377c478bd9Sstevel@tonic-gate fmd_hdl_strfree(fmd_hdl_t *hdl, char *s) 8387c478bd9Sstevel@tonic-gate { 8397c478bd9Sstevel@tonic-gate if (s != NULL) 8407c478bd9Sstevel@tonic-gate fmd_hdl_free(hdl, s, strlen(s) + 1); 8417c478bd9Sstevel@tonic-gate } 8427c478bd9Sstevel@tonic-gate 8437c478bd9Sstevel@tonic-gate void 8447c478bd9Sstevel@tonic-gate fmd_hdl_vabort(fmd_hdl_t *hdl, const char *format, va_list ap) 8457c478bd9Sstevel@tonic-gate { 8467c478bd9Sstevel@tonic-gate fmd_api_verror(fmd_api_module_lock(hdl), EFMD_HDL_ABORT, format, ap); 8477c478bd9Sstevel@tonic-gate } 8487c478bd9Sstevel@tonic-gate 8497c478bd9Sstevel@tonic-gate /*PRINTFLIKE2*/ 8507c478bd9Sstevel@tonic-gate void 8517c478bd9Sstevel@tonic-gate fmd_hdl_abort(fmd_hdl_t *hdl, const char *format, ...) 8527c478bd9Sstevel@tonic-gate { 8537c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 8547c478bd9Sstevel@tonic-gate va_list ap; 8557c478bd9Sstevel@tonic-gate 8567c478bd9Sstevel@tonic-gate va_start(ap, format); 8577c478bd9Sstevel@tonic-gate fmd_api_verror(mp, EFMD_HDL_ABORT, format, ap); 8587c478bd9Sstevel@tonic-gate va_end(ap); 8597c478bd9Sstevel@tonic-gate } 8607c478bd9Sstevel@tonic-gate 8617c478bd9Sstevel@tonic-gate void 8627c478bd9Sstevel@tonic-gate fmd_hdl_verror(fmd_hdl_t *hdl, const char *format, va_list ap) 8637c478bd9Sstevel@tonic-gate { 8647c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 8657c478bd9Sstevel@tonic-gate fmd_api_vxerror(mp, errno, format, ap); 8667c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 8677c478bd9Sstevel@tonic-gate } 8687c478bd9Sstevel@tonic-gate 8697c478bd9Sstevel@tonic-gate /*PRINTFLIKE2*/ 8707c478bd9Sstevel@tonic-gate void 8717c478bd9Sstevel@tonic-gate fmd_hdl_error(fmd_hdl_t *hdl, const char *format, ...) 8727c478bd9Sstevel@tonic-gate { 8737c478bd9Sstevel@tonic-gate va_list ap; 8747c478bd9Sstevel@tonic-gate 8757c478bd9Sstevel@tonic-gate va_start(ap, format); 8767c478bd9Sstevel@tonic-gate fmd_hdl_verror(hdl, format, ap); 8777c478bd9Sstevel@tonic-gate va_end(ap); 8787c478bd9Sstevel@tonic-gate } 8797c478bd9Sstevel@tonic-gate 8807c478bd9Sstevel@tonic-gate void 8817c478bd9Sstevel@tonic-gate fmd_hdl_vdebug(fmd_hdl_t *hdl, const char *format, va_list ap) 8827c478bd9Sstevel@tonic-gate { 8837c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 8847c478bd9Sstevel@tonic-gate 8857c478bd9Sstevel@tonic-gate char *msg; 8867c478bd9Sstevel@tonic-gate size_t len; 8877c478bd9Sstevel@tonic-gate char c; 8887c478bd9Sstevel@tonic-gate 8897c478bd9Sstevel@tonic-gate if (!(fmd.d_hdl_debug)) { 8907c478bd9Sstevel@tonic-gate mp->mod_stats->ms_debugdrop.fmds_value.ui64++; 8917c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 8927c478bd9Sstevel@tonic-gate return; 8937c478bd9Sstevel@tonic-gate } 8947c478bd9Sstevel@tonic-gate 8957c478bd9Sstevel@tonic-gate len = vsnprintf(&c, 1, format, ap); 8967c478bd9Sstevel@tonic-gate 8977c478bd9Sstevel@tonic-gate if ((msg = fmd_alloc(len + 2, FMD_NOSLEEP)) == NULL) { 8987c478bd9Sstevel@tonic-gate mp->mod_stats->ms_debugdrop.fmds_value.ui64++; 8997c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 9007c478bd9Sstevel@tonic-gate return; 9017c478bd9Sstevel@tonic-gate } 9027c478bd9Sstevel@tonic-gate 9037c478bd9Sstevel@tonic-gate (void) vsnprintf(msg, len + 1, format, ap); 9047c478bd9Sstevel@tonic-gate 9057c478bd9Sstevel@tonic-gate if (msg[len - 1] != '\n') 9067c478bd9Sstevel@tonic-gate (void) strcpy(&msg[len], "\n"); 9077c478bd9Sstevel@tonic-gate 9087c478bd9Sstevel@tonic-gate if (fmd.d_hdl_dbout & FMD_DBOUT_STDERR) { 9097c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&fmd.d_err_lock); 9107c478bd9Sstevel@tonic-gate (void) fprintf(stderr, "%s DEBUG: %s: %s", 9117c478bd9Sstevel@tonic-gate fmd.d_pname, mp->mod_name, msg); 9127c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&fmd.d_err_lock); 9137c478bd9Sstevel@tonic-gate } 9147c478bd9Sstevel@tonic-gate 9157c478bd9Sstevel@tonic-gate if (fmd.d_hdl_dbout & FMD_DBOUT_SYSLOG) { 9167c478bd9Sstevel@tonic-gate syslog(LOG_DEBUG | LOG_DAEMON, "%s DEBUG: %s: %s", 9177c478bd9Sstevel@tonic-gate fmd.d_pname, mp->mod_name, msg); 9187c478bd9Sstevel@tonic-gate } 9197c478bd9Sstevel@tonic-gate 9207c478bd9Sstevel@tonic-gate fmd_free(msg, len + 2); 9217c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 9227c478bd9Sstevel@tonic-gate } 9237c478bd9Sstevel@tonic-gate 9247c478bd9Sstevel@tonic-gate /*PRINTFLIKE2*/ 9257c478bd9Sstevel@tonic-gate void 9267c478bd9Sstevel@tonic-gate fmd_hdl_debug(fmd_hdl_t *hdl, const char *format, ...) 9277c478bd9Sstevel@tonic-gate { 9287c478bd9Sstevel@tonic-gate va_list ap; 9297c478bd9Sstevel@tonic-gate 9307c478bd9Sstevel@tonic-gate va_start(ap, format); 9317c478bd9Sstevel@tonic-gate fmd_hdl_vdebug(hdl, format, ap); 9327c478bd9Sstevel@tonic-gate va_end(ap); 9337c478bd9Sstevel@tonic-gate } 9347c478bd9Sstevel@tonic-gate 9357c478bd9Sstevel@tonic-gate int32_t 9367c478bd9Sstevel@tonic-gate fmd_prop_get_int32(fmd_hdl_t *hdl, const char *name) 9377c478bd9Sstevel@tonic-gate { 9387c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 9397c478bd9Sstevel@tonic-gate const fmd_conf_ops_t *ops = fmd_conf_gettype(mp->mod_conf, name); 9407c478bd9Sstevel@tonic-gate int32_t value = 0; 9417c478bd9Sstevel@tonic-gate 9427c478bd9Sstevel@tonic-gate if (ops == &fmd_conf_bool || ops == &fmd_conf_int32 || 9437c478bd9Sstevel@tonic-gate ops == &fmd_conf_uint32) 9447c478bd9Sstevel@tonic-gate (void) fmd_conf_getprop(mp->mod_conf, name, &value); 9457c478bd9Sstevel@tonic-gate else if (ops != NULL) { 9467c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_PROP_TYPE, 9477c478bd9Sstevel@tonic-gate "property %s is not of int32 type\n", name); 9487c478bd9Sstevel@tonic-gate } else { 9497c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_PROP_DEFN, 9507c478bd9Sstevel@tonic-gate "property %s is not defined\n", name); 9517c478bd9Sstevel@tonic-gate } 9527c478bd9Sstevel@tonic-gate 9537c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 9547c478bd9Sstevel@tonic-gate return (value); 9557c478bd9Sstevel@tonic-gate } 9567c478bd9Sstevel@tonic-gate 9577c478bd9Sstevel@tonic-gate int64_t 9587c478bd9Sstevel@tonic-gate fmd_prop_get_int64(fmd_hdl_t *hdl, const char *name) 9597c478bd9Sstevel@tonic-gate { 9607c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 9617c478bd9Sstevel@tonic-gate const fmd_conf_ops_t *ops = fmd_conf_gettype(mp->mod_conf, name); 9627c478bd9Sstevel@tonic-gate int64_t value = 0; 9637c478bd9Sstevel@tonic-gate 9647c478bd9Sstevel@tonic-gate if (ops == &fmd_conf_int64 || ops == &fmd_conf_uint64 || 9657c478bd9Sstevel@tonic-gate ops == &fmd_conf_time || ops == &fmd_conf_size) 9667c478bd9Sstevel@tonic-gate (void) fmd_conf_getprop(mp->mod_conf, name, &value); 9677c478bd9Sstevel@tonic-gate else if (ops != NULL) { 9687c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_PROP_TYPE, 9697c478bd9Sstevel@tonic-gate "property %s is not of int64 type\n", name); 9707c478bd9Sstevel@tonic-gate } else { 9717c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_PROP_DEFN, 9727c478bd9Sstevel@tonic-gate "property %s is not defined\n", name); 9737c478bd9Sstevel@tonic-gate } 9747c478bd9Sstevel@tonic-gate 9757c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 9767c478bd9Sstevel@tonic-gate return (value); 9777c478bd9Sstevel@tonic-gate } 9787c478bd9Sstevel@tonic-gate 9797c478bd9Sstevel@tonic-gate char * 9807c478bd9Sstevel@tonic-gate fmd_prop_get_string(fmd_hdl_t *hdl, const char *name) 9817c478bd9Sstevel@tonic-gate { 9827c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 9837c478bd9Sstevel@tonic-gate const fmd_conf_ops_t *ops = fmd_conf_gettype(mp->mod_conf, name); 9847c478bd9Sstevel@tonic-gate char *value = NULL; 9857c478bd9Sstevel@tonic-gate const char *s; 9867c478bd9Sstevel@tonic-gate 9877c478bd9Sstevel@tonic-gate if (ops == &fmd_conf_string) { 9887c478bd9Sstevel@tonic-gate (void) fmd_conf_getprop(mp->mod_conf, name, &s); 9897c478bd9Sstevel@tonic-gate value = fmd_strdup(s, FMD_SLEEP); 9907c478bd9Sstevel@tonic-gate } else if (ops != NULL) { 9917c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_PROP_TYPE, 9927c478bd9Sstevel@tonic-gate "property %s is not of string type\n", name); 9937c478bd9Sstevel@tonic-gate } else { 9947c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_PROP_DEFN, 9957c478bd9Sstevel@tonic-gate "property %s is not defined\n", name); 9967c478bd9Sstevel@tonic-gate } 9977c478bd9Sstevel@tonic-gate 9987c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 9997c478bd9Sstevel@tonic-gate return (value); 10007c478bd9Sstevel@tonic-gate } 10017c478bd9Sstevel@tonic-gate 10027c478bd9Sstevel@tonic-gate void 10037c478bd9Sstevel@tonic-gate fmd_prop_free_string(fmd_hdl_t *hdl, char *s) 10047c478bd9Sstevel@tonic-gate { 10057c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 10067c478bd9Sstevel@tonic-gate fmd_strfree(s); 10077c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 10087c478bd9Sstevel@tonic-gate } 10097c478bd9Sstevel@tonic-gate 10107c478bd9Sstevel@tonic-gate fmd_stat_t * 10117c478bd9Sstevel@tonic-gate fmd_stat_create(fmd_hdl_t *hdl, uint_t flags, uint_t argc, fmd_stat_t *argv) 10127c478bd9Sstevel@tonic-gate { 10137c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 10147c478bd9Sstevel@tonic-gate fmd_stat_t *ep, *sp; 10157c478bd9Sstevel@tonic-gate 10167c478bd9Sstevel@tonic-gate if (flags & ~FMD_STAT_ALLOC) { 10177c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_STAT_FLAGS, 10187c478bd9Sstevel@tonic-gate "invalid flags 0x%x passed to fmd_stat_create\n", flags); 10197c478bd9Sstevel@tonic-gate } 10207c478bd9Sstevel@tonic-gate 10217c478bd9Sstevel@tonic-gate if ((sp = fmd_ustat_insert(mp->mod_ustat, 10227c478bd9Sstevel@tonic-gate flags | FMD_USTAT_VALIDATE, argc, argv, &ep)) == NULL) { 10237c478bd9Sstevel@tonic-gate fmd_api_error(mp, errno, 10247c478bd9Sstevel@tonic-gate "failed to publish stat '%s'", ep->fmds_name); 10257c478bd9Sstevel@tonic-gate } 10267c478bd9Sstevel@tonic-gate 10277c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 10287c478bd9Sstevel@tonic-gate return (sp); 10297c478bd9Sstevel@tonic-gate } 10307c478bd9Sstevel@tonic-gate 10317c478bd9Sstevel@tonic-gate void 10327c478bd9Sstevel@tonic-gate fmd_stat_destroy(fmd_hdl_t *hdl, uint_t argc, fmd_stat_t *argv) 10337c478bd9Sstevel@tonic-gate { 10347c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 10357c478bd9Sstevel@tonic-gate fmd_ustat_delete(mp->mod_ustat, argc, argv); 10367c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 10377c478bd9Sstevel@tonic-gate } 10387c478bd9Sstevel@tonic-gate 10397c478bd9Sstevel@tonic-gate void 10407c478bd9Sstevel@tonic-gate fmd_stat_setstr(fmd_hdl_t *hdl, fmd_stat_t *sp, const char *s) 10417c478bd9Sstevel@tonic-gate { 10427c478bd9Sstevel@tonic-gate char *str = fmd_strdup(s, FMD_SLEEP); 10437c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 10447c478bd9Sstevel@tonic-gate 10457c478bd9Sstevel@tonic-gate if (sp->fmds_type != FMD_TYPE_STRING) { 10467c478bd9Sstevel@tonic-gate fmd_strfree(str); 10477c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_STAT_TYPE, 10487c478bd9Sstevel@tonic-gate "stat '%s' is not a string\n", sp->fmds_name); 10497c478bd9Sstevel@tonic-gate } 10507c478bd9Sstevel@tonic-gate 10517c478bd9Sstevel@tonic-gate fmd_strfree(sp->fmds_value.str); 10527c478bd9Sstevel@tonic-gate sp->fmds_value.str = str; 10537c478bd9Sstevel@tonic-gate 10547c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 10557c478bd9Sstevel@tonic-gate } 10567c478bd9Sstevel@tonic-gate 10577c478bd9Sstevel@tonic-gate fmd_case_t * 10587c478bd9Sstevel@tonic-gate fmd_case_open(fmd_hdl_t *hdl, void *data) 10597c478bd9Sstevel@tonic-gate { 10607c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 1061*f6e214c7SGavin Maltby fmd_case_t *cp = fmd_case_create(mp, NULL, data); 10627c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 10637c478bd9Sstevel@tonic-gate return (cp); 10647c478bd9Sstevel@tonic-gate } 10657c478bd9Sstevel@tonic-gate 1066*f6e214c7SGavin Maltby fmd_case_t * 1067*f6e214c7SGavin Maltby fmd_case_open_uuid(fmd_hdl_t *hdl, const char *uuidstr, void *data) 1068*f6e214c7SGavin Maltby { 1069*f6e214c7SGavin Maltby fmd_module_t *mp; 1070*f6e214c7SGavin Maltby fmd_case_t *cp; 1071*f6e214c7SGavin Maltby uint_t uuidlen; 1072*f6e214c7SGavin Maltby uuid_t uuid; 1073*f6e214c7SGavin Maltby 1074*f6e214c7SGavin Maltby mp = fmd_api_module_lock(hdl); 1075*f6e214c7SGavin Maltby 1076*f6e214c7SGavin Maltby (void) fmd_conf_getprop(fmd.d_conf, "uuidlen", &uuidlen); 1077*f6e214c7SGavin Maltby 1078*f6e214c7SGavin Maltby if (uuidstr == NULL) { 1079*f6e214c7SGavin Maltby fmd_api_error(mp, EFMD_CASE_INVAL, "NULL uuid string\n"); 1080*f6e214c7SGavin Maltby } else if (strnlen(uuidstr, uuidlen + 1) != uuidlen) { 1081*f6e214c7SGavin Maltby fmd_api_error(mp, EFMD_CASE_INVAL, "invalid uuid string: '%s' " 1082*f6e214c7SGavin Maltby "(expected length %d)\n", uuidstr, uuidlen); 1083*f6e214c7SGavin Maltby } else if (uuid_parse((char *)uuidstr, uuid) == -1) { 1084*f6e214c7SGavin Maltby fmd_api_error(mp, EFMD_CASE_INVAL, "cannot parse uuid string: " 1085*f6e214c7SGavin Maltby "'%s'\n", uuidstr); 1086*f6e214c7SGavin Maltby } 1087*f6e214c7SGavin Maltby 1088*f6e214c7SGavin Maltby if ((cp = fmd_case_hash_lookup(fmd.d_cases, uuidstr)) == NULL) { 1089*f6e214c7SGavin Maltby cp = fmd_case_create(mp, uuidstr, data); 1090*f6e214c7SGavin Maltby } else { 1091*f6e214c7SGavin Maltby fmd_case_rele(cp); 1092*f6e214c7SGavin Maltby cp = NULL; 1093*f6e214c7SGavin Maltby } 1094*f6e214c7SGavin Maltby 1095*f6e214c7SGavin Maltby fmd_module_unlock(mp); 1096*f6e214c7SGavin Maltby return (cp); /* May be NULL iff case already exists */ 1097*f6e214c7SGavin Maltby } 1098*f6e214c7SGavin Maltby 10997c478bd9Sstevel@tonic-gate void 11007c478bd9Sstevel@tonic-gate fmd_case_reset(fmd_hdl_t *hdl, fmd_case_t *cp) 11017c478bd9Sstevel@tonic-gate { 11027c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 11037c478bd9Sstevel@tonic-gate fmd_case_impl_t *cip = fmd_api_case_impl(mp, cp); 11047c478bd9Sstevel@tonic-gate 11057c478bd9Sstevel@tonic-gate if (cip->ci_state >= FMD_CASE_SOLVED) { 11067c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_CASE_STATE, "cannot solve %s: " 11077c478bd9Sstevel@tonic-gate "case is already solved or closed\n", cip->ci_uuid); 11087c478bd9Sstevel@tonic-gate } 11097c478bd9Sstevel@tonic-gate 11107c478bd9Sstevel@tonic-gate fmd_case_reset_suspects(cp); 11117c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 11127c478bd9Sstevel@tonic-gate } 11137c478bd9Sstevel@tonic-gate 11147c478bd9Sstevel@tonic-gate void 11157c478bd9Sstevel@tonic-gate fmd_case_solve(fmd_hdl_t *hdl, fmd_case_t *cp) 11167c478bd9Sstevel@tonic-gate { 11177c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 11187c478bd9Sstevel@tonic-gate fmd_case_impl_t *cip = fmd_api_case_impl(mp, cp); 11197c478bd9Sstevel@tonic-gate 11207c478bd9Sstevel@tonic-gate if (cip->ci_state >= FMD_CASE_SOLVED) { 11217c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_CASE_STATE, "cannot solve %s: " 11227c478bd9Sstevel@tonic-gate "case is already solved or closed\n", cip->ci_uuid); 11237c478bd9Sstevel@tonic-gate } 11247c478bd9Sstevel@tonic-gate 1125d9638e54Smws fmd_case_transition(cp, FMD_CASE_SOLVED, FMD_CF_SOLVED); 11267c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 11277c478bd9Sstevel@tonic-gate } 11287c478bd9Sstevel@tonic-gate 11297c478bd9Sstevel@tonic-gate void 11307c478bd9Sstevel@tonic-gate fmd_case_close(fmd_hdl_t *hdl, fmd_case_t *cp) 11317c478bd9Sstevel@tonic-gate { 11327c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 11337c478bd9Sstevel@tonic-gate 11347c478bd9Sstevel@tonic-gate (void) fmd_api_case_impl(mp, cp); /* validate 'cp' */ 1135d9638e54Smws fmd_case_transition(cp, FMD_CASE_CLOSE_WAIT, FMD_CF_ISOLATED); 11367c478bd9Sstevel@tonic-gate 11377c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 11387c478bd9Sstevel@tonic-gate } 11397c478bd9Sstevel@tonic-gate 11407c478bd9Sstevel@tonic-gate const char * 11417c478bd9Sstevel@tonic-gate fmd_case_uuid(fmd_hdl_t *hdl, fmd_case_t *cp) 11427c478bd9Sstevel@tonic-gate { 11437c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 11447c478bd9Sstevel@tonic-gate fmd_case_impl_t *cip = fmd_api_case_impl(mp, cp); 11457c478bd9Sstevel@tonic-gate const char *uuid = cip->ci_uuid; 11467c478bd9Sstevel@tonic-gate 11477c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 11487c478bd9Sstevel@tonic-gate return (uuid); 11497c478bd9Sstevel@tonic-gate } 11507c478bd9Sstevel@tonic-gate 11517c478bd9Sstevel@tonic-gate fmd_case_t * 11527c478bd9Sstevel@tonic-gate fmd_case_uulookup(fmd_hdl_t *hdl, const char *uuid) 11537c478bd9Sstevel@tonic-gate { 11547c478bd9Sstevel@tonic-gate fmd_module_t *cmp, *mp = fmd_api_module_lock(hdl); 11557c478bd9Sstevel@tonic-gate fmd_case_t *cp = fmd_case_hash_lookup(fmd.d_cases, uuid); 11567c478bd9Sstevel@tonic-gate 11577c478bd9Sstevel@tonic-gate if (cp != NULL) { 11587c478bd9Sstevel@tonic-gate cmp = ((fmd_case_impl_t *)cp)->ci_mod; 11597c478bd9Sstevel@tonic-gate fmd_case_rele(cp); 11607c478bd9Sstevel@tonic-gate } else 11617c478bd9Sstevel@tonic-gate cmp = NULL; 11627c478bd9Sstevel@tonic-gate 11637c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 11647c478bd9Sstevel@tonic-gate return (cmp == mp ? cp : NULL); 11657c478bd9Sstevel@tonic-gate } 11667c478bd9Sstevel@tonic-gate 11677c478bd9Sstevel@tonic-gate void 11687c478bd9Sstevel@tonic-gate fmd_case_uuclose(fmd_hdl_t *hdl, const char *uuid) 11697c478bd9Sstevel@tonic-gate { 11707c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 11717c478bd9Sstevel@tonic-gate fmd_case_t *cp = fmd_case_hash_lookup(fmd.d_cases, uuid); 11727c478bd9Sstevel@tonic-gate 1173d9638e54Smws if (cp != NULL) { 1174d9638e54Smws fmd_case_transition(cp, FMD_CASE_CLOSE_WAIT, FMD_CF_ISOLATED); 11757c478bd9Sstevel@tonic-gate fmd_case_rele(cp); 1176d9638e54Smws } 1177d9638e54Smws 11787c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 11797c478bd9Sstevel@tonic-gate } 11807c478bd9Sstevel@tonic-gate 11817c478bd9Sstevel@tonic-gate int 11827c478bd9Sstevel@tonic-gate fmd_case_uuclosed(fmd_hdl_t *hdl, const char *uuid) 11837c478bd9Sstevel@tonic-gate { 11847c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 11857c478bd9Sstevel@tonic-gate fmd_case_t *cp = fmd_case_hash_lookup(fmd.d_cases, uuid); 11867c478bd9Sstevel@tonic-gate fmd_case_impl_t *cip = (fmd_case_impl_t *)cp; 11877c478bd9Sstevel@tonic-gate int rv = FMD_B_TRUE; 11887c478bd9Sstevel@tonic-gate 11897c478bd9Sstevel@tonic-gate if (cip != NULL) { 1190d9638e54Smws rv = cip->ci_state >= FMD_CASE_CLOSE_WAIT; 11917c478bd9Sstevel@tonic-gate fmd_case_rele(cp); 11927c478bd9Sstevel@tonic-gate } 11937c478bd9Sstevel@tonic-gate 11947c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 11957c478bd9Sstevel@tonic-gate return (rv); 11967c478bd9Sstevel@tonic-gate } 11977c478bd9Sstevel@tonic-gate 119825c6ff4bSstephh void 119925c6ff4bSstephh fmd_case_uuresolved(fmd_hdl_t *hdl, const char *uuid) 120025c6ff4bSstephh { 120125c6ff4bSstephh fmd_module_t *mp = fmd_api_module_lock(hdl); 120225c6ff4bSstephh fmd_case_t *cp = fmd_case_hash_lookup(fmd.d_cases, uuid); 120325c6ff4bSstephh 120425c6ff4bSstephh if (cp != NULL) { 1205cbf75e67SStephen Hanson fmd_case_impl_t *cip = (fmd_case_impl_t *)cp; 1206cbf75e67SStephen Hanson /* 1207cbf75e67SStephen Hanson * For a proxy, we notify the diagnosing side, and then 1208cbf75e67SStephen Hanson * wait for it to send us back a list.resolved. 1209cbf75e67SStephen Hanson */ 1210cbf75e67SStephen Hanson if (cip->ci_xprt != NULL) 1211cbf75e67SStephen Hanson fmd_xprt_uuresolved(cip->ci_xprt, cip->ci_uuid); 1212cbf75e67SStephen Hanson else 121325c6ff4bSstephh fmd_case_transition(cp, FMD_CASE_RESOLVED, 0); 121425c6ff4bSstephh fmd_case_rele(cp); 121525c6ff4bSstephh } 121625c6ff4bSstephh 121725c6ff4bSstephh fmd_module_unlock(mp); 121825c6ff4bSstephh } 121925c6ff4bSstephh 1220*f6e214c7SGavin Maltby int 1221*f6e214c7SGavin Maltby fmd_case_uuisresolved(fmd_hdl_t *hdl, const char *uuid) 1222*f6e214c7SGavin Maltby { 1223*f6e214c7SGavin Maltby fmd_module_t *mp = fmd_api_module_lock(hdl); 1224*f6e214c7SGavin Maltby fmd_case_t *cp = fmd_case_hash_lookup(fmd.d_cases, uuid); 1225*f6e214c7SGavin Maltby fmd_case_impl_t *cip = (fmd_case_impl_t *)cp; 1226*f6e214c7SGavin Maltby int rv = FMD_B_FALSE; 1227*f6e214c7SGavin Maltby 1228*f6e214c7SGavin Maltby if (cip != NULL) { 1229*f6e214c7SGavin Maltby rv = (cip->ci_state >= FMD_CASE_RESOLVED); 1230*f6e214c7SGavin Maltby fmd_case_rele(cp); 1231*f6e214c7SGavin Maltby } 1232*f6e214c7SGavin Maltby 1233*f6e214c7SGavin Maltby fmd_module_unlock(mp); 1234*f6e214c7SGavin Maltby return (rv); 1235*f6e214c7SGavin Maltby } 1236*f6e214c7SGavin Maltby 12377c478bd9Sstevel@tonic-gate static int 12387c478bd9Sstevel@tonic-gate fmd_case_instate(fmd_hdl_t *hdl, fmd_case_t *cp, uint_t state) 12397c478bd9Sstevel@tonic-gate { 12407c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 12417c478bd9Sstevel@tonic-gate fmd_case_impl_t *cip = fmd_api_case_impl(mp, cp); 12427c478bd9Sstevel@tonic-gate int rv = cip->ci_state >= state; 12437c478bd9Sstevel@tonic-gate 12447c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 12457c478bd9Sstevel@tonic-gate return (rv); 12467c478bd9Sstevel@tonic-gate } 12477c478bd9Sstevel@tonic-gate 12487c478bd9Sstevel@tonic-gate int 12497c478bd9Sstevel@tonic-gate fmd_case_solved(fmd_hdl_t *hdl, fmd_case_t *cp) 12507c478bd9Sstevel@tonic-gate { 12517c478bd9Sstevel@tonic-gate return (fmd_case_instate(hdl, cp, FMD_CASE_SOLVED)); 12527c478bd9Sstevel@tonic-gate } 12537c478bd9Sstevel@tonic-gate 12547c478bd9Sstevel@tonic-gate int 12557c478bd9Sstevel@tonic-gate fmd_case_closed(fmd_hdl_t *hdl, fmd_case_t *cp) 12567c478bd9Sstevel@tonic-gate { 1257d9638e54Smws return (fmd_case_instate(hdl, cp, FMD_CASE_CLOSE_WAIT)); 12587c478bd9Sstevel@tonic-gate } 12597c478bd9Sstevel@tonic-gate 12607c478bd9Sstevel@tonic-gate void 12617c478bd9Sstevel@tonic-gate fmd_case_add_ereport(fmd_hdl_t *hdl, fmd_case_t *cp, fmd_event_t *ep) 12627c478bd9Sstevel@tonic-gate { 12637c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 12647c478bd9Sstevel@tonic-gate 12657c478bd9Sstevel@tonic-gate (void) fmd_api_case_impl(mp, cp); /* validate 'cp' */ 12667aec1d6eScindi 12677aec1d6eScindi if (fmd_case_insert_event(cp, ep)) 12687c478bd9Sstevel@tonic-gate mp->mod_stats->ms_accepted.fmds_value.ui64++; 12697c478bd9Sstevel@tonic-gate 12707c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 12717c478bd9Sstevel@tonic-gate } 12727c478bd9Sstevel@tonic-gate 12737c478bd9Sstevel@tonic-gate void 12747c478bd9Sstevel@tonic-gate fmd_case_add_serd(fmd_hdl_t *hdl, fmd_case_t *cp, const char *name) 12757c478bd9Sstevel@tonic-gate { 12767c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 12777c478bd9Sstevel@tonic-gate fmd_serd_elem_t *sep; 12787c478bd9Sstevel@tonic-gate fmd_serd_eng_t *sgp; 12797c478bd9Sstevel@tonic-gate 12807c478bd9Sstevel@tonic-gate if ((sgp = fmd_serd_eng_lookup(&mp->mod_serds, name)) == NULL) { 12817c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_SERD_NAME, 12827c478bd9Sstevel@tonic-gate "failed to add events from serd engine '%s'", name); 12837c478bd9Sstevel@tonic-gate } 12847c478bd9Sstevel@tonic-gate 12857c478bd9Sstevel@tonic-gate (void) fmd_api_case_impl(mp, cp); /* validate 'cp' */ 12867c478bd9Sstevel@tonic-gate 12877c478bd9Sstevel@tonic-gate for (sep = fmd_list_next(&sgp->sg_list); 12887aec1d6eScindi sep != NULL; sep = fmd_list_next(sep)) { 12897aec1d6eScindi if (fmd_case_insert_event(cp, sep->se_event)) 12907aec1d6eScindi mp->mod_stats->ms_accepted.fmds_value.ui64++; 12917aec1d6eScindi } 12927c478bd9Sstevel@tonic-gate 12937c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 12947c478bd9Sstevel@tonic-gate } 12957c478bd9Sstevel@tonic-gate 12967c478bd9Sstevel@tonic-gate void 12977c478bd9Sstevel@tonic-gate fmd_case_add_suspect(fmd_hdl_t *hdl, fmd_case_t *cp, nvlist_t *nvl) 12987c478bd9Sstevel@tonic-gate { 12997c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 13007c478bd9Sstevel@tonic-gate fmd_case_impl_t *cip = fmd_api_case_impl(mp, cp); 13017c478bd9Sstevel@tonic-gate char *class; 1302b7d3956bSstephh topo_hdl_t *thp; 1303b7d3956bSstephh int err; 13048e7248e5SStephen Hanson nvlist_t *rsrc = NULL, *asru_prop = NULL, *asru = NULL, *fru = NULL; 1305b7d3956bSstephh char *loc = NULL, *serial = NULL; 13067c478bd9Sstevel@tonic-gate 13077c478bd9Sstevel@tonic-gate if (cip->ci_state >= FMD_CASE_SOLVED) { 13087c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_CASE_STATE, "cannot add suspect to " 13097c478bd9Sstevel@tonic-gate "%s: case is already solved or closed\n", cip->ci_uuid); 13107c478bd9Sstevel@tonic-gate } 13117c478bd9Sstevel@tonic-gate 13127c478bd9Sstevel@tonic-gate if (nvlist_lookup_string(nvl, FM_CLASS, &class) != 0 || 13137c478bd9Sstevel@tonic-gate class == NULL || *class == '\0') { 13147c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_CASE_EVENT, "cannot add suspect to " 13157c478bd9Sstevel@tonic-gate "%s: suspect event is missing a class\n", cip->ci_uuid); 13167c478bd9Sstevel@tonic-gate } 13177c478bd9Sstevel@tonic-gate 1318b7d3956bSstephh thp = fmd_module_topo_hold(mp); 1319b7d3956bSstephh (void) nvlist_lookup_nvlist(nvl, FM_FAULT_RESOURCE, &rsrc); 1320b7d3956bSstephh (void) nvlist_lookup_nvlist(nvl, FM_FAULT_ASRU, &asru); 1321b7d3956bSstephh (void) nvlist_lookup_nvlist(nvl, FM_FAULT_FRU, &fru); 1322b7d3956bSstephh if (rsrc != NULL) { 1323b7d3956bSstephh if (strncmp(class, "defect", 6) == 0) { 1324b7d3956bSstephh if (asru == NULL && topo_fmri_getprop(thp, rsrc, 1325b7d3956bSstephh TOPO_PGROUP_IO, TOPO_IO_MODULE, rsrc, 13268e7248e5SStephen Hanson &asru_prop, &err) == 0 && 13278e7248e5SStephen Hanson nvlist_lookup_nvlist(asru_prop, TOPO_PROP_VAL_VAL, 13288e7248e5SStephen Hanson &asru) == 0) { 1329b7d3956bSstephh (void) nvlist_add_nvlist(nvl, FM_FAULT_ASRU, 1330b7d3956bSstephh asru); 1331705e9f42SStephen Hanson nvlist_free(asru_prop); 1332b7d3956bSstephh (void) nvlist_lookup_nvlist(nvl, FM_FAULT_ASRU, 1333b7d3956bSstephh &asru); 1334b7d3956bSstephh } 1335b7d3956bSstephh } else { 1336b7d3956bSstephh if (topo_fmri_asru(thp, rsrc, &asru, &err) == 0) { 1337b7d3956bSstephh (void) nvlist_remove(nvl, FM_FAULT_ASRU, 1338b7d3956bSstephh DATA_TYPE_NVLIST); 1339b7d3956bSstephh (void) nvlist_add_nvlist(nvl, FM_FAULT_ASRU, 1340b7d3956bSstephh asru); 1341b7d3956bSstephh nvlist_free(asru); 1342b7d3956bSstephh (void) nvlist_lookup_nvlist(nvl, FM_FAULT_ASRU, 1343b7d3956bSstephh &asru); 1344b7d3956bSstephh } 1345b7d3956bSstephh if (topo_fmri_fru(thp, rsrc, &fru, &err) == 0) { 1346b7d3956bSstephh (void) nvlist_remove(nvl, FM_FAULT_FRU, 1347b7d3956bSstephh DATA_TYPE_NVLIST); 1348b7d3956bSstephh (void) nvlist_add_nvlist(nvl, FM_FAULT_FRU, 1349b7d3956bSstephh fru); 1350b7d3956bSstephh nvlist_free(fru); 1351b7d3956bSstephh (void) nvlist_lookup_nvlist(nvl, FM_FAULT_FRU, 1352b7d3956bSstephh &fru); 1353b7d3956bSstephh } 1354b7d3956bSstephh } 1355b7d3956bSstephh } 1356b7d3956bSstephh 1357b7d3956bSstephh /* 1358b7d3956bSstephh * Try to find the location label for this resource 1359b7d3956bSstephh */ 1360705e9f42SStephen Hanson if (strncmp(class, "defect", 6) != 0) { 1361b7d3956bSstephh if (fru != NULL) 1362b7d3956bSstephh (void) topo_fmri_label(thp, fru, &loc, &err); 1363b7d3956bSstephh else if (rsrc != NULL) 1364b7d3956bSstephh (void) topo_fmri_label(thp, rsrc, &loc, &err); 1365705e9f42SStephen Hanson if (loc != NULL) { 1366705e9f42SStephen Hanson (void) nvlist_remove(nvl, FM_FAULT_LOCATION, 1367705e9f42SStephen Hanson DATA_TYPE_STRING); 1368b7d3956bSstephh (void) nvlist_add_string(nvl, FM_FAULT_LOCATION, loc); 1369b7d3956bSstephh topo_hdl_strfree(thp, loc); 1370b7d3956bSstephh } 1371705e9f42SStephen Hanson } 1372b7d3956bSstephh 1373b7d3956bSstephh /* 1374b7d3956bSstephh * In some cases, serial information for the resource will not be 1375b7d3956bSstephh * available at enumeration but may instead be available by invoking 1376b7d3956bSstephh * a dynamic property method on the FRU. In order to ensure the serial 1377b7d3956bSstephh * number is persisted properly in the ASRU cache, we'll fetch the 1378b7d3956bSstephh * property, if it exists, and add it to the resource and fru fmris. 137983031c4cSSrihari Venkatesan * If the DE has not listed a fru in the suspect, see if we can 138083031c4cSSrihari Venkatesan * retrieve the serial from the resource instead. 1381b7d3956bSstephh */ 1382b7d3956bSstephh if (fru != NULL) { 1383b7d3956bSstephh (void) topo_fmri_serial(thp, fru, &serial, &err); 1384b7d3956bSstephh if (serial != NULL) { 1385b7d3956bSstephh (void) nvlist_add_string(fru, "serial", serial); 1386b7d3956bSstephh topo_hdl_strfree(thp, serial); 1387b7d3956bSstephh } 1388b7d3956bSstephh } 1389b7d3956bSstephh 1390b7d3956bSstephh err = fmd_module_topo_rele(mp, thp); 1391b7d3956bSstephh ASSERT(err == 0); 1392b7d3956bSstephh 13937c478bd9Sstevel@tonic-gate fmd_case_insert_suspect(cp, nvl); 13947c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 13957c478bd9Sstevel@tonic-gate } 13967c478bd9Sstevel@tonic-gate 13977c478bd9Sstevel@tonic-gate void 13987c478bd9Sstevel@tonic-gate fmd_case_setspecific(fmd_hdl_t *hdl, fmd_case_t *cp, void *data) 13997c478bd9Sstevel@tonic-gate { 14007c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 14017c478bd9Sstevel@tonic-gate fmd_case_impl_t *cip = fmd_api_case_impl(mp, cp); 14027c478bd9Sstevel@tonic-gate 14037c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&cip->ci_lock); 14047c478bd9Sstevel@tonic-gate cip->ci_data = data; 14057c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&cip->ci_lock); 14067c478bd9Sstevel@tonic-gate 14077c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 14087c478bd9Sstevel@tonic-gate } 14097c478bd9Sstevel@tonic-gate 14107c478bd9Sstevel@tonic-gate void * 14117c478bd9Sstevel@tonic-gate fmd_case_getspecific(fmd_hdl_t *hdl, fmd_case_t *cp) 14127c478bd9Sstevel@tonic-gate { 14137c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 14147c478bd9Sstevel@tonic-gate fmd_case_impl_t *cip = fmd_api_case_impl(mp, cp); 14157c478bd9Sstevel@tonic-gate void *data; 14167c478bd9Sstevel@tonic-gate 14177c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&cip->ci_lock); 14187c478bd9Sstevel@tonic-gate data = cip->ci_data; 14197c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&cip->ci_lock); 14207c478bd9Sstevel@tonic-gate 14217c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 14227c478bd9Sstevel@tonic-gate return (data); 14237c478bd9Sstevel@tonic-gate } 14247c478bd9Sstevel@tonic-gate 14257c478bd9Sstevel@tonic-gate void 14267c478bd9Sstevel@tonic-gate fmd_case_setprincipal(fmd_hdl_t *hdl, fmd_case_t *cp, fmd_event_t *ep) 14277c478bd9Sstevel@tonic-gate { 14287c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 14297c478bd9Sstevel@tonic-gate 14307c478bd9Sstevel@tonic-gate (void) fmd_api_case_impl(mp, cp); /* validate 'cp' */ 14317aec1d6eScindi 14327aec1d6eScindi if (fmd_case_insert_principal(cp, ep)) 14337c478bd9Sstevel@tonic-gate mp->mod_stats->ms_accepted.fmds_value.ui64++; 14347c478bd9Sstevel@tonic-gate 14357c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 14367c478bd9Sstevel@tonic-gate } 14377c478bd9Sstevel@tonic-gate 14387c478bd9Sstevel@tonic-gate fmd_event_t * 14397c478bd9Sstevel@tonic-gate fmd_case_getprincipal(fmd_hdl_t *hdl, fmd_case_t *cp) 14407c478bd9Sstevel@tonic-gate { 14417c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 14427c478bd9Sstevel@tonic-gate fmd_case_impl_t *cip = fmd_api_case_impl(mp, cp); 14437c478bd9Sstevel@tonic-gate fmd_event_t *ep; 14447c478bd9Sstevel@tonic-gate 14457c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&cip->ci_lock); 14467c478bd9Sstevel@tonic-gate ep = cip->ci_principal; 14477c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&cip->ci_lock); 14487c478bd9Sstevel@tonic-gate 14497c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 14507c478bd9Sstevel@tonic-gate return (ep); 14517c478bd9Sstevel@tonic-gate } 14527c478bd9Sstevel@tonic-gate 14537c478bd9Sstevel@tonic-gate fmd_case_t * 14547c478bd9Sstevel@tonic-gate fmd_case_next(fmd_hdl_t *hdl, fmd_case_t *cp) 14557c478bd9Sstevel@tonic-gate { 14567c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 14577c478bd9Sstevel@tonic-gate 14587c478bd9Sstevel@tonic-gate if (cp != NULL) 14597c478bd9Sstevel@tonic-gate cp = fmd_list_next(fmd_api_case_impl(mp, cp)); 14607c478bd9Sstevel@tonic-gate else 14617c478bd9Sstevel@tonic-gate cp = fmd_list_next(&mp->mod_cases); 14627c478bd9Sstevel@tonic-gate 14637c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 14647c478bd9Sstevel@tonic-gate return (cp); 14657c478bd9Sstevel@tonic-gate } 14667c478bd9Sstevel@tonic-gate 14677c478bd9Sstevel@tonic-gate fmd_case_t * 14687c478bd9Sstevel@tonic-gate fmd_case_prev(fmd_hdl_t *hdl, fmd_case_t *cp) 14697c478bd9Sstevel@tonic-gate { 14707c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 14717c478bd9Sstevel@tonic-gate 14727c478bd9Sstevel@tonic-gate if (cp != NULL) 14737c478bd9Sstevel@tonic-gate cp = fmd_list_prev(fmd_api_case_impl(mp, cp)); 14747c478bd9Sstevel@tonic-gate else 14757c478bd9Sstevel@tonic-gate cp = fmd_list_prev(&mp->mod_cases); 14767c478bd9Sstevel@tonic-gate 14777c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 14787c478bd9Sstevel@tonic-gate return (cp); 14797c478bd9Sstevel@tonic-gate } 14807c478bd9Sstevel@tonic-gate 14817c478bd9Sstevel@tonic-gate /* 14827c478bd9Sstevel@tonic-gate * Utility function for fmd_buf_* routines. If a case is specified, use the 14837c478bd9Sstevel@tonic-gate * case's ci_bufs hash; otherwise use the module's global mod_bufs hash. 14847c478bd9Sstevel@tonic-gate */ 14857c478bd9Sstevel@tonic-gate static fmd_buf_hash_t * 14867c478bd9Sstevel@tonic-gate fmd_buf_gethash(fmd_module_t *mp, fmd_case_t *cp) 14877c478bd9Sstevel@tonic-gate { 14887c478bd9Sstevel@tonic-gate return (cp ? &fmd_api_case_impl(mp, cp)->ci_bufs : &mp->mod_bufs); 14897c478bd9Sstevel@tonic-gate } 14907c478bd9Sstevel@tonic-gate 14917c478bd9Sstevel@tonic-gate void 14927c478bd9Sstevel@tonic-gate fmd_buf_create(fmd_hdl_t *hdl, fmd_case_t *cp, const char *name, size_t size) 14937c478bd9Sstevel@tonic-gate { 14947c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 14957c478bd9Sstevel@tonic-gate fmd_buf_hash_t *bhp = fmd_buf_gethash(mp, cp); 14967c478bd9Sstevel@tonic-gate fmd_buf_t *bp = fmd_buf_lookup(bhp, name); 14977c478bd9Sstevel@tonic-gate 14987c478bd9Sstevel@tonic-gate if (bp == NULL) { 14997c478bd9Sstevel@tonic-gate if (fmd_strbadid(name, FMD_B_TRUE) != NULL || size == 0) { 15007c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_BUF_INVAL, "cannot create '%s' " 15017c478bd9Sstevel@tonic-gate "(size %lu): %s\n", name, (ulong_t)size, 15027c478bd9Sstevel@tonic-gate fmd_strerror(EFMD_BUF_INVAL)); 15037c478bd9Sstevel@tonic-gate } 15047c478bd9Sstevel@tonic-gate 15057c478bd9Sstevel@tonic-gate if (mp->mod_stats->ms_buflimit.fmds_value.ui64 - 15067c478bd9Sstevel@tonic-gate mp->mod_stats->ms_buftotal.fmds_value.ui64 < size) { 15077c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_BUF_LIMIT, "cannot create '%s': " 15087c478bd9Sstevel@tonic-gate "buf limit exceeded (%llu)\n", name, (u_longlong_t) 15097c478bd9Sstevel@tonic-gate mp->mod_stats->ms_buflimit.fmds_value.ui64); 15107c478bd9Sstevel@tonic-gate } 15117c478bd9Sstevel@tonic-gate 15127c478bd9Sstevel@tonic-gate mp->mod_stats->ms_buftotal.fmds_value.ui64 += size; 15137c478bd9Sstevel@tonic-gate bp = fmd_buf_insert(bhp, name, size); 15147c478bd9Sstevel@tonic-gate 15157c478bd9Sstevel@tonic-gate } else { 15167c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_BUF_EXISTS, 15177c478bd9Sstevel@tonic-gate "cannot create '%s': buffer already exists\n", name); 15187c478bd9Sstevel@tonic-gate } 15197c478bd9Sstevel@tonic-gate 15207c478bd9Sstevel@tonic-gate if (cp != NULL) 15217c478bd9Sstevel@tonic-gate fmd_case_setdirty(cp); 15227c478bd9Sstevel@tonic-gate else 15237c478bd9Sstevel@tonic-gate fmd_module_setdirty(mp); 15247c478bd9Sstevel@tonic-gate 15257c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 15267c478bd9Sstevel@tonic-gate } 15277c478bd9Sstevel@tonic-gate 15287c478bd9Sstevel@tonic-gate void 15297c478bd9Sstevel@tonic-gate fmd_buf_destroy(fmd_hdl_t *hdl, fmd_case_t *cp, const char *name) 15307c478bd9Sstevel@tonic-gate { 15317c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 15327c478bd9Sstevel@tonic-gate fmd_buf_hash_t *bhp = fmd_buf_gethash(mp, cp); 15337c478bd9Sstevel@tonic-gate fmd_buf_t *bp = fmd_buf_lookup(bhp, name); 15347c478bd9Sstevel@tonic-gate 15357c478bd9Sstevel@tonic-gate if (bp != NULL) { 15367c478bd9Sstevel@tonic-gate mp->mod_stats->ms_buftotal.fmds_value.ui64 -= bp->buf_size; 15377c478bd9Sstevel@tonic-gate fmd_buf_delete(bhp, name); 15387c478bd9Sstevel@tonic-gate 15397c478bd9Sstevel@tonic-gate if (cp != NULL) 15407c478bd9Sstevel@tonic-gate fmd_case_setdirty(cp); 15417c478bd9Sstevel@tonic-gate else 15427c478bd9Sstevel@tonic-gate fmd_module_setdirty(mp); 15437c478bd9Sstevel@tonic-gate } 15447c478bd9Sstevel@tonic-gate 15457c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 15467c478bd9Sstevel@tonic-gate } 15477c478bd9Sstevel@tonic-gate 15487c478bd9Sstevel@tonic-gate void 15497c478bd9Sstevel@tonic-gate fmd_buf_read(fmd_hdl_t *hdl, fmd_case_t *cp, 15507c478bd9Sstevel@tonic-gate const char *name, void *buf, size_t size) 15517c478bd9Sstevel@tonic-gate { 15527c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 15537c478bd9Sstevel@tonic-gate fmd_buf_t *bp = fmd_buf_lookup(fmd_buf_gethash(mp, cp), name); 15547c478bd9Sstevel@tonic-gate 15557c478bd9Sstevel@tonic-gate if (bp == NULL) { 15567c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_BUF_NOENT, "no buf named '%s' is " 15577c478bd9Sstevel@tonic-gate "associated with %s\n", name, cp ? "case" : "module"); 15587c478bd9Sstevel@tonic-gate } 15597c478bd9Sstevel@tonic-gate 15607c478bd9Sstevel@tonic-gate bcopy(bp->buf_data, buf, MIN(bp->buf_size, size)); 15617c478bd9Sstevel@tonic-gate if (size > bp->buf_size) 15627c478bd9Sstevel@tonic-gate bzero((char *)buf + bp->buf_size, size - bp->buf_size); 15637c478bd9Sstevel@tonic-gate 15647c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 15657c478bd9Sstevel@tonic-gate } 15667c478bd9Sstevel@tonic-gate 15677c478bd9Sstevel@tonic-gate void 15687c478bd9Sstevel@tonic-gate fmd_buf_write(fmd_hdl_t *hdl, fmd_case_t *cp, 15697c478bd9Sstevel@tonic-gate const char *name, const void *buf, size_t size) 15707c478bd9Sstevel@tonic-gate { 15717c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 15727c478bd9Sstevel@tonic-gate fmd_buf_hash_t *bhp = fmd_buf_gethash(mp, cp); 15737c478bd9Sstevel@tonic-gate fmd_buf_t *bp = fmd_buf_lookup(bhp, name); 15747c478bd9Sstevel@tonic-gate 15757c478bd9Sstevel@tonic-gate if (bp == NULL) { 15767c478bd9Sstevel@tonic-gate if (fmd_strbadid(name, FMD_B_TRUE) != NULL || size == 0) { 15777c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_BUF_INVAL, "cannot write '%s' " 15787c478bd9Sstevel@tonic-gate "(size %lu): %s\n", name, (ulong_t)size, 15797c478bd9Sstevel@tonic-gate fmd_strerror(EFMD_BUF_INVAL)); 15807c478bd9Sstevel@tonic-gate } 15817c478bd9Sstevel@tonic-gate 15827c478bd9Sstevel@tonic-gate if (mp->mod_stats->ms_buflimit.fmds_value.ui64 - 15837c478bd9Sstevel@tonic-gate mp->mod_stats->ms_buftotal.fmds_value.ui64 < size) { 15847c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_BUF_LIMIT, "cannot write '%s': " 15857c478bd9Sstevel@tonic-gate "buf limit exceeded (%llu)\n", name, (u_longlong_t) 15867c478bd9Sstevel@tonic-gate mp->mod_stats->ms_buflimit.fmds_value.ui64); 15877c478bd9Sstevel@tonic-gate } 15887c478bd9Sstevel@tonic-gate 15897c478bd9Sstevel@tonic-gate mp->mod_stats->ms_buftotal.fmds_value.ui64 += size; 15907c478bd9Sstevel@tonic-gate bp = fmd_buf_insert(bhp, name, size); 15917c478bd9Sstevel@tonic-gate 15927c478bd9Sstevel@tonic-gate } else if (size > bp->buf_size) { 15937c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_BUF_OFLOW, 15947c478bd9Sstevel@tonic-gate "write to buf '%s' overflows buf size (%lu > %lu)\n", 15957c478bd9Sstevel@tonic-gate name, (ulong_t)size, (ulong_t)bp->buf_size); 15967c478bd9Sstevel@tonic-gate } 15977c478bd9Sstevel@tonic-gate 15987c478bd9Sstevel@tonic-gate bcopy(buf, bp->buf_data, MIN(bp->buf_size, size)); 15997c478bd9Sstevel@tonic-gate bp->buf_flags |= FMD_BUF_DIRTY; 16007c478bd9Sstevel@tonic-gate 16017c478bd9Sstevel@tonic-gate if (cp != NULL) 16027c478bd9Sstevel@tonic-gate fmd_case_setdirty(cp); 16037c478bd9Sstevel@tonic-gate else 16047c478bd9Sstevel@tonic-gate fmd_module_setdirty(mp); 16057c478bd9Sstevel@tonic-gate 16067c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 16077c478bd9Sstevel@tonic-gate } 16087c478bd9Sstevel@tonic-gate 16097c478bd9Sstevel@tonic-gate size_t 16107c478bd9Sstevel@tonic-gate fmd_buf_size(fmd_hdl_t *hdl, fmd_case_t *cp, const char *name) 16117c478bd9Sstevel@tonic-gate { 16127c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 16137c478bd9Sstevel@tonic-gate fmd_buf_hash_t *bhp = fmd_buf_gethash(mp, cp); 16147c478bd9Sstevel@tonic-gate 16157c478bd9Sstevel@tonic-gate fmd_buf_t *bp; 16167c478bd9Sstevel@tonic-gate size_t size; 16177c478bd9Sstevel@tonic-gate 16187c478bd9Sstevel@tonic-gate if ((bp = fmd_buf_lookup(bhp, name)) != NULL) 16197c478bd9Sstevel@tonic-gate size = bp->buf_size; 16207c478bd9Sstevel@tonic-gate else 16217c478bd9Sstevel@tonic-gate size = 0; 16227c478bd9Sstevel@tonic-gate 16237c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 16247c478bd9Sstevel@tonic-gate return (size); 16257c478bd9Sstevel@tonic-gate } 16267c478bd9Sstevel@tonic-gate 16277c478bd9Sstevel@tonic-gate void 16287c478bd9Sstevel@tonic-gate fmd_serd_create(fmd_hdl_t *hdl, const char *name, uint_t n, hrtime_t t) 16297c478bd9Sstevel@tonic-gate { 16307c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 16317c478bd9Sstevel@tonic-gate 16327c478bd9Sstevel@tonic-gate if (fmd_serd_eng_lookup(&mp->mod_serds, name) != NULL) { 16337c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_SERD_EXISTS, 16347c478bd9Sstevel@tonic-gate "failed to create serd engine '%s': %s\n", 16357c478bd9Sstevel@tonic-gate name, fmd_strerror(EFMD_SERD_EXISTS)); 16367c478bd9Sstevel@tonic-gate } 16377c478bd9Sstevel@tonic-gate 16387c478bd9Sstevel@tonic-gate (void) fmd_serd_eng_insert(&mp->mod_serds, name, n, t); 16397c478bd9Sstevel@tonic-gate fmd_module_setdirty(mp); 16407c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 16417c478bd9Sstevel@tonic-gate } 16427c478bd9Sstevel@tonic-gate 16437c478bd9Sstevel@tonic-gate void 16447c478bd9Sstevel@tonic-gate fmd_serd_destroy(fmd_hdl_t *hdl, const char *name) 16457c478bd9Sstevel@tonic-gate { 16467c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 16477c478bd9Sstevel@tonic-gate 16487c478bd9Sstevel@tonic-gate fmd_serd_eng_delete(&mp->mod_serds, name); 16497c478bd9Sstevel@tonic-gate fmd_module_setdirty(mp); 16507c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 16517c478bd9Sstevel@tonic-gate } 16527c478bd9Sstevel@tonic-gate 16537c478bd9Sstevel@tonic-gate int 16547c478bd9Sstevel@tonic-gate fmd_serd_exists(fmd_hdl_t *hdl, const char *name) 16557c478bd9Sstevel@tonic-gate { 16567c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 16577c478bd9Sstevel@tonic-gate int rv = (fmd_serd_eng_lookup(&mp->mod_serds, name) != NULL); 16587c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 16597c478bd9Sstevel@tonic-gate 16607c478bd9Sstevel@tonic-gate return (rv); 16617c478bd9Sstevel@tonic-gate } 16627c478bd9Sstevel@tonic-gate 16637c478bd9Sstevel@tonic-gate void 16647c478bd9Sstevel@tonic-gate fmd_serd_reset(fmd_hdl_t *hdl, const char *name) 16657c478bd9Sstevel@tonic-gate { 16667c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 16677c478bd9Sstevel@tonic-gate fmd_serd_eng_t *sgp; 16687c478bd9Sstevel@tonic-gate 16697c478bd9Sstevel@tonic-gate if ((sgp = fmd_serd_eng_lookup(&mp->mod_serds, name)) == NULL) { 16707c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_SERD_NAME, 16717c478bd9Sstevel@tonic-gate "serd engine '%s' does not exist\n", name); 16727c478bd9Sstevel@tonic-gate } 16737c478bd9Sstevel@tonic-gate 16747c478bd9Sstevel@tonic-gate fmd_serd_eng_reset(sgp); 16757c478bd9Sstevel@tonic-gate fmd_module_setdirty(mp); 16767c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 16777c478bd9Sstevel@tonic-gate } 16787c478bd9Sstevel@tonic-gate 16797c478bd9Sstevel@tonic-gate int 16807c478bd9Sstevel@tonic-gate fmd_serd_record(fmd_hdl_t *hdl, const char *name, fmd_event_t *ep) 16817c478bd9Sstevel@tonic-gate { 16827c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 16837c478bd9Sstevel@tonic-gate fmd_serd_eng_t *sgp; 16847c478bd9Sstevel@tonic-gate int err; 16857c478bd9Sstevel@tonic-gate 16867c478bd9Sstevel@tonic-gate if ((sgp = fmd_serd_eng_lookup(&mp->mod_serds, name)) == NULL) { 16877c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_SERD_NAME, 16887c478bd9Sstevel@tonic-gate "failed to add record to serd engine '%s'", name); 16897c478bd9Sstevel@tonic-gate } 16907c478bd9Sstevel@tonic-gate 16917c478bd9Sstevel@tonic-gate err = fmd_serd_eng_record(sgp, ep); 16927c478bd9Sstevel@tonic-gate 16937c478bd9Sstevel@tonic-gate if (sgp->sg_flags & FMD_SERD_DIRTY) 16947c478bd9Sstevel@tonic-gate fmd_module_setdirty(mp); 16957c478bd9Sstevel@tonic-gate 16967c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 16977c478bd9Sstevel@tonic-gate return (err); 16987c478bd9Sstevel@tonic-gate } 16997c478bd9Sstevel@tonic-gate 17007c478bd9Sstevel@tonic-gate int 17017c478bd9Sstevel@tonic-gate fmd_serd_fired(fmd_hdl_t *hdl, const char *name) 17027c478bd9Sstevel@tonic-gate { 17037c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 17047c478bd9Sstevel@tonic-gate fmd_serd_eng_t *sgp; 17057c478bd9Sstevel@tonic-gate int err; 17067c478bd9Sstevel@tonic-gate 17077c478bd9Sstevel@tonic-gate if ((sgp = fmd_serd_eng_lookup(&mp->mod_serds, name)) == NULL) { 17087c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_SERD_NAME, 17097c478bd9Sstevel@tonic-gate "serd engine '%s' does not exist\n", name); 17107c478bd9Sstevel@tonic-gate } 17117c478bd9Sstevel@tonic-gate 17127c478bd9Sstevel@tonic-gate err = fmd_serd_eng_fired(sgp); 17137c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 17147c478bd9Sstevel@tonic-gate return (err); 17157c478bd9Sstevel@tonic-gate } 17167c478bd9Sstevel@tonic-gate 17177c478bd9Sstevel@tonic-gate int 17187c478bd9Sstevel@tonic-gate fmd_serd_empty(fmd_hdl_t *hdl, const char *name) 17197c478bd9Sstevel@tonic-gate { 17207c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 17217c478bd9Sstevel@tonic-gate fmd_serd_eng_t *sgp; 17227c478bd9Sstevel@tonic-gate int empty; 17237c478bd9Sstevel@tonic-gate 17247c478bd9Sstevel@tonic-gate if ((sgp = fmd_serd_eng_lookup(&mp->mod_serds, name)) == NULL) { 17257c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_SERD_NAME, 17267c478bd9Sstevel@tonic-gate "serd engine '%s' does not exist\n", name); 17277c478bd9Sstevel@tonic-gate } 17287c478bd9Sstevel@tonic-gate 17297c478bd9Sstevel@tonic-gate empty = fmd_serd_eng_empty(sgp); 17307c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 17317c478bd9Sstevel@tonic-gate return (empty); 17327c478bd9Sstevel@tonic-gate } 17337c478bd9Sstevel@tonic-gate 17347c478bd9Sstevel@tonic-gate pthread_t 17357c478bd9Sstevel@tonic-gate fmd_thr_create(fmd_hdl_t *hdl, void (*func)(void *), void *arg) 17367c478bd9Sstevel@tonic-gate { 17377c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 17387c478bd9Sstevel@tonic-gate fmd_thread_t *tp; 17397c478bd9Sstevel@tonic-gate pthread_t tid; 17407c478bd9Sstevel@tonic-gate 17417c478bd9Sstevel@tonic-gate if (mp->mod_stats->ms_thrtotal.fmds_value.ui32 >= 17427c478bd9Sstevel@tonic-gate mp->mod_stats->ms_thrlimit.fmds_value.ui32) { 17437c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_THR_LIMIT, "%s request to create an " 17447c478bd9Sstevel@tonic-gate "auxiliary thread exceeds module thread limit (%u)\n", 17457c478bd9Sstevel@tonic-gate mp->mod_name, mp->mod_stats->ms_thrlimit.fmds_value.ui32); 17467c478bd9Sstevel@tonic-gate } 17477c478bd9Sstevel@tonic-gate 17487c478bd9Sstevel@tonic-gate if ((tp = fmd_thread_create(mp, func, arg)) == NULL) { 17497c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_THR_CREATE, 17507c478bd9Sstevel@tonic-gate "failed to create auxiliary thread"); 17517c478bd9Sstevel@tonic-gate } 17527c478bd9Sstevel@tonic-gate 17537c478bd9Sstevel@tonic-gate tid = tp->thr_tid; 17547c478bd9Sstevel@tonic-gate mp->mod_stats->ms_thrtotal.fmds_value.ui32++; 17557c478bd9Sstevel@tonic-gate (void) fmd_idspace_xalloc(mp->mod_threads, tid, tp); 17567c478bd9Sstevel@tonic-gate 17577c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 17587c478bd9Sstevel@tonic-gate return (tid); 17597c478bd9Sstevel@tonic-gate } 17607c478bd9Sstevel@tonic-gate 17617c478bd9Sstevel@tonic-gate void 17627c478bd9Sstevel@tonic-gate fmd_thr_destroy(fmd_hdl_t *hdl, pthread_t tid) 17637c478bd9Sstevel@tonic-gate { 17647c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 17657c478bd9Sstevel@tonic-gate fmd_thread_t *tp; 17667c478bd9Sstevel@tonic-gate int err; 17677c478bd9Sstevel@tonic-gate 17687c478bd9Sstevel@tonic-gate if (pthread_self() == tid) { 17697c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_THR_INVAL, "auxiliary thread tried to " 17707c478bd9Sstevel@tonic-gate "destroy itself (tid %u)\n", tid); 17717c478bd9Sstevel@tonic-gate } 17727c478bd9Sstevel@tonic-gate 17737c478bd9Sstevel@tonic-gate if ((tp = fmd_idspace_getspecific(mp->mod_threads, tid)) == NULL) { 17747c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_THR_INVAL, "auxiliary thread tried to " 17757c478bd9Sstevel@tonic-gate "destroy an invalid thread (tid %u)\n", tid); 17767c478bd9Sstevel@tonic-gate } 17777c478bd9Sstevel@tonic-gate 17787c478bd9Sstevel@tonic-gate /* 17797c478bd9Sstevel@tonic-gate * Wait for the specified thread to exit and then join with it. Since 17807c478bd9Sstevel@tonic-gate * the thread may need to make API calls in order to complete its work 17817c478bd9Sstevel@tonic-gate * we must sleep with the module lock unheld, and then reacquire it. 17827c478bd9Sstevel@tonic-gate */ 17837c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 17847c478bd9Sstevel@tonic-gate err = pthread_join(tid, NULL); 17857c478bd9Sstevel@tonic-gate mp = fmd_api_module_lock(hdl); 17867c478bd9Sstevel@tonic-gate 17877c478bd9Sstevel@tonic-gate /* 17887c478bd9Sstevel@tonic-gate * Since pthread_join() was called without the module lock held, if 17897c478bd9Sstevel@tonic-gate * multiple callers attempted to destroy the same auxiliary thread 17907c478bd9Sstevel@tonic-gate * simultaneously, one will succeed and the others will get ESRCH. 17917c478bd9Sstevel@tonic-gate * Therefore we silently ignore ESRCH but only allow the caller who 17927c478bd9Sstevel@tonic-gate * succeessfully joined with the auxiliary thread to destroy it. 17937c478bd9Sstevel@tonic-gate */ 17947c478bd9Sstevel@tonic-gate if (err != 0 && err != ESRCH) { 17957c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_THR_JOIN, 17967c478bd9Sstevel@tonic-gate "failed to join with auxiliary thread %u\n", tid); 17977c478bd9Sstevel@tonic-gate } 17987c478bd9Sstevel@tonic-gate 17997c478bd9Sstevel@tonic-gate if (err == 0) { 18007c478bd9Sstevel@tonic-gate fmd_thread_destroy(tp, FMD_THREAD_NOJOIN); 18017c478bd9Sstevel@tonic-gate mp->mod_stats->ms_thrtotal.fmds_value.ui32--; 18027c478bd9Sstevel@tonic-gate (void) fmd_idspace_free(mp->mod_threads, tid); 18037c478bd9Sstevel@tonic-gate } 18047c478bd9Sstevel@tonic-gate 18057c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 18067c478bd9Sstevel@tonic-gate } 18077c478bd9Sstevel@tonic-gate 18087c478bd9Sstevel@tonic-gate void 18097c478bd9Sstevel@tonic-gate fmd_thr_signal(fmd_hdl_t *hdl, pthread_t tid) 18107c478bd9Sstevel@tonic-gate { 18117c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 18127c478bd9Sstevel@tonic-gate 18137c478bd9Sstevel@tonic-gate if (tid != mp->mod_thread->thr_tid && 18147c478bd9Sstevel@tonic-gate fmd_idspace_getspecific(mp->mod_threads, tid) == NULL) { 18157c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_THR_INVAL, "tid %u is not a valid " 18167c478bd9Sstevel@tonic-gate "thread id for module %s\n", tid, mp->mod_name); 18177c478bd9Sstevel@tonic-gate } 18187c478bd9Sstevel@tonic-gate 18197c478bd9Sstevel@tonic-gate (void) pthread_kill(tid, fmd.d_thr_sig); 18207c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 18217c478bd9Sstevel@tonic-gate } 18227c478bd9Sstevel@tonic-gate 182325351652SVuong Nguyen void 182425351652SVuong Nguyen fmd_thr_checkpoint(fmd_hdl_t *hdl) 182525351652SVuong Nguyen { 182625351652SVuong Nguyen fmd_module_t *mp = fmd_api_module_lock(hdl); 182725351652SVuong Nguyen pthread_t tid = pthread_self(); 182825351652SVuong Nguyen 182925351652SVuong Nguyen if (tid == mp->mod_thread->thr_tid || 183025351652SVuong Nguyen fmd_idspace_getspecific(mp->mod_threads, tid) == NULL) { 183125351652SVuong Nguyen fmd_api_error(mp, EFMD_THR_INVAL, "tid %u is not a valid " 183225351652SVuong Nguyen "auxiliary thread id for module %s\n", tid, mp->mod_name); 183325351652SVuong Nguyen } 183425351652SVuong Nguyen 183525351652SVuong Nguyen fmd_ckpt_save(mp); 183625351652SVuong Nguyen 183725351652SVuong Nguyen fmd_module_unlock(mp); 183825351652SVuong Nguyen } 183925351652SVuong Nguyen 1840*f6e214c7SGavin Maltby /*ARGSUSED3*/ 1841*f6e214c7SGavin Maltby int 1842*f6e214c7SGavin Maltby fmd_doorthr_create(door_info_t *dip, void *(*crf)(void *), void *crarg, 1843*f6e214c7SGavin Maltby void *cookie) 1844*f6e214c7SGavin Maltby { 1845*f6e214c7SGavin Maltby fmd_thread_t *old_tp, *new_tp; 1846*f6e214c7SGavin Maltby fmd_module_t *mp; 1847*f6e214c7SGavin Maltby pthread_t tid; 1848*f6e214c7SGavin Maltby 1849*f6e214c7SGavin Maltby /* 1850*f6e214c7SGavin Maltby * We're called either during initial door_xcreate or during 1851*f6e214c7SGavin Maltby * a depletion callback. In both cases the current thread 1852*f6e214c7SGavin Maltby * is already setup so we can retrieve the fmd_thread_t. 1853*f6e214c7SGavin Maltby * If not then we panic. The new thread will be associated with 1854*f6e214c7SGavin Maltby * the same module as the old. 1855*f6e214c7SGavin Maltby * 1856*f6e214c7SGavin Maltby * If dip == NULL we're being called as part of the 1857*f6e214c7SGavin Maltby * sysevent_bind_subscriber hack - see comments there. 1858*f6e214c7SGavin Maltby */ 1859*f6e214c7SGavin Maltby if ((old_tp = pthread_getspecific(fmd.d_key)) == NULL) 1860*f6e214c7SGavin Maltby fmd_panic("fmd_doorthr_create from unrecognized thread\n"); 1861*f6e214c7SGavin Maltby 1862*f6e214c7SGavin Maltby mp = old_tp->thr_mod; 1863*f6e214c7SGavin Maltby (void) fmd_api_module_lock((fmd_hdl_t *)mp); 1864*f6e214c7SGavin Maltby 1865*f6e214c7SGavin Maltby if (dip && mp->mod_stats->ms_doorthrtotal.fmds_value.ui32 >= 1866*f6e214c7SGavin Maltby mp->mod_stats->ms_doorthrlimit.fmds_value.ui32) { 1867*f6e214c7SGavin Maltby fmd_module_unlock(mp); 1868*f6e214c7SGavin Maltby (void) fmd_dprintf(FMD_DBG_XPRT, "door server %s for %p " 1869*f6e214c7SGavin Maltby "not attemped - at max\n", 1870*f6e214c7SGavin Maltby dip->di_attributes & DOOR_DEPLETION_CB ? 1871*f6e214c7SGavin Maltby "depletion callback" : "startup", (void *)dip); 1872*f6e214c7SGavin Maltby return (0); 1873*f6e214c7SGavin Maltby } 1874*f6e214c7SGavin Maltby 1875*f6e214c7SGavin Maltby if ((new_tp = fmd_doorthread_create(mp, (fmd_thread_f *)crf, 1876*f6e214c7SGavin Maltby crarg)) != NULL) { 1877*f6e214c7SGavin Maltby tid = new_tp->thr_tid; 1878*f6e214c7SGavin Maltby mp->mod_stats->ms_doorthrtotal.fmds_value.ui32++; 1879*f6e214c7SGavin Maltby (void) fmd_idspace_xalloc(mp->mod_threads, tid, new_tp); 1880*f6e214c7SGavin Maltby } 1881*f6e214c7SGavin Maltby 1882*f6e214c7SGavin Maltby fmd_module_unlock(mp); 1883*f6e214c7SGavin Maltby 1884*f6e214c7SGavin Maltby if (dip) { 1885*f6e214c7SGavin Maltby fmd_dprintf(FMD_DBG_XPRT, "door server startup for %p %s\n", 1886*f6e214c7SGavin Maltby (void *)dip, new_tp ? "successful" : "failed"); 1887*f6e214c7SGavin Maltby } 1888*f6e214c7SGavin Maltby 1889*f6e214c7SGavin Maltby return (new_tp ? 1 : -1); 1890*f6e214c7SGavin Maltby } 1891*f6e214c7SGavin Maltby 1892*f6e214c7SGavin Maltby /*ARGSUSED*/ 1893*f6e214c7SGavin Maltby void 1894*f6e214c7SGavin Maltby fmd_doorthr_setup(void *cookie) 1895*f6e214c7SGavin Maltby { 1896*f6e214c7SGavin Maltby (void) pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); 1897*f6e214c7SGavin Maltby } 1898*f6e214c7SGavin Maltby 18997c478bd9Sstevel@tonic-gate id_t 19007c478bd9Sstevel@tonic-gate fmd_timer_install(fmd_hdl_t *hdl, void *arg, fmd_event_t *ep, hrtime_t delta) 19017c478bd9Sstevel@tonic-gate { 19027c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 19037c478bd9Sstevel@tonic-gate fmd_modtimer_t *t; 19047c478bd9Sstevel@tonic-gate id_t id; 19057c478bd9Sstevel@tonic-gate 19067c478bd9Sstevel@tonic-gate if (delta < 0) { 19077c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_TIMER_INVAL, 19087c478bd9Sstevel@tonic-gate "timer delta %lld is not a valid interval\n", delta); 19097c478bd9Sstevel@tonic-gate } 19107c478bd9Sstevel@tonic-gate 19117c478bd9Sstevel@tonic-gate t = fmd_alloc(sizeof (fmd_modtimer_t), FMD_SLEEP); 19127c478bd9Sstevel@tonic-gate t->mt_mod = mp; 19137c478bd9Sstevel@tonic-gate t->mt_arg = arg; 19147c478bd9Sstevel@tonic-gate t->mt_id = -1; 19157c478bd9Sstevel@tonic-gate 19167c478bd9Sstevel@tonic-gate if ((id = fmd_timerq_install(fmd.d_timers, mp->mod_timerids, 19177c478bd9Sstevel@tonic-gate (fmd_timer_f *)fmd_module_timeout, t, ep, delta)) == -1) { 19187c478bd9Sstevel@tonic-gate fmd_free(t, sizeof (fmd_modtimer_t)); 19197c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_TIMER_LIMIT, 19207c478bd9Sstevel@tonic-gate "failed to install timer +%lld", delta); 19217c478bd9Sstevel@tonic-gate } 19227c478bd9Sstevel@tonic-gate 19237c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 19247c478bd9Sstevel@tonic-gate return (id); 19257c478bd9Sstevel@tonic-gate } 19267c478bd9Sstevel@tonic-gate 19277c478bd9Sstevel@tonic-gate void 19287c478bd9Sstevel@tonic-gate fmd_timer_remove(fmd_hdl_t *hdl, id_t id) 19297c478bd9Sstevel@tonic-gate { 19307c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 19317c478bd9Sstevel@tonic-gate fmd_modtimer_t *t; 19327c478bd9Sstevel@tonic-gate 19337c478bd9Sstevel@tonic-gate if (!fmd_idspace_valid(mp->mod_timerids, id)) { 19347c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_TIMER_INVAL, 19357c478bd9Sstevel@tonic-gate "id %ld is not a valid timer id\n", id); 19367c478bd9Sstevel@tonic-gate } 19377c478bd9Sstevel@tonic-gate 19389dd0f810Scindi /* 19399dd0f810Scindi * If the timer has not fired (t != NULL), remove it from the timer 19409dd0f810Scindi * queue. If the timer has fired (t == NULL), we could be in one of 19419dd0f810Scindi * two situations: a) we are processing the timer callback or b) 19429dd0f810Scindi * the timer event is on the module queue awaiting dispatch. For a), 19439dd0f810Scindi * fmd_timerq_remove() will wait for the timer callback function 19449dd0f810Scindi * to complete and queue an event for dispatch. For a) and b), 19459dd0f810Scindi * we cancel the outstanding timer event from the module's dispatch 19469dd0f810Scindi * queue. 19479dd0f810Scindi */ 19489dd0f810Scindi if ((t = fmd_timerq_remove(fmd.d_timers, mp->mod_timerids, id)) != NULL) 19499dd0f810Scindi fmd_free(t, sizeof (fmd_modtimer_t)); 19507c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 19517c478bd9Sstevel@tonic-gate 19529dd0f810Scindi fmd_eventq_cancel(mp->mod_queue, FMD_EVT_TIMEOUT, (void *)id); 19537c478bd9Sstevel@tonic-gate } 19547c478bd9Sstevel@tonic-gate 1955*f6e214c7SGavin Maltby static nvlist_t * 1956*f6e214c7SGavin Maltby fmd_nvl_create_suspect(fmd_hdl_t *hdl, const char *class, 1957*f6e214c7SGavin Maltby uint8_t certainty, nvlist_t *asru, nvlist_t *fru, nvlist_t *rsrc, 1958*f6e214c7SGavin Maltby const char *pfx, boolean_t chkpfx) 19597c478bd9Sstevel@tonic-gate { 19609dd0f810Scindi fmd_module_t *mp; 19617c478bd9Sstevel@tonic-gate nvlist_t *nvl; 19627c478bd9Sstevel@tonic-gate 19639dd0f810Scindi mp = fmd_api_module_lock(hdl); 1964*f6e214c7SGavin Maltby if (class == NULL || class[0] == '\0' || 1965*f6e214c7SGavin Maltby chkpfx == B_TRUE && strncmp(class, pfx, strlen(pfx)) != 0) 1966*f6e214c7SGavin Maltby fmd_api_error(mp, EFMD_NVL_INVAL, "invalid %s class: '%s'\n", 1967*f6e214c7SGavin Maltby pfx, class ? class : "(empty)"); 19687c478bd9Sstevel@tonic-gate 1969b7d3956bSstephh nvl = fmd_protocol_fault(class, certainty, asru, fru, rsrc, NULL); 197024db4641Seschrock 197124db4641Seschrock fmd_module_unlock(mp); 197224db4641Seschrock 19737c478bd9Sstevel@tonic-gate return (nvl); 19747c478bd9Sstevel@tonic-gate } 19757c478bd9Sstevel@tonic-gate 1976*f6e214c7SGavin Maltby nvlist_t * 1977*f6e214c7SGavin Maltby fmd_nvl_create_fault(fmd_hdl_t *hdl, const char *class, 1978*f6e214c7SGavin Maltby uint8_t certainty, nvlist_t *asru, nvlist_t *fru, nvlist_t *rsrc) 1979*f6e214c7SGavin Maltby { 1980*f6e214c7SGavin Maltby /* 1981*f6e214c7SGavin Maltby * We can't enforce that callers only specifiy classes matching 1982*f6e214c7SGavin Maltby * fault.* since there are already a number of modules that 1983*f6e214c7SGavin Maltby * use fmd_nvl_create_fault to create a defect event. Since 1984*f6e214c7SGavin Maltby * fmd_nvl_create_{fault,defect} are equivalent, for now anyway, 1985*f6e214c7SGavin Maltby * no harm is done. So call fmd_nvl_create_suspect with last 1986*f6e214c7SGavin Maltby * argument B_FALSE. 1987*f6e214c7SGavin Maltby */ 1988*f6e214c7SGavin Maltby return (fmd_nvl_create_suspect(hdl, class, certainty, asru, 1989*f6e214c7SGavin Maltby fru, rsrc, FM_FAULT_CLASS ".", B_FALSE)); 1990*f6e214c7SGavin Maltby } 1991*f6e214c7SGavin Maltby 1992*f6e214c7SGavin Maltby nvlist_t * 1993*f6e214c7SGavin Maltby fmd_nvl_create_defect(fmd_hdl_t *hdl, const char *class, 1994*f6e214c7SGavin Maltby uint8_t certainty, nvlist_t *asru, nvlist_t *fru, nvlist_t *rsrc) 1995*f6e214c7SGavin Maltby { 1996*f6e214c7SGavin Maltby return (fmd_nvl_create_suspect(hdl, class, certainty, asru, 1997*f6e214c7SGavin Maltby fru, rsrc, FM_DEFECT_CLASS ".", B_TRUE)); 1998*f6e214c7SGavin Maltby } 1999*f6e214c7SGavin Maltby 2000*f6e214c7SGavin Maltby const nvlist_t * 2001*f6e214c7SGavin Maltby fmd_hdl_fmauth(fmd_hdl_t *hdl) 2002*f6e214c7SGavin Maltby { 2003*f6e214c7SGavin Maltby fmd_module_t *mp = fmd_api_module_lock(hdl); 2004*f6e214c7SGavin Maltby const nvlist_t *auth; 2005*f6e214c7SGavin Maltby 2006*f6e214c7SGavin Maltby auth = (const nvlist_t *)fmd.d_rmod->mod_fmri; 2007*f6e214c7SGavin Maltby 2008*f6e214c7SGavin Maltby fmd_module_unlock(mp); 2009*f6e214c7SGavin Maltby 2010*f6e214c7SGavin Maltby return (auth); 2011*f6e214c7SGavin Maltby } 2012*f6e214c7SGavin Maltby 2013*f6e214c7SGavin Maltby const nvlist_t * 2014*f6e214c7SGavin Maltby fmd_hdl_modauth(fmd_hdl_t *hdl) 2015*f6e214c7SGavin Maltby { 2016*f6e214c7SGavin Maltby fmd_module_t *mp = fmd_api_module_lock(hdl); 2017*f6e214c7SGavin Maltby const nvlist_t *auth; 2018*f6e214c7SGavin Maltby 2019*f6e214c7SGavin Maltby auth = (const nvlist_t *)mp->mod_fmri; 2020*f6e214c7SGavin Maltby 2021*f6e214c7SGavin Maltby fmd_module_unlock(mp); 2022*f6e214c7SGavin Maltby 2023*f6e214c7SGavin Maltby return (auth); 2024*f6e214c7SGavin Maltby } 2025*f6e214c7SGavin Maltby 2026*f6e214c7SGavin Maltby 20277c478bd9Sstevel@tonic-gate int 20287c478bd9Sstevel@tonic-gate fmd_nvl_class_match(fmd_hdl_t *hdl, nvlist_t *nvl, const char *pattern) 20297c478bd9Sstevel@tonic-gate { 20307c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 20317c478bd9Sstevel@tonic-gate char *class; 20327c478bd9Sstevel@tonic-gate int rv; 20337c478bd9Sstevel@tonic-gate 20347c478bd9Sstevel@tonic-gate rv = (nvl != NULL && nvlist_lookup_string(nvl, 20357c478bd9Sstevel@tonic-gate FM_CLASS, &class) == 0 && fmd_strmatch(class, pattern)); 20367c478bd9Sstevel@tonic-gate 20377c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 20387c478bd9Sstevel@tonic-gate return (rv); 20397c478bd9Sstevel@tonic-gate } 20407c478bd9Sstevel@tonic-gate 20417c478bd9Sstevel@tonic-gate int 20427c478bd9Sstevel@tonic-gate fmd_nvl_fmri_expand(fmd_hdl_t *hdl, nvlist_t *nvl) 20437c478bd9Sstevel@tonic-gate { 20447c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 20457c478bd9Sstevel@tonic-gate int rv; 20467c478bd9Sstevel@tonic-gate 20477c478bd9Sstevel@tonic-gate if (nvl == NULL) { 20487c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_NVL_INVAL, 20497c478bd9Sstevel@tonic-gate "invalid nvlist %p\n", (void *)nvl); 20507c478bd9Sstevel@tonic-gate } 20517c478bd9Sstevel@tonic-gate 20527c478bd9Sstevel@tonic-gate rv = fmd_fmri_expand(nvl); 20537c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 20547c478bd9Sstevel@tonic-gate return (rv); 20557c478bd9Sstevel@tonic-gate } 20567c478bd9Sstevel@tonic-gate 20577c478bd9Sstevel@tonic-gate int 20587c478bd9Sstevel@tonic-gate fmd_nvl_fmri_present(fmd_hdl_t *hdl, nvlist_t *nvl) 20597c478bd9Sstevel@tonic-gate { 20607c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 20617c478bd9Sstevel@tonic-gate int rv; 20627c478bd9Sstevel@tonic-gate 20637c478bd9Sstevel@tonic-gate if (nvl == NULL) { 20647c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_NVL_INVAL, 20657c478bd9Sstevel@tonic-gate "invalid nvlist %p\n", (void *)nvl); 20667c478bd9Sstevel@tonic-gate } 20677c478bd9Sstevel@tonic-gate 20687c478bd9Sstevel@tonic-gate rv = fmd_fmri_present(nvl); 20697c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 20707c478bd9Sstevel@tonic-gate 20717c478bd9Sstevel@tonic-gate if (rv < 0) { 20727c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_FMRI_OP, "invalid fmri for " 20737c478bd9Sstevel@tonic-gate "fmd_nvl_fmri_present\n"); 20747c478bd9Sstevel@tonic-gate } 20757c478bd9Sstevel@tonic-gate 20767c478bd9Sstevel@tonic-gate return (rv); 20777c478bd9Sstevel@tonic-gate } 20787c478bd9Sstevel@tonic-gate 20797c478bd9Sstevel@tonic-gate int 208025c6ff4bSstephh fmd_nvl_fmri_replaced(fmd_hdl_t *hdl, nvlist_t *nvl) 208125c6ff4bSstephh { 208225c6ff4bSstephh fmd_module_t *mp = fmd_api_module_lock(hdl); 208325c6ff4bSstephh int rv; 208425c6ff4bSstephh 208525c6ff4bSstephh if (nvl == NULL) { 208625c6ff4bSstephh fmd_api_error(mp, EFMD_NVL_INVAL, 208725c6ff4bSstephh "invalid nvlist %p\n", (void *)nvl); 208825c6ff4bSstephh } 208925c6ff4bSstephh 209025c6ff4bSstephh rv = fmd_fmri_replaced(nvl); 209125c6ff4bSstephh fmd_module_unlock(mp); 209225c6ff4bSstephh 209325c6ff4bSstephh return (rv); 209425c6ff4bSstephh } 209525c6ff4bSstephh 209625c6ff4bSstephh int 20977c478bd9Sstevel@tonic-gate fmd_nvl_fmri_unusable(fmd_hdl_t *hdl, nvlist_t *nvl) 20987c478bd9Sstevel@tonic-gate { 20997c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 21007c478bd9Sstevel@tonic-gate int rv; 21017c478bd9Sstevel@tonic-gate 21027c478bd9Sstevel@tonic-gate if (nvl == NULL) { 21037c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_NVL_INVAL, 21047c478bd9Sstevel@tonic-gate "invalid nvlist %p\n", (void *)nvl); 21057c478bd9Sstevel@tonic-gate } 21067c478bd9Sstevel@tonic-gate 21077c478bd9Sstevel@tonic-gate rv = fmd_fmri_unusable(nvl); 21087c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 21097c478bd9Sstevel@tonic-gate 21107c478bd9Sstevel@tonic-gate if (rv < 0) { 21117c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_FMRI_OP, "invalid fmri for " 21127c478bd9Sstevel@tonic-gate "fmd_nvl_fmri_unusable\n"); 21137c478bd9Sstevel@tonic-gate } 21147c478bd9Sstevel@tonic-gate 21157c478bd9Sstevel@tonic-gate return (rv); 21167c478bd9Sstevel@tonic-gate } 21177c478bd9Sstevel@tonic-gate 21187c478bd9Sstevel@tonic-gate int 2119e4b86885SCheng Sean Ye fmd_nvl_fmri_retire(fmd_hdl_t *hdl, nvlist_t *nvl) 2120e4b86885SCheng Sean Ye { 2121e4b86885SCheng Sean Ye fmd_module_t *mp = fmd_api_module_lock(hdl); 2122e4b86885SCheng Sean Ye int rv; 2123e4b86885SCheng Sean Ye 2124e4b86885SCheng Sean Ye if (nvl == NULL) { 2125e4b86885SCheng Sean Ye fmd_api_error(mp, EFMD_NVL_INVAL, 2126e4b86885SCheng Sean Ye "invalid nvlist %p\n", (void *)nvl); 2127e4b86885SCheng Sean Ye } 2128e4b86885SCheng Sean Ye 2129e4b86885SCheng Sean Ye rv = fmd_fmri_retire(nvl); 2130e4b86885SCheng Sean Ye fmd_module_unlock(mp); 2131e4b86885SCheng Sean Ye 2132e4b86885SCheng Sean Ye return (rv); 2133e4b86885SCheng Sean Ye } 2134e4b86885SCheng Sean Ye 2135e4b86885SCheng Sean Ye int 2136e4b86885SCheng Sean Ye fmd_nvl_fmri_unretire(fmd_hdl_t *hdl, nvlist_t *nvl) 2137e4b86885SCheng Sean Ye { 2138e4b86885SCheng Sean Ye fmd_module_t *mp = fmd_api_module_lock(hdl); 2139e4b86885SCheng Sean Ye int rv; 2140e4b86885SCheng Sean Ye 2141e4b86885SCheng Sean Ye if (nvl == NULL) { 2142e4b86885SCheng Sean Ye fmd_api_error(mp, EFMD_NVL_INVAL, 2143e4b86885SCheng Sean Ye "invalid nvlist %p\n", (void *)nvl); 2144e4b86885SCheng Sean Ye } 2145e4b86885SCheng Sean Ye 2146e4b86885SCheng Sean Ye rv = fmd_fmri_unretire(nvl); 2147e4b86885SCheng Sean Ye fmd_module_unlock(mp); 2148e4b86885SCheng Sean Ye 2149e4b86885SCheng Sean Ye return (rv); 2150e4b86885SCheng Sean Ye } 2151e4b86885SCheng Sean Ye 2152e4b86885SCheng Sean Ye int 215325c6ff4bSstephh fmd_nvl_fmri_service_state(fmd_hdl_t *hdl, nvlist_t *nvl) 21547aec1d6eScindi { 21557aec1d6eScindi fmd_module_t *mp = fmd_api_module_lock(hdl); 215625c6ff4bSstephh int rv; 21577aec1d6eScindi 21587aec1d6eScindi if (nvl == NULL) { 21597aec1d6eScindi fmd_api_error(mp, EFMD_NVL_INVAL, 21607aec1d6eScindi "invalid nvlist %p\n", (void *)nvl); 21617aec1d6eScindi } 21627aec1d6eScindi 216325c6ff4bSstephh rv = fmd_fmri_service_state(nvl); 216425c6ff4bSstephh if (rv < 0) 216525c6ff4bSstephh rv = fmd_fmri_unusable(nvl) ? FMD_SERVICE_STATE_UNUSABLE : 216625c6ff4bSstephh FMD_SERVICE_STATE_OK; 216725c6ff4bSstephh fmd_module_unlock(mp); 216825c6ff4bSstephh 216925c6ff4bSstephh if (rv < 0) { 217025c6ff4bSstephh fmd_api_error(mp, EFMD_FMRI_OP, "invalid fmri for " 217125c6ff4bSstephh "fmd_nvl_fmri_service_state\n"); 21727aec1d6eScindi } 21737aec1d6eScindi 217425c6ff4bSstephh return (rv); 217525c6ff4bSstephh } 217625c6ff4bSstephh 217725c6ff4bSstephh typedef struct { 217825c6ff4bSstephh const char *class; 217925c6ff4bSstephh int *rvp; 218025c6ff4bSstephh } fmd_has_fault_arg_t; 218125c6ff4bSstephh 218225c6ff4bSstephh static void 218325c6ff4bSstephh fmd_rsrc_has_fault(fmd_asru_link_t *alp, void *arg) 218425c6ff4bSstephh { 218525c6ff4bSstephh fmd_has_fault_arg_t *fhfp = (fmd_has_fault_arg_t *)arg; 218625c6ff4bSstephh char *class; 218725c6ff4bSstephh 218825c6ff4bSstephh if (fhfp->class == NULL) { 218925c6ff4bSstephh if (alp->al_flags & FMD_ASRU_FAULTY) 219025c6ff4bSstephh *fhfp->rvp = 1; 219125c6ff4bSstephh } else { 219225c6ff4bSstephh if ((alp->al_flags & FMD_ASRU_FAULTY) && 219325c6ff4bSstephh alp->al_event != NULL && nvlist_lookup_string(alp->al_event, 219425c6ff4bSstephh FM_CLASS, &class) == 0 && fmd_strmatch(class, fhfp->class)) 219525c6ff4bSstephh *fhfp->rvp = 1; 219625c6ff4bSstephh } 219725c6ff4bSstephh } 219825c6ff4bSstephh 219925c6ff4bSstephh int 220025c6ff4bSstephh fmd_nvl_fmri_has_fault(fmd_hdl_t *hdl, nvlist_t *nvl, int type, char *class) 220125c6ff4bSstephh { 220225c6ff4bSstephh fmd_module_t *mp = fmd_api_module_lock(hdl); 220325c6ff4bSstephh fmd_asru_hash_t *ahp = fmd.d_asrus; 220425c6ff4bSstephh int rv = 0; 220525c6ff4bSstephh char *name; 220625c6ff4bSstephh int namelen; 220725c6ff4bSstephh fmd_has_fault_arg_t fhf; 220825c6ff4bSstephh 220925c6ff4bSstephh if (nvl == NULL) { 221025c6ff4bSstephh fmd_api_error(mp, EFMD_NVL_INVAL, 221125c6ff4bSstephh "invalid nvlist %p\n", (void *)nvl); 221225c6ff4bSstephh } 221325c6ff4bSstephh if ((namelen = fmd_fmri_nvl2str(nvl, NULL, 0)) == -1) 221425c6ff4bSstephh fmd_api_error(mp, EFMD_NVL_INVAL, 221525c6ff4bSstephh "invalid nvlist: %p\n", (void *)nvl); 221625c6ff4bSstephh name = fmd_alloc(namelen + 1, FMD_SLEEP); 221725c6ff4bSstephh if (fmd_fmri_nvl2str(nvl, name, namelen + 1) == -1) { 221825c6ff4bSstephh if (name != NULL) 221925c6ff4bSstephh fmd_free(name, namelen + 1); 222025c6ff4bSstephh fmd_api_error(mp, EFMD_NVL_INVAL, 222125c6ff4bSstephh "invalid nvlist: %p\n", (void *)nvl); 222225c6ff4bSstephh } 222325c6ff4bSstephh 222425c6ff4bSstephh fhf.class = class; 222525c6ff4bSstephh fhf.rvp = &rv; 222625c6ff4bSstephh if (type == FMD_HAS_FAULT_RESOURCE) 222725c6ff4bSstephh fmd_asru_hash_apply_by_rsrc(ahp, name, fmd_rsrc_has_fault, 222825c6ff4bSstephh &fhf); 222925c6ff4bSstephh else if (type == FMD_HAS_FAULT_ASRU) 223025c6ff4bSstephh fmd_asru_hash_apply_by_asru(ahp, name, fmd_rsrc_has_fault, 223125c6ff4bSstephh &fhf); 223225c6ff4bSstephh else if (type == FMD_HAS_FAULT_FRU) 223325c6ff4bSstephh fmd_asru_hash_apply_by_fru(ahp, name, fmd_rsrc_has_fault, 223425c6ff4bSstephh &fhf); 223525c6ff4bSstephh 223625c6ff4bSstephh if (name != NULL) 223725c6ff4bSstephh fmd_free(name, namelen + 1); 22387aec1d6eScindi fmd_module_unlock(mp); 22397aec1d6eScindi return (rv); 22407aec1d6eScindi } 22417aec1d6eScindi 22427aec1d6eScindi int 22437c478bd9Sstevel@tonic-gate fmd_nvl_fmri_contains(fmd_hdl_t *hdl, nvlist_t *n1, nvlist_t *n2) 22447c478bd9Sstevel@tonic-gate { 22457c478bd9Sstevel@tonic-gate fmd_module_t *mp = fmd_api_module_lock(hdl); 22467c478bd9Sstevel@tonic-gate int rv; 22477c478bd9Sstevel@tonic-gate 22487c478bd9Sstevel@tonic-gate if (n1 == NULL || n2 == NULL) { 22497c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_NVL_INVAL, 22507c478bd9Sstevel@tonic-gate "invalid nvlist(s): %p, %p\n", (void *)n1, (void *)n2); 22517c478bd9Sstevel@tonic-gate } 22527c478bd9Sstevel@tonic-gate 22537c478bd9Sstevel@tonic-gate rv = fmd_fmri_contains(n1, n2); 22547c478bd9Sstevel@tonic-gate fmd_module_unlock(mp); 22557c478bd9Sstevel@tonic-gate 22567c478bd9Sstevel@tonic-gate if (rv < 0) { 22577c478bd9Sstevel@tonic-gate fmd_api_error(mp, EFMD_FMRI_OP, "invalid fmri for " 22587c478bd9Sstevel@tonic-gate "fmd_nvl_fmri_contains\n"); 22597c478bd9Sstevel@tonic-gate } 22607c478bd9Sstevel@tonic-gate 22617c478bd9Sstevel@tonic-gate return (rv); 22627c478bd9Sstevel@tonic-gate } 2263d9638e54Smws 2264d9638e54Smws nvlist_t * 2265d9638e54Smws fmd_nvl_fmri_translate(fmd_hdl_t *hdl, nvlist_t *fmri, nvlist_t *auth) 2266d9638e54Smws { 2267d9638e54Smws fmd_module_t *mp = fmd_api_module_lock(hdl); 2268d9638e54Smws nvlist_t *xfmri; 2269d9638e54Smws 2270d9638e54Smws if (fmri == NULL || auth == NULL) { 2271d9638e54Smws fmd_api_error(mp, EFMD_NVL_INVAL, 2272d9638e54Smws "invalid nvlist(s): %p, %p\n", (void *)fmri, (void *)auth); 2273d9638e54Smws } 2274d9638e54Smws 2275d9638e54Smws xfmri = fmd_fmri_translate(fmri, auth); 2276d9638e54Smws fmd_module_unlock(mp); 2277d9638e54Smws return (xfmri); 2278d9638e54Smws } 2279d9638e54Smws 22809af3851aSeschrock static int 22819af3851aSeschrock fmd_nvl_op_init(nv_alloc_t *ops, va_list ap) 22829af3851aSeschrock { 22839af3851aSeschrock fmd_module_t *mp = va_arg(ap, fmd_module_t *); 22849af3851aSeschrock 22859af3851aSeschrock ops->nva_arg = mp; 22869af3851aSeschrock 22879af3851aSeschrock return (0); 22889af3851aSeschrock } 22899af3851aSeschrock 22909af3851aSeschrock static void * 22919af3851aSeschrock fmd_nvl_op_alloc_sleep(nv_alloc_t *ops, size_t size) 22929af3851aSeschrock { 22939af3851aSeschrock fmd_module_t *mp = ops->nva_arg; 22949af3851aSeschrock 22959af3851aSeschrock return (fmd_hdl_alloc_locked(mp, size, FMD_SLEEP)); 22969af3851aSeschrock } 22979af3851aSeschrock 22989af3851aSeschrock static void * 22999af3851aSeschrock fmd_nvl_op_alloc_nosleep(nv_alloc_t *ops, size_t size) 23009af3851aSeschrock { 23019af3851aSeschrock fmd_module_t *mp = ops->nva_arg; 23029af3851aSeschrock 23039af3851aSeschrock return (fmd_hdl_alloc_locked(mp, size, FMD_NOSLEEP)); 23049af3851aSeschrock } 23059af3851aSeschrock 23069af3851aSeschrock static void 23079af3851aSeschrock fmd_nvl_op_free(nv_alloc_t *ops, void *data, size_t size) 23089af3851aSeschrock { 23099af3851aSeschrock fmd_module_t *mp = ops->nva_arg; 23109af3851aSeschrock 23119af3851aSeschrock fmd_hdl_free_locked(mp, data, size); 23129af3851aSeschrock } 23139af3851aSeschrock 23149af3851aSeschrock nv_alloc_ops_t fmd_module_nva_ops_sleep = { 23159af3851aSeschrock fmd_nvl_op_init, 23169af3851aSeschrock NULL, 23179af3851aSeschrock fmd_nvl_op_alloc_sleep, 23189af3851aSeschrock fmd_nvl_op_free, 23199af3851aSeschrock NULL 23209af3851aSeschrock }; 23219af3851aSeschrock 23229af3851aSeschrock nv_alloc_ops_t fmd_module_nva_ops_nosleep = { 23239af3851aSeschrock fmd_nvl_op_init, 23249af3851aSeschrock NULL, 23259af3851aSeschrock fmd_nvl_op_alloc_nosleep, 23269af3851aSeschrock fmd_nvl_op_free, 23279af3851aSeschrock NULL 23289af3851aSeschrock }; 23299af3851aSeschrock 23309af3851aSeschrock nvlist_t * 23319af3851aSeschrock fmd_nvl_alloc(fmd_hdl_t *hdl, int flags) 23329af3851aSeschrock { 23339af3851aSeschrock fmd_module_t *mp = fmd_api_module_lock(hdl); 23349af3851aSeschrock nv_alloc_t *nva; 23359af3851aSeschrock nvlist_t *nvl; 23369af3851aSeschrock int ret; 23379af3851aSeschrock 23389af3851aSeschrock if (flags == FMD_SLEEP) 23399af3851aSeschrock nva = &mp->mod_nva_sleep; 23409af3851aSeschrock else 23419af3851aSeschrock nva = &mp->mod_nva_nosleep; 23429af3851aSeschrock 23439af3851aSeschrock ret = nvlist_xalloc(&nvl, NV_UNIQUE_NAME, nva); 23449af3851aSeschrock 23459af3851aSeschrock fmd_module_unlock(mp); 23469af3851aSeschrock 23479af3851aSeschrock if (ret != 0) 23489af3851aSeschrock return (NULL); 23499af3851aSeschrock else 23509af3851aSeschrock return (nvl); 23519af3851aSeschrock } 23529af3851aSeschrock 23539af3851aSeschrock nvlist_t * 23549af3851aSeschrock fmd_nvl_dup(fmd_hdl_t *hdl, nvlist_t *src, int flags) 23559af3851aSeschrock { 23569af3851aSeschrock fmd_module_t *mp = fmd_api_module_lock(hdl); 23579af3851aSeschrock nv_alloc_t *nva; 23589af3851aSeschrock nvlist_t *nvl; 23599af3851aSeschrock int ret; 23609af3851aSeschrock 23619af3851aSeschrock if (flags == FMD_SLEEP) 23629af3851aSeschrock nva = &mp->mod_nva_sleep; 23639af3851aSeschrock else 23649af3851aSeschrock nva = &mp->mod_nva_nosleep; 23659af3851aSeschrock 23669af3851aSeschrock ret = nvlist_xdup(src, &nvl, nva); 23679af3851aSeschrock 23689af3851aSeschrock fmd_module_unlock(mp); 23699af3851aSeschrock 23709af3851aSeschrock if (ret != 0) 23719af3851aSeschrock return (NULL); 23729af3851aSeschrock else 23739af3851aSeschrock return (nvl); 23749af3851aSeschrock } 23759af3851aSeschrock 2376e5dcf7beSRobert Johnston /*ARGSUSED*/ 2377e5dcf7beSRobert Johnston void 2378e5dcf7beSRobert Johnston fmd_repair_fru(fmd_hdl_t *hdl, const char *fmri) 2379e5dcf7beSRobert Johnston { 2380e5dcf7beSRobert Johnston int err; 23816e1fa242SStephen Hanson fmd_asru_rep_arg_t fara; 2382e5dcf7beSRobert Johnston 23836e1fa242SStephen Hanson fara.fara_reason = FMD_ASRU_REPAIRED; 23846e1fa242SStephen Hanson fara.fara_bywhat = FARA_BY_FRU; 23856e1fa242SStephen Hanson fara.fara_rval = &err; 2386e5dcf7beSRobert Johnston fmd_asru_hash_apply_by_fru(fmd.d_asrus, (char *)fmri, 23876e1fa242SStephen Hanson fmd_asru_repaired, &fara); 2388e5dcf7beSRobert Johnston } 2389e5dcf7beSRobert Johnston 2390a62774dfSSinanallur Balasubramanian /*ARGSUSED*/ 2391a62774dfSSinanallur Balasubramanian int 2392a62774dfSSinanallur Balasubramanian fmd_repair_asru(fmd_hdl_t *hdl, const char *fmri) 2393a62774dfSSinanallur Balasubramanian { 2394a62774dfSSinanallur Balasubramanian int err = FARA_ERR_RSRCNOTF; 2395a62774dfSSinanallur Balasubramanian fmd_asru_rep_arg_t fara; 2396a62774dfSSinanallur Balasubramanian 2397a62774dfSSinanallur Balasubramanian fara.fara_reason = FMD_ASRU_REPAIRED; 2398a62774dfSSinanallur Balasubramanian fara.fara_rval = &err; 2399a62774dfSSinanallur Balasubramanian fara.fara_uuid = NULL; 2400a62774dfSSinanallur Balasubramanian fara.fara_bywhat = FARA_BY_ASRU; 2401a62774dfSSinanallur Balasubramanian fmd_asru_hash_apply_by_asru(fmd.d_asrus, fmri, 2402a62774dfSSinanallur Balasubramanian fmd_asru_repaired, &fara); 2403a62774dfSSinanallur Balasubramanian return (err); 2404a62774dfSSinanallur Balasubramanian } 2405a62774dfSSinanallur Balasubramanian 2406d9638e54Smws int 2407d9638e54Smws fmd_event_local(fmd_hdl_t *hdl, fmd_event_t *ep) 2408d9638e54Smws { 2409d9638e54Smws if (hdl == NULL || ep == NULL) { 2410d9638e54Smws fmd_api_error(fmd_api_module_lock(hdl), EFMD_EVENT_INVAL, 2411d9638e54Smws "NULL parameter specified to fmd_event_local\n"); 2412d9638e54Smws } 2413d9638e54Smws 2414d9638e54Smws return (((fmd_event_impl_t *)ep)->ev_flags & FMD_EVF_LOCAL); 2415d9638e54Smws } 2416d9638e54Smws 241724db4641Seschrock /*ARGSUSED*/ 241824db4641Seschrock uint64_t 241924db4641Seschrock fmd_event_ena_create(fmd_hdl_t *hdl) 242024db4641Seschrock { 242124db4641Seschrock return (fmd_ena()); 242224db4641Seschrock } 242324db4641Seschrock 2424d9638e54Smws fmd_xprt_t * 2425d9638e54Smws fmd_xprt_open(fmd_hdl_t *hdl, uint_t flags, nvlist_t *auth, void *data) 2426d9638e54Smws { 2427d9638e54Smws fmd_module_t *mp = fmd_api_module_lock(hdl); 2428d9638e54Smws fmd_xprt_t *xp; 2429d9638e54Smws 2430d9638e54Smws if (flags & ~FMD_XPRT_CMASK) { 2431d9638e54Smws fmd_api_error(mp, EFMD_XPRT_INVAL, 2432d9638e54Smws "invalid transport flags 0x%x\n", flags); 2433d9638e54Smws } 2434d9638e54Smws 2435d9638e54Smws if ((flags & FMD_XPRT_RDWR) != FMD_XPRT_RDWR && 2436d9638e54Smws (flags & FMD_XPRT_RDWR) != FMD_XPRT_RDONLY) { 2437d9638e54Smws fmd_api_error(mp, EFMD_XPRT_INVAL, 2438d9638e54Smws "cannot open write-only transport\n"); 2439d9638e54Smws } 2440d9638e54Smws 2441d9638e54Smws if (mp->mod_stats->ms_xprtopen.fmds_value.ui32 >= 2442d9638e54Smws mp->mod_stats->ms_xprtlimit.fmds_value.ui32) { 2443d9638e54Smws fmd_api_error(mp, EFMD_XPRT_LIMIT, "%s request to create a " 2444d9638e54Smws "transport exceeds module transport limit (%u)\n", 2445d9638e54Smws mp->mod_name, mp->mod_stats->ms_xprtlimit.fmds_value.ui32); 2446d9638e54Smws } 2447d9638e54Smws 2448d9638e54Smws if ((xp = fmd_xprt_create(mp, flags, auth, data)) == NULL) 2449d9638e54Smws fmd_api_error(mp, errno, "cannot create transport"); 2450d9638e54Smws 2451d9638e54Smws fmd_module_unlock(mp); 2452d9638e54Smws return (xp); 2453d9638e54Smws } 2454d9638e54Smws 2455d9638e54Smws void 2456d9638e54Smws fmd_xprt_close(fmd_hdl_t *hdl, fmd_xprt_t *xp) 2457d9638e54Smws { 2458d9638e54Smws fmd_module_t *mp = fmd_api_module_lock(hdl); 2459d9638e54Smws fmd_xprt_impl_t *xip = fmd_api_transport_impl(hdl, xp); 2460d9638e54Smws 2461d9638e54Smws /* 2462d9638e54Smws * Although this could be supported, it doesn't seem necessary or worth 2463d9638e54Smws * the trouble. For now, just detect this and trigger a module abort. 2464d9638e54Smws * If it is needed, transports should grow reference counts and a new 2465d9638e54Smws * event type will need to be enqueued for the main thread to reap it. 2466d9638e54Smws */ 2467d9638e54Smws if (xip->xi_thread != NULL && 2468d9638e54Smws xip->xi_thread->thr_tid == pthread_self()) { 2469d9638e54Smws fmd_api_error(mp, EFMD_XPRT_INVAL, 2470d9638e54Smws "fmd_xprt_close() cannot be called from fmdo_send()\n"); 2471d9638e54Smws } 2472d9638e54Smws 2473d9638e54Smws fmd_xprt_destroy(xp); 2474d9638e54Smws fmd_module_unlock(mp); 2475d9638e54Smws } 2476d9638e54Smws 2477d9638e54Smws void 2478d9638e54Smws fmd_xprt_post(fmd_hdl_t *hdl, fmd_xprt_t *xp, nvlist_t *nvl, hrtime_t hrt) 2479d9638e54Smws { 24807793aa8bSEric Schrock nv_alloc_t *nva = nvlist_lookup_nv_alloc(nvl); 24817793aa8bSEric Schrock fmd_module_t *mp = fmd_api_module(hdl); 2482d9638e54Smws fmd_xprt_impl_t *xip = fmd_api_transport_impl(hdl, xp); 24837793aa8bSEric Schrock nvlist_t *tmp; 24847793aa8bSEric Schrock 24857793aa8bSEric Schrock /* 24867793aa8bSEric Schrock * If this event was allocated using the module-specific nvlist ops, we 24877793aa8bSEric Schrock * need to create a copy using the standard fmd nvlist ops. Otherwise, 24887793aa8bSEric Schrock * the event may persist after the module has been unloaded and we'll 24897793aa8bSEric Schrock * die when attempting to free the nvlist. 24907793aa8bSEric Schrock */ 24917793aa8bSEric Schrock if (nva == &mp->mod_nva_sleep || nva == &mp->mod_nva_nosleep) { 24927793aa8bSEric Schrock (void) nvlist_xdup(nvl, &tmp, &fmd.d_nva); 24937793aa8bSEric Schrock nvlist_free(nvl); 24947793aa8bSEric Schrock nvl = tmp; 24957793aa8bSEric Schrock } 2496d9638e54Smws 2497d9638e54Smws /* 2498d9638e54Smws * fmd_xprt_recv() must block during startup waiting for fmd to globally 2499d9638e54Smws * clear FMD_XPRT_DSUSPENDED. As such, we can't allow it to be called 2500d9638e54Smws * from a module's _fmd_init() routine, because that would block 2501d9638e54Smws * fmd from completing initial module loading, resulting in a deadlock. 2502d9638e54Smws */ 2503d9638e54Smws if ((xip->xi_flags & FMD_XPRT_ISUSPENDED) && 2504d9638e54Smws (pthread_self() == xip->xi_queue->eq_mod->mod_thread->thr_tid)) { 2505d9638e54Smws fmd_api_error(fmd_api_module_lock(hdl), EFMD_XPRT_INVAL, 2506d9638e54Smws "fmd_xprt_post() cannot be called from _fmd_init()\n"); 2507d9638e54Smws } 2508d9638e54Smws 250925351652SVuong Nguyen fmd_xprt_recv(xp, nvl, hrt, FMD_B_FALSE); 251025351652SVuong Nguyen } 251125351652SVuong Nguyen 251225351652SVuong Nguyen void 251325351652SVuong Nguyen fmd_xprt_log(fmd_hdl_t *hdl, fmd_xprt_t *xp, nvlist_t *nvl, hrtime_t hrt) 251425351652SVuong Nguyen { 251525351652SVuong Nguyen fmd_xprt_impl_t *xip = fmd_api_transport_impl(hdl, xp); 251625351652SVuong Nguyen 251725351652SVuong Nguyen /* 251825351652SVuong Nguyen * fmd_xprt_recv() must block during startup waiting for fmd to globally 251925351652SVuong Nguyen * clear FMD_XPRT_DSUSPENDED. As such, we can't allow it to be called 252025351652SVuong Nguyen * from a module's _fmd_init() routine, because that would block 252125351652SVuong Nguyen * fmd from completing initial module loading, resulting in a deadlock. 252225351652SVuong Nguyen */ 252325351652SVuong Nguyen if ((xip->xi_flags & FMD_XPRT_ISUSPENDED) && 252425351652SVuong Nguyen (pthread_self() == xip->xi_queue->eq_mod->mod_thread->thr_tid)) { 252525351652SVuong Nguyen fmd_api_error(fmd_api_module_lock(hdl), EFMD_XPRT_INVAL, 252625351652SVuong Nguyen "fmd_xprt_log() cannot be called from _fmd_init()\n"); 252725351652SVuong Nguyen } 252825351652SVuong Nguyen 252925351652SVuong Nguyen fmd_xprt_recv(xp, nvl, hrt, FMD_B_TRUE); 2530d9638e54Smws } 2531d9638e54Smws 2532d9638e54Smws void 2533d9638e54Smws fmd_xprt_suspend(fmd_hdl_t *hdl, fmd_xprt_t *xp) 2534d9638e54Smws { 2535d9638e54Smws (void) fmd_api_transport_impl(hdl, xp); /* validate 'xp' */ 2536d9638e54Smws fmd_xprt_xsuspend(xp, FMD_XPRT_SUSPENDED); 2537d9638e54Smws } 2538d9638e54Smws 2539d9638e54Smws void 2540d9638e54Smws fmd_xprt_resume(fmd_hdl_t *hdl, fmd_xprt_t *xp) 2541d9638e54Smws { 2542d9638e54Smws (void) fmd_api_transport_impl(hdl, xp); /* validate 'xp' */ 2543d9638e54Smws fmd_xprt_xresume(xp, FMD_XPRT_SUSPENDED); 2544d9638e54Smws } 2545d9638e54Smws 2546d9638e54Smws int 2547d9638e54Smws fmd_xprt_error(fmd_hdl_t *hdl, fmd_xprt_t *xp) 2548d9638e54Smws { 2549d9638e54Smws fmd_xprt_impl_t *xip = fmd_api_transport_impl(hdl, xp); 2550d9638e54Smws return (xip->xi_state == _fmd_xprt_state_err); 2551d9638e54Smws } 2552d9638e54Smws 2553d9638e54Smws /* 2554d9638e54Smws * Translate all FMRIs in the specified name-value pair list for the specified 2555d9638e54Smws * FMRI authority, and return a new name-value pair list for the translation. 2556d9638e54Smws * This function is the recursive engine used by fmd_xprt_translate(), below. 2557d9638e54Smws */ 2558d9638e54Smws static nvlist_t * 2559d9638e54Smws fmd_xprt_xtranslate(nvlist_t *nvl, nvlist_t *auth) 2560d9638e54Smws { 2561d9638e54Smws uint_t i, j, n; 2562d9638e54Smws nvpair_t *nvp, **nvps; 2563d9638e54Smws uint_t nvpslen = 0; 2564d9638e54Smws char *name; 2565d9638e54Smws size_t namelen = 0; 2566d9638e54Smws 2567d9638e54Smws nvlist_t **a, **b; 2568d9638e54Smws nvlist_t *l, *r; 2569d9638e54Smws data_type_t type; 2570d9638e54Smws char *s; 2571d9638e54Smws int err; 2572d9638e54Smws 2573d9638e54Smws (void) nvlist_xdup(nvl, &nvl, &fmd.d_nva); 2574d9638e54Smws 2575d9638e54Smws /* 2576d9638e54Smws * Count up the number of name-value pairs in 'nvl' and compute the 2577d9638e54Smws * maximum length of a name used in this list for use below. 2578d9638e54Smws */ 2579d9638e54Smws for (nvp = nvlist_next_nvpair(nvl, NULL); 2580d9638e54Smws nvp != NULL; nvp = nvlist_next_nvpair(nvl, nvp), nvpslen++) { 2581d9638e54Smws size_t len = strlen(nvpair_name(nvp)); 2582d9638e54Smws namelen = MAX(namelen, len); 2583d9638e54Smws } 2584d9638e54Smws 2585d9638e54Smws nvps = alloca(sizeof (nvpair_t *) * nvpslen); 2586d9638e54Smws name = alloca(namelen + 1); 2587d9638e54Smws 2588d9638e54Smws /* 2589d9638e54Smws * Store a snapshot of the name-value pairs in 'nvl' into nvps[] so 2590d9638e54Smws * that we can iterate over the original pairs in the loop below while 2591d9638e54Smws * performing arbitrary insert and delete operations on 'nvl' itself. 2592d9638e54Smws */ 2593d9638e54Smws for (i = 0, nvp = nvlist_next_nvpair(nvl, NULL); 2594d9638e54Smws nvp != NULL; nvp = nvlist_next_nvpair(nvl, nvp)) 2595d9638e54Smws nvps[i++] = nvp; 2596d9638e54Smws 2597d9638e54Smws /* 2598d9638e54Smws * Now iterate over the snapshot of the name-value pairs. If we find a 2599d9638e54Smws * value that is of type NVLIST or NVLIST_ARRAY, we translate that 2600d9638e54Smws * object by either calling ourself recursively on it, or calling into 2601d9638e54Smws * fmd_fmri_translate() if the object is an FMRI. We then rip out the 2602d9638e54Smws * original name-value pair and replace it with the translated one. 2603d9638e54Smws */ 2604d9638e54Smws for (i = 0; i < nvpslen; i++) { 2605d9638e54Smws nvp = nvps[i]; 2606d9638e54Smws type = nvpair_type(nvp); 2607d9638e54Smws 2608d9638e54Smws switch (type) { 2609d9638e54Smws case DATA_TYPE_NVLIST_ARRAY: 2610d9638e54Smws if (nvpair_value_nvlist_array(nvp, &a, &n) != 0 || 2611d9638e54Smws a == NULL || n == 0) 2612d9638e54Smws continue; /* array is zero-sized; skip it */ 2613d9638e54Smws 2614d9638e54Smws b = fmd_alloc(sizeof (nvlist_t *) * n, FMD_SLEEP); 2615d9638e54Smws 2616d9638e54Smws /* 2617d9638e54Smws * If the first array nvlist element looks like an FMRI 2618d9638e54Smws * then assume the other elements are FMRIs as well. 2619d9638e54Smws * If any b[j]'s can't be translated, then EINVAL will 2620d9638e54Smws * be returned from nvlist_add_nvlist_array() below. 2621d9638e54Smws */ 2622d9638e54Smws if (nvlist_lookup_string(*a, FM_FMRI_SCHEME, &s) == 0) { 2623d9638e54Smws for (j = 0; j < n; j++) 2624d9638e54Smws b[j] = fmd_fmri_translate(a[j], auth); 2625d9638e54Smws } else { 2626d9638e54Smws for (j = 0; j < n; j++) 2627d9638e54Smws b[j] = fmd_xprt_xtranslate(a[j], auth); 2628d9638e54Smws } 2629d9638e54Smws 2630d9638e54Smws (void) strcpy(name, nvpair_name(nvp)); 2631d9638e54Smws (void) nvlist_remove(nvl, name, type); 2632d9638e54Smws err = nvlist_add_nvlist_array(nvl, name, b, n); 2633d9638e54Smws 2634d9638e54Smws for (j = 0; j < n; j++) 2635d9638e54Smws nvlist_free(b[j]); 2636d9638e54Smws 2637d9638e54Smws fmd_free(b, sizeof (nvlist_t *) * n); 2638d9638e54Smws 2639d9638e54Smws if (err != 0) { 2640d9638e54Smws nvlist_free(nvl); 2641d9638e54Smws errno = err; 2642d9638e54Smws return (NULL); 2643d9638e54Smws } 2644d9638e54Smws break; 2645d9638e54Smws 2646d9638e54Smws case DATA_TYPE_NVLIST: 2647d9638e54Smws if (nvpair_value_nvlist(nvp, &l) == 0 && 2648d9638e54Smws nvlist_lookup_string(l, FM_FMRI_SCHEME, &s) == 0) 2649d9638e54Smws r = fmd_fmri_translate(l, auth); 2650d9638e54Smws else 2651d9638e54Smws r = fmd_xprt_xtranslate(l, auth); 2652d9638e54Smws 2653d9638e54Smws if (r == NULL) { 2654d9638e54Smws nvlist_free(nvl); 2655d9638e54Smws return (NULL); 2656d9638e54Smws } 2657d9638e54Smws 2658d9638e54Smws (void) strcpy(name, nvpair_name(nvp)); 2659d9638e54Smws (void) nvlist_remove(nvl, name, type); 2660d9638e54Smws (void) nvlist_add_nvlist(nvl, name, r); 2661d9638e54Smws 2662d9638e54Smws nvlist_free(r); 2663d9638e54Smws break; 2664d9638e54Smws } 2665d9638e54Smws } 2666d9638e54Smws 2667d9638e54Smws return (nvl); 2668d9638e54Smws } 2669d9638e54Smws 2670d9638e54Smws nvlist_t * 2671d9638e54Smws fmd_xprt_translate(fmd_hdl_t *hdl, fmd_xprt_t *xp, fmd_event_t *ep) 2672d9638e54Smws { 2673d9638e54Smws fmd_xprt_impl_t *xip = fmd_api_transport_impl(hdl, xp); 2674d9638e54Smws 2675d9638e54Smws if (xip->xi_auth == NULL) { 2676d9638e54Smws fmd_api_error(fmd_api_module_lock(hdl), EFMD_XPRT_INVAL, 2677d9638e54Smws "no authority defined for transport %p\n", (void *)xp); 2678d9638e54Smws } 2679d9638e54Smws 2680d9638e54Smws return (fmd_xprt_xtranslate(FMD_EVENT_NVL(ep), xip->xi_auth)); 2681d9638e54Smws } 2682d9638e54Smws 2683cbf75e67SStephen Hanson /*ARGSUSED*/ 2684cbf75e67SStephen Hanson void 2685cbf75e67SStephen Hanson fmd_xprt_add_domain(fmd_hdl_t *hdl, nvlist_t *nvl, char *domain) 2686cbf75e67SStephen Hanson { 2687cbf75e67SStephen Hanson nvpair_t *nvp, *nvp2; 2688cbf75e67SStephen Hanson nvlist_t *nvl2, *nvl3; 2689cbf75e67SStephen Hanson char *class; 2690cbf75e67SStephen Hanson 2691cbf75e67SStephen Hanson if (nvl == NULL || domain == NULL) 2692cbf75e67SStephen Hanson return; 2693cbf75e67SStephen Hanson for (nvp = nvlist_next_nvpair(nvl, NULL); nvp != NULL; 2694cbf75e67SStephen Hanson nvp = nvlist_next_nvpair(nvl, nvp)) { 2695cbf75e67SStephen Hanson if (strcmp(nvpair_name(nvp), FM_CLASS) == 0) { 2696cbf75e67SStephen Hanson (void) nvpair_value_string(nvp, &class); 2697cbf75e67SStephen Hanson if (strcmp(class, FM_LIST_SUSPECT_CLASS) != 0) 2698cbf75e67SStephen Hanson return; 2699cbf75e67SStephen Hanson } 2700cbf75e67SStephen Hanson } 2701cbf75e67SStephen Hanson for (nvp = nvlist_next_nvpair(nvl, NULL); nvp != NULL; 2702cbf75e67SStephen Hanson nvp = nvlist_next_nvpair(nvl, nvp)) { 2703cbf75e67SStephen Hanson if (strcmp(nvpair_name(nvp), FM_SUSPECT_DE) == 0) { 2704cbf75e67SStephen Hanson (void) nvpair_value_nvlist(nvp, &nvl2); 2705cbf75e67SStephen Hanson for (nvp2 = nvlist_next_nvpair(nvl2, NULL); 2706cbf75e67SStephen Hanson nvp2 != NULL; 2707cbf75e67SStephen Hanson nvp2 = nvlist_next_nvpair(nvl2, nvp2)) { 2708cbf75e67SStephen Hanson if (strcmp(nvpair_name(nvp2), 2709cbf75e67SStephen Hanson FM_FMRI_AUTHORITY) == 0) { 2710cbf75e67SStephen Hanson (void) nvpair_value_nvlist(nvp2, &nvl3); 2711cbf75e67SStephen Hanson (void) nvlist_add_string(nvl3, 2712cbf75e67SStephen Hanson FM_FMRI_AUTH_DOMAIN, domain); 2713cbf75e67SStephen Hanson break; 2714cbf75e67SStephen Hanson } 2715cbf75e67SStephen Hanson } 2716cbf75e67SStephen Hanson break; 2717cbf75e67SStephen Hanson } 2718cbf75e67SStephen Hanson } 2719cbf75e67SStephen Hanson } 2720cbf75e67SStephen Hanson 2721d9638e54Smws void 2722d9638e54Smws fmd_xprt_setspecific(fmd_hdl_t *hdl, fmd_xprt_t *xp, void *data) 2723d9638e54Smws { 2724d9638e54Smws fmd_api_transport_impl(hdl, xp)->xi_data = data; 2725d9638e54Smws } 2726d9638e54Smws 2727d9638e54Smws void * 2728d9638e54Smws fmd_xprt_getspecific(fmd_hdl_t *hdl, fmd_xprt_t *xp) 2729d9638e54Smws { 2730d9638e54Smws return (fmd_api_transport_impl(hdl, xp)->xi_data); 2731d9638e54Smws } 2732