1eda14cbcSMatt Macy /* 2eda14cbcSMatt Macy * CDDL HEADER START 3eda14cbcSMatt Macy * 4eda14cbcSMatt Macy * The contents of this file are subject to the terms of the 5eda14cbcSMatt Macy * Common Development and Distribution License (the "License"). 6eda14cbcSMatt Macy * You may not use this file except in compliance with the License. 7eda14cbcSMatt Macy * 8eda14cbcSMatt Macy * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9eda14cbcSMatt Macy * or http://www.opensolaris.org/os/licensing. 10eda14cbcSMatt Macy * See the License for the specific language governing permissions 11eda14cbcSMatt Macy * and limitations under the License. 12eda14cbcSMatt Macy * 13eda14cbcSMatt Macy * When distributing Covered Code, include this CDDL HEADER in each 14eda14cbcSMatt Macy * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15eda14cbcSMatt Macy * If applicable, add the following below this CDDL HEADER, with the 16eda14cbcSMatt Macy * fields enclosed by brackets "[]" replaced with your own identifying 17eda14cbcSMatt Macy * information: Portions Copyright [yyyy] [name of copyright owner] 18eda14cbcSMatt Macy * 19eda14cbcSMatt Macy * CDDL HEADER END 20eda14cbcSMatt Macy */ 21eda14cbcSMatt Macy /* 22eda14cbcSMatt Macy * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved. 23eda14cbcSMatt Macy * 24eda14cbcSMatt Macy * Copyright (c) 2016, Intel Corporation. 25eda14cbcSMatt Macy */ 26eda14cbcSMatt Macy 27eda14cbcSMatt Macy /* 28eda14cbcSMatt Macy * This file implements the minimal FMD module API required to support the 29eda14cbcSMatt Macy * fault logic modules in ZED. This support includes module registration, 30eda14cbcSMatt Macy * memory allocation, module property accessors, basic case management, 31eda14cbcSMatt Macy * one-shot timers and SERD engines. 32eda14cbcSMatt Macy * 33eda14cbcSMatt Macy * In the ZED runtime, the modules are called from a single thread so no 34eda14cbcSMatt Macy * locking is required in this emulated FMD environment. 35eda14cbcSMatt Macy */ 36eda14cbcSMatt Macy 37eda14cbcSMatt Macy #include <sys/types.h> 38eda14cbcSMatt Macy #include <sys/fm/protocol.h> 39eda14cbcSMatt Macy #include <uuid/uuid.h> 40eda14cbcSMatt Macy #include <signal.h> 41da5137abSMartin Matuska #include <string.h> 42eda14cbcSMatt Macy #include <time.h> 43eda14cbcSMatt Macy 44eda14cbcSMatt Macy #include "fmd_api.h" 45eda14cbcSMatt Macy #include "fmd_serd.h" 46eda14cbcSMatt Macy 47eda14cbcSMatt Macy #include "zfs_agents.h" 48eda14cbcSMatt Macy #include "../zed_log.h" 49eda14cbcSMatt Macy 50eda14cbcSMatt Macy typedef struct fmd_modstat { 51eda14cbcSMatt Macy fmd_stat_t ms_accepted; /* total events accepted by module */ 52eda14cbcSMatt Macy fmd_stat_t ms_caseopen; /* cases currently open */ 53eda14cbcSMatt Macy fmd_stat_t ms_casesolved; /* total cases solved by module */ 54eda14cbcSMatt Macy fmd_stat_t ms_caseclosed; /* total cases closed by module */ 55eda14cbcSMatt Macy } fmd_modstat_t; 56eda14cbcSMatt Macy 57eda14cbcSMatt Macy typedef struct fmd_module { 58eda14cbcSMatt Macy const char *mod_name; /* basename of module (ro) */ 59eda14cbcSMatt Macy const fmd_hdl_info_t *mod_info; /* module info registered with handle */ 60eda14cbcSMatt Macy void *mod_spec; /* fmd_hdl_get/setspecific data value */ 61eda14cbcSMatt Macy fmd_stat_t *mod_ustat; /* module specific custom stats */ 62eda14cbcSMatt Macy uint_t mod_ustat_cnt; /* count of ustat stats */ 63eda14cbcSMatt Macy fmd_modstat_t mod_stats; /* fmd built-in per-module statistics */ 64eda14cbcSMatt Macy fmd_serd_hash_t mod_serds; /* hash of serd engs owned by module */ 65eda14cbcSMatt Macy char *mod_vers; /* a copy of module version string */ 66eda14cbcSMatt Macy } fmd_module_t; 67eda14cbcSMatt Macy 68eda14cbcSMatt Macy /* 69eda14cbcSMatt Macy * ZED has two FMD hardwired module instances 70eda14cbcSMatt Macy */ 71eda14cbcSMatt Macy fmd_module_t zfs_retire_module; 72eda14cbcSMatt Macy fmd_module_t zfs_diagnosis_module; 73eda14cbcSMatt Macy 74eda14cbcSMatt Macy /* 75eda14cbcSMatt Macy * Enable a reasonable set of defaults for libumem debugging on DEBUG builds. 76eda14cbcSMatt Macy */ 77eda14cbcSMatt Macy 78eda14cbcSMatt Macy #ifdef DEBUG 79eda14cbcSMatt Macy const char * 80eda14cbcSMatt Macy _umem_debug_init(void) 81eda14cbcSMatt Macy { 82eda14cbcSMatt Macy return ("default,verbose"); /* $UMEM_DEBUG setting */ 83eda14cbcSMatt Macy } 84eda14cbcSMatt Macy 85eda14cbcSMatt Macy const char * 86eda14cbcSMatt Macy _umem_logging_init(void) 87eda14cbcSMatt Macy { 88eda14cbcSMatt Macy return ("fail,contents"); /* $UMEM_LOGGING setting */ 89eda14cbcSMatt Macy } 90eda14cbcSMatt Macy #endif 91eda14cbcSMatt Macy 92eda14cbcSMatt Macy /* 93eda14cbcSMatt Macy * Register a module with fmd and finish module initialization. 94eda14cbcSMatt Macy * Returns an integer indicating whether it succeeded (zero) or 95eda14cbcSMatt Macy * failed (non-zero). 96eda14cbcSMatt Macy */ 97eda14cbcSMatt Macy int 98eda14cbcSMatt Macy fmd_hdl_register(fmd_hdl_t *hdl, int version, const fmd_hdl_info_t *mip) 99eda14cbcSMatt Macy { 100e92ffd9bSMartin Matuska (void) version; 101eda14cbcSMatt Macy fmd_module_t *mp = (fmd_module_t *)hdl; 102eda14cbcSMatt Macy 103eda14cbcSMatt Macy mp->mod_info = mip; 104eda14cbcSMatt Macy mp->mod_name = mip->fmdi_desc + 4; /* drop 'ZFS ' prefix */ 105eda14cbcSMatt Macy mp->mod_spec = NULL; 106eda14cbcSMatt Macy 107eda14cbcSMatt Macy /* bare minimum module stats */ 108eda14cbcSMatt Macy (void) strcpy(mp->mod_stats.ms_accepted.fmds_name, "fmd.accepted"); 109eda14cbcSMatt Macy (void) strcpy(mp->mod_stats.ms_caseopen.fmds_name, "fmd.caseopen"); 110eda14cbcSMatt Macy (void) strcpy(mp->mod_stats.ms_casesolved.fmds_name, "fmd.casesolved"); 111eda14cbcSMatt Macy (void) strcpy(mp->mod_stats.ms_caseclosed.fmds_name, "fmd.caseclosed"); 112eda14cbcSMatt Macy 113eda14cbcSMatt Macy fmd_serd_hash_create(&mp->mod_serds); 114eda14cbcSMatt Macy 115eda14cbcSMatt Macy fmd_hdl_debug(hdl, "register module"); 116eda14cbcSMatt Macy 117eda14cbcSMatt Macy return (0); 118eda14cbcSMatt Macy } 119eda14cbcSMatt Macy 120eda14cbcSMatt Macy void 121eda14cbcSMatt Macy fmd_hdl_unregister(fmd_hdl_t *hdl) 122eda14cbcSMatt Macy { 123eda14cbcSMatt Macy fmd_module_t *mp = (fmd_module_t *)hdl; 124eda14cbcSMatt Macy fmd_modstat_t *msp = &mp->mod_stats; 125eda14cbcSMatt Macy const fmd_hdl_ops_t *ops = mp->mod_info->fmdi_ops; 126eda14cbcSMatt Macy 127eda14cbcSMatt Macy /* dump generic module stats */ 128eda14cbcSMatt Macy fmd_hdl_debug(hdl, "%s: %llu", msp->ms_accepted.fmds_name, 129eda14cbcSMatt Macy msp->ms_accepted.fmds_value.ui64); 130eda14cbcSMatt Macy if (ops->fmdo_close != NULL) { 131eda14cbcSMatt Macy fmd_hdl_debug(hdl, "%s: %llu", msp->ms_caseopen.fmds_name, 132eda14cbcSMatt Macy msp->ms_caseopen.fmds_value.ui64); 133eda14cbcSMatt Macy fmd_hdl_debug(hdl, "%s: %llu", msp->ms_casesolved.fmds_name, 134eda14cbcSMatt Macy msp->ms_casesolved.fmds_value.ui64); 135eda14cbcSMatt Macy fmd_hdl_debug(hdl, "%s: %llu", msp->ms_caseclosed.fmds_name, 136eda14cbcSMatt Macy msp->ms_caseclosed.fmds_value.ui64); 137eda14cbcSMatt Macy } 138eda14cbcSMatt Macy 139eda14cbcSMatt Macy /* dump module specific stats */ 140eda14cbcSMatt Macy if (mp->mod_ustat != NULL) { 141eda14cbcSMatt Macy int i; 142eda14cbcSMatt Macy 143eda14cbcSMatt Macy for (i = 0; i < mp->mod_ustat_cnt; i++) { 144eda14cbcSMatt Macy fmd_hdl_debug(hdl, "%s: %llu", 145eda14cbcSMatt Macy mp->mod_ustat[i].fmds_name, 146eda14cbcSMatt Macy mp->mod_ustat[i].fmds_value.ui64); 147eda14cbcSMatt Macy } 148eda14cbcSMatt Macy } 149eda14cbcSMatt Macy 150eda14cbcSMatt Macy fmd_serd_hash_destroy(&mp->mod_serds); 151eda14cbcSMatt Macy 152eda14cbcSMatt Macy fmd_hdl_debug(hdl, "unregister module"); 153eda14cbcSMatt Macy } 154eda14cbcSMatt Macy 155eda14cbcSMatt Macy /* 156eda14cbcSMatt Macy * fmd_hdl_setspecific() is used to associate a data pointer with 157eda14cbcSMatt Macy * the specified handle for the duration of the module's lifetime. 158eda14cbcSMatt Macy * This pointer can be retrieved using fmd_hdl_getspecific(). 159eda14cbcSMatt Macy */ 160eda14cbcSMatt Macy void 161eda14cbcSMatt Macy fmd_hdl_setspecific(fmd_hdl_t *hdl, void *spec) 162eda14cbcSMatt Macy { 163eda14cbcSMatt Macy fmd_module_t *mp = (fmd_module_t *)hdl; 164eda14cbcSMatt Macy 165eda14cbcSMatt Macy mp->mod_spec = spec; 166eda14cbcSMatt Macy } 167eda14cbcSMatt Macy 168eda14cbcSMatt Macy /* 169eda14cbcSMatt Macy * Return the module-specific data pointer previously associated 170eda14cbcSMatt Macy * with the handle using fmd_hdl_setspecific(). 171eda14cbcSMatt Macy */ 172eda14cbcSMatt Macy void * 173eda14cbcSMatt Macy fmd_hdl_getspecific(fmd_hdl_t *hdl) 174eda14cbcSMatt Macy { 175eda14cbcSMatt Macy fmd_module_t *mp = (fmd_module_t *)hdl; 176eda14cbcSMatt Macy 177eda14cbcSMatt Macy return (mp->mod_spec); 178eda14cbcSMatt Macy } 179eda14cbcSMatt Macy 180eda14cbcSMatt Macy void * 181eda14cbcSMatt Macy fmd_hdl_alloc(fmd_hdl_t *hdl, size_t size, int flags) 182eda14cbcSMatt Macy { 183e92ffd9bSMartin Matuska (void) hdl; 184eda14cbcSMatt Macy return (umem_alloc(size, flags)); 185eda14cbcSMatt Macy } 186eda14cbcSMatt Macy 187eda14cbcSMatt Macy void * 188eda14cbcSMatt Macy fmd_hdl_zalloc(fmd_hdl_t *hdl, size_t size, int flags) 189eda14cbcSMatt Macy { 190e92ffd9bSMartin Matuska (void) hdl; 191eda14cbcSMatt Macy return (umem_zalloc(size, flags)); 192eda14cbcSMatt Macy } 193eda14cbcSMatt Macy 194eda14cbcSMatt Macy void 195eda14cbcSMatt Macy fmd_hdl_free(fmd_hdl_t *hdl, void *data, size_t size) 196eda14cbcSMatt Macy { 197e92ffd9bSMartin Matuska (void) hdl; 198eda14cbcSMatt Macy umem_free(data, size); 199eda14cbcSMatt Macy } 200eda14cbcSMatt Macy 201eda14cbcSMatt Macy /* 202eda14cbcSMatt Macy * Record a module debug message using the specified format. 203eda14cbcSMatt Macy */ 204eda14cbcSMatt Macy void 205eda14cbcSMatt Macy fmd_hdl_debug(fmd_hdl_t *hdl, const char *format, ...) 206eda14cbcSMatt Macy { 207eda14cbcSMatt Macy char message[256]; 208eda14cbcSMatt Macy va_list vargs; 209eda14cbcSMatt Macy fmd_module_t *mp = (fmd_module_t *)hdl; 210eda14cbcSMatt Macy 211eda14cbcSMatt Macy va_start(vargs, format); 212eda14cbcSMatt Macy (void) vsnprintf(message, sizeof (message), format, vargs); 213eda14cbcSMatt Macy va_end(vargs); 214eda14cbcSMatt Macy 215eda14cbcSMatt Macy /* prefix message with module name */ 216eda14cbcSMatt Macy zed_log_msg(LOG_INFO, "%s: %s", mp->mod_name, message); 217eda14cbcSMatt Macy } 218eda14cbcSMatt Macy 219eda14cbcSMatt Macy /* Property Retrieval */ 220eda14cbcSMatt Macy 221eda14cbcSMatt Macy int32_t 222eda14cbcSMatt Macy fmd_prop_get_int32(fmd_hdl_t *hdl, const char *name) 223eda14cbcSMatt Macy { 224e92ffd9bSMartin Matuska (void) hdl; 225e92ffd9bSMartin Matuska 226eda14cbcSMatt Macy /* 227eda14cbcSMatt Macy * These can be looked up in mp->modinfo->fmdi_props 228eda14cbcSMatt Macy * For now we just hard code for phase 2. In the 229eda14cbcSMatt Macy * future, there can be a ZED based override. 230eda14cbcSMatt Macy */ 231eda14cbcSMatt Macy if (strcmp(name, "spare_on_remove") == 0) 232eda14cbcSMatt Macy return (1); 233eda14cbcSMatt Macy 234eda14cbcSMatt Macy if (strcmp(name, "io_N") == 0 || strcmp(name, "checksum_N") == 0) 235eda14cbcSMatt Macy return (10); /* N = 10 events */ 236eda14cbcSMatt Macy 237eda14cbcSMatt Macy return (0); 238eda14cbcSMatt Macy } 239eda14cbcSMatt Macy 240eda14cbcSMatt Macy int64_t 241eda14cbcSMatt Macy fmd_prop_get_int64(fmd_hdl_t *hdl, const char *name) 242eda14cbcSMatt Macy { 243e92ffd9bSMartin Matuska (void) hdl; 244e92ffd9bSMartin Matuska 245eda14cbcSMatt Macy /* 246eda14cbcSMatt Macy * These can be looked up in mp->modinfo->fmdi_props 247eda14cbcSMatt Macy * For now we just hard code for phase 2. In the 248eda14cbcSMatt Macy * future, there can be a ZED based override. 249eda14cbcSMatt Macy */ 250eda14cbcSMatt Macy if (strcmp(name, "remove_timeout") == 0) 251eda14cbcSMatt Macy return (15ULL * 1000ULL * 1000ULL * 1000ULL); /* 15 sec */ 252eda14cbcSMatt Macy 253eda14cbcSMatt Macy if (strcmp(name, "io_T") == 0 || strcmp(name, "checksum_T") == 0) 254eda14cbcSMatt Macy return (1000ULL * 1000ULL * 1000ULL * 600ULL); /* 10 min */ 255eda14cbcSMatt Macy 256eda14cbcSMatt Macy return (0); 257eda14cbcSMatt Macy } 258eda14cbcSMatt Macy 259eda14cbcSMatt Macy /* FMD Statistics */ 260eda14cbcSMatt Macy 261eda14cbcSMatt Macy fmd_stat_t * 262eda14cbcSMatt Macy fmd_stat_create(fmd_hdl_t *hdl, uint_t flags, uint_t nstats, fmd_stat_t *statv) 263eda14cbcSMatt Macy { 264eda14cbcSMatt Macy fmd_module_t *mp = (fmd_module_t *)hdl; 265eda14cbcSMatt Macy 266eda14cbcSMatt Macy if (flags == FMD_STAT_NOALLOC) { 267eda14cbcSMatt Macy mp->mod_ustat = statv; 268eda14cbcSMatt Macy mp->mod_ustat_cnt = nstats; 269eda14cbcSMatt Macy } 270eda14cbcSMatt Macy 271eda14cbcSMatt Macy return (statv); 272eda14cbcSMatt Macy } 273eda14cbcSMatt Macy 274eda14cbcSMatt Macy /* Case Management */ 275eda14cbcSMatt Macy 276eda14cbcSMatt Macy fmd_case_t * 277eda14cbcSMatt Macy fmd_case_open(fmd_hdl_t *hdl, void *data) 278eda14cbcSMatt Macy { 279eda14cbcSMatt Macy fmd_module_t *mp = (fmd_module_t *)hdl; 280eda14cbcSMatt Macy uuid_t uuid; 281eda14cbcSMatt Macy 282eda14cbcSMatt Macy fmd_case_t *cp; 283eda14cbcSMatt Macy 284eda14cbcSMatt Macy cp = fmd_hdl_zalloc(hdl, sizeof (fmd_case_t), FMD_SLEEP); 285eda14cbcSMatt Macy cp->ci_mod = hdl; 286eda14cbcSMatt Macy cp->ci_state = FMD_CASE_UNSOLVED; 287eda14cbcSMatt Macy cp->ci_flags = FMD_CF_DIRTY; 288eda14cbcSMatt Macy cp->ci_data = data; 289eda14cbcSMatt Macy cp->ci_bufptr = NULL; 290eda14cbcSMatt Macy cp->ci_bufsiz = 0; 291eda14cbcSMatt Macy 292eda14cbcSMatt Macy uuid_generate(uuid); 293eda14cbcSMatt Macy uuid_unparse(uuid, cp->ci_uuid); 294eda14cbcSMatt Macy 295eda14cbcSMatt Macy fmd_hdl_debug(hdl, "case opened (%s)", cp->ci_uuid); 296eda14cbcSMatt Macy mp->mod_stats.ms_caseopen.fmds_value.ui64++; 297eda14cbcSMatt Macy 298eda14cbcSMatt Macy return (cp); 299eda14cbcSMatt Macy } 300eda14cbcSMatt Macy 301eda14cbcSMatt Macy void 302eda14cbcSMatt Macy fmd_case_solve(fmd_hdl_t *hdl, fmd_case_t *cp) 303eda14cbcSMatt Macy { 304eda14cbcSMatt Macy fmd_module_t *mp = (fmd_module_t *)hdl; 305eda14cbcSMatt Macy 306eda14cbcSMatt Macy /* 307eda14cbcSMatt Macy * For ZED, the event was already sent from fmd_case_add_suspect() 308eda14cbcSMatt Macy */ 309eda14cbcSMatt Macy 310eda14cbcSMatt Macy if (cp->ci_state >= FMD_CASE_SOLVED) 311eda14cbcSMatt Macy fmd_hdl_debug(hdl, "case is already solved or closed"); 312eda14cbcSMatt Macy 313eda14cbcSMatt Macy cp->ci_state = FMD_CASE_SOLVED; 314eda14cbcSMatt Macy 315eda14cbcSMatt Macy fmd_hdl_debug(hdl, "case solved (%s)", cp->ci_uuid); 316eda14cbcSMatt Macy mp->mod_stats.ms_casesolved.fmds_value.ui64++; 317eda14cbcSMatt Macy } 318eda14cbcSMatt Macy 319eda14cbcSMatt Macy void 320eda14cbcSMatt Macy fmd_case_close(fmd_hdl_t *hdl, fmd_case_t *cp) 321eda14cbcSMatt Macy { 322eda14cbcSMatt Macy fmd_module_t *mp = (fmd_module_t *)hdl; 323eda14cbcSMatt Macy const fmd_hdl_ops_t *ops = mp->mod_info->fmdi_ops; 324eda14cbcSMatt Macy 325eda14cbcSMatt Macy fmd_hdl_debug(hdl, "case closed (%s)", cp->ci_uuid); 326eda14cbcSMatt Macy 327eda14cbcSMatt Macy if (ops->fmdo_close != NULL) 328eda14cbcSMatt Macy ops->fmdo_close(hdl, cp); 329eda14cbcSMatt Macy 330eda14cbcSMatt Macy mp->mod_stats.ms_caseopen.fmds_value.ui64--; 331eda14cbcSMatt Macy mp->mod_stats.ms_caseclosed.fmds_value.ui64++; 332eda14cbcSMatt Macy 333eda14cbcSMatt Macy if (cp->ci_bufptr != NULL && cp->ci_bufsiz > 0) 334eda14cbcSMatt Macy fmd_hdl_free(hdl, cp->ci_bufptr, cp->ci_bufsiz); 335eda14cbcSMatt Macy 336eda14cbcSMatt Macy fmd_hdl_free(hdl, cp, sizeof (fmd_case_t)); 337eda14cbcSMatt Macy } 338eda14cbcSMatt Macy 339eda14cbcSMatt Macy void 340eda14cbcSMatt Macy fmd_case_uuresolved(fmd_hdl_t *hdl, const char *uuid) 341eda14cbcSMatt Macy { 342eda14cbcSMatt Macy fmd_hdl_debug(hdl, "case resolved by uuid (%s)", uuid); 343eda14cbcSMatt Macy } 344eda14cbcSMatt Macy 345da5137abSMartin Matuska boolean_t 346eda14cbcSMatt Macy fmd_case_solved(fmd_hdl_t *hdl, fmd_case_t *cp) 347eda14cbcSMatt Macy { 348e92ffd9bSMartin Matuska (void) hdl; 349da5137abSMartin Matuska return (cp->ci_state >= FMD_CASE_SOLVED); 350eda14cbcSMatt Macy } 351eda14cbcSMatt Macy 352eda14cbcSMatt Macy void 353eda14cbcSMatt Macy fmd_case_add_ereport(fmd_hdl_t *hdl, fmd_case_t *cp, fmd_event_t *ep) 354eda14cbcSMatt Macy { 355e92ffd9bSMartin Matuska (void) hdl, (void) cp, (void) ep; 356eda14cbcSMatt Macy } 357eda14cbcSMatt Macy 358eda14cbcSMatt Macy static void 359eda14cbcSMatt Macy zed_log_fault(nvlist_t *nvl, const char *uuid, const char *code) 360eda14cbcSMatt Macy { 361eda14cbcSMatt Macy nvlist_t *rsrc; 362eda14cbcSMatt Macy char *strval; 363eda14cbcSMatt Macy uint64_t guid; 364eda14cbcSMatt Macy uint8_t byte; 365eda14cbcSMatt Macy 366eda14cbcSMatt Macy zed_log_msg(LOG_INFO, "\nzed_fault_event:"); 367eda14cbcSMatt Macy 368eda14cbcSMatt Macy if (uuid != NULL) 369eda14cbcSMatt Macy zed_log_msg(LOG_INFO, "\t%s: %s", FM_SUSPECT_UUID, uuid); 370eda14cbcSMatt Macy if (nvlist_lookup_string(nvl, FM_CLASS, &strval) == 0) 371eda14cbcSMatt Macy zed_log_msg(LOG_INFO, "\t%s: %s", FM_CLASS, strval); 372eda14cbcSMatt Macy if (code != NULL) 373eda14cbcSMatt Macy zed_log_msg(LOG_INFO, "\t%s: %s", FM_SUSPECT_DIAG_CODE, code); 374eda14cbcSMatt Macy if (nvlist_lookup_uint8(nvl, FM_FAULT_CERTAINTY, &byte) == 0) 375eda14cbcSMatt Macy zed_log_msg(LOG_INFO, "\t%s: %llu", FM_FAULT_CERTAINTY, byte); 376eda14cbcSMatt Macy if (nvlist_lookup_nvlist(nvl, FM_FAULT_RESOURCE, &rsrc) == 0) { 377eda14cbcSMatt Macy if (nvlist_lookup_string(rsrc, FM_FMRI_SCHEME, &strval) == 0) 378eda14cbcSMatt Macy zed_log_msg(LOG_INFO, "\t%s: %s", FM_FMRI_SCHEME, 379eda14cbcSMatt Macy strval); 380eda14cbcSMatt Macy if (nvlist_lookup_uint64(rsrc, FM_FMRI_ZFS_POOL, &guid) == 0) 381eda14cbcSMatt Macy zed_log_msg(LOG_INFO, "\t%s: %llu", FM_FMRI_ZFS_POOL, 382eda14cbcSMatt Macy guid); 383eda14cbcSMatt Macy if (nvlist_lookup_uint64(rsrc, FM_FMRI_ZFS_VDEV, &guid) == 0) 384eda14cbcSMatt Macy zed_log_msg(LOG_INFO, "\t%s: %llu \n", FM_FMRI_ZFS_VDEV, 385eda14cbcSMatt Macy guid); 386eda14cbcSMatt Macy } 387eda14cbcSMatt Macy } 388eda14cbcSMatt Macy 389eda14cbcSMatt Macy static const char * 390eda14cbcSMatt Macy fmd_fault_mkcode(nvlist_t *fault) 391eda14cbcSMatt Macy { 392*a0b956f5SMartin Matuska char *class; 393*a0b956f5SMartin Matuska const char *code = "-"; 394eda14cbcSMatt Macy 395eda14cbcSMatt Macy /* 396eda14cbcSMatt Macy * Note: message codes come from: openzfs/usr/src/cmd/fm/dicts/ZFS.po 397eda14cbcSMatt Macy */ 398eda14cbcSMatt Macy if (nvlist_lookup_string(fault, FM_CLASS, &class) == 0) { 399eda14cbcSMatt Macy if (strcmp(class, "fault.fs.zfs.vdev.io") == 0) 400eda14cbcSMatt Macy code = "ZFS-8000-FD"; 401eda14cbcSMatt Macy else if (strcmp(class, "fault.fs.zfs.vdev.checksum") == 0) 402eda14cbcSMatt Macy code = "ZFS-8000-GH"; 403eda14cbcSMatt Macy else if (strcmp(class, "fault.fs.zfs.io_failure_wait") == 0) 404eda14cbcSMatt Macy code = "ZFS-8000-HC"; 405eda14cbcSMatt Macy else if (strcmp(class, "fault.fs.zfs.io_failure_continue") == 0) 406eda14cbcSMatt Macy code = "ZFS-8000-JQ"; 407eda14cbcSMatt Macy else if (strcmp(class, "fault.fs.zfs.log_replay") == 0) 408eda14cbcSMatt Macy code = "ZFS-8000-K4"; 409eda14cbcSMatt Macy else if (strcmp(class, "fault.fs.zfs.pool") == 0) 410eda14cbcSMatt Macy code = "ZFS-8000-CS"; 411eda14cbcSMatt Macy else if (strcmp(class, "fault.fs.zfs.device") == 0) 412eda14cbcSMatt Macy code = "ZFS-8000-D3"; 413eda14cbcSMatt Macy 414eda14cbcSMatt Macy } 415eda14cbcSMatt Macy return (code); 416eda14cbcSMatt Macy } 417eda14cbcSMatt Macy 418eda14cbcSMatt Macy void 419eda14cbcSMatt Macy fmd_case_add_suspect(fmd_hdl_t *hdl, fmd_case_t *cp, nvlist_t *fault) 420eda14cbcSMatt Macy { 421eda14cbcSMatt Macy nvlist_t *nvl; 422eda14cbcSMatt Macy const char *code = fmd_fault_mkcode(fault); 423eda14cbcSMatt Macy int64_t tod[2]; 424eda14cbcSMatt Macy int err = 0; 425eda14cbcSMatt Macy 426eda14cbcSMatt Macy /* 427eda14cbcSMatt Macy * payload derived from fmd_protocol_list() 428eda14cbcSMatt Macy */ 429eda14cbcSMatt Macy 430eda14cbcSMatt Macy (void) gettimeofday(&cp->ci_tv, NULL); 431eda14cbcSMatt Macy tod[0] = cp->ci_tv.tv_sec; 432eda14cbcSMatt Macy tod[1] = cp->ci_tv.tv_usec; 433eda14cbcSMatt Macy 434eda14cbcSMatt Macy nvl = fmd_nvl_alloc(hdl, FMD_SLEEP); 435eda14cbcSMatt Macy 436eda14cbcSMatt Macy err |= nvlist_add_uint8(nvl, FM_VERSION, FM_SUSPECT_VERSION); 437eda14cbcSMatt Macy err |= nvlist_add_string(nvl, FM_CLASS, FM_LIST_SUSPECT_CLASS); 438eda14cbcSMatt Macy err |= nvlist_add_string(nvl, FM_SUSPECT_UUID, cp->ci_uuid); 439eda14cbcSMatt Macy err |= nvlist_add_string(nvl, FM_SUSPECT_DIAG_CODE, code); 440eda14cbcSMatt Macy err |= nvlist_add_int64_array(nvl, FM_SUSPECT_DIAG_TIME, tod, 2); 441eda14cbcSMatt Macy err |= nvlist_add_uint32(nvl, FM_SUSPECT_FAULT_SZ, 1); 442681ce946SMartin Matuska err |= nvlist_add_nvlist_array(nvl, FM_SUSPECT_FAULT_LIST, 443681ce946SMartin Matuska (const nvlist_t **)&fault, 1); 444eda14cbcSMatt Macy 445eda14cbcSMatt Macy if (err) 446eda14cbcSMatt Macy zed_log_die("failed to populate nvlist"); 447eda14cbcSMatt Macy 448eda14cbcSMatt Macy zed_log_fault(fault, cp->ci_uuid, code); 449eda14cbcSMatt Macy zfs_agent_post_event(FM_LIST_SUSPECT_CLASS, NULL, nvl); 450eda14cbcSMatt Macy 451eda14cbcSMatt Macy nvlist_free(nvl); 452eda14cbcSMatt Macy nvlist_free(fault); 453eda14cbcSMatt Macy } 454eda14cbcSMatt Macy 455eda14cbcSMatt Macy void 456eda14cbcSMatt Macy fmd_case_setspecific(fmd_hdl_t *hdl, fmd_case_t *cp, void *data) 457eda14cbcSMatt Macy { 458e92ffd9bSMartin Matuska (void) hdl; 459eda14cbcSMatt Macy cp->ci_data = data; 460eda14cbcSMatt Macy } 461eda14cbcSMatt Macy 462eda14cbcSMatt Macy void * 463eda14cbcSMatt Macy fmd_case_getspecific(fmd_hdl_t *hdl, fmd_case_t *cp) 464eda14cbcSMatt Macy { 465e92ffd9bSMartin Matuska (void) hdl; 466eda14cbcSMatt Macy return (cp->ci_data); 467eda14cbcSMatt Macy } 468eda14cbcSMatt Macy 469eda14cbcSMatt Macy void 470eda14cbcSMatt Macy fmd_buf_create(fmd_hdl_t *hdl, fmd_case_t *cp, const char *name, size_t size) 471eda14cbcSMatt Macy { 472e92ffd9bSMartin Matuska assert(strcmp(name, "data") == 0), (void) name; 473eda14cbcSMatt Macy assert(cp->ci_bufptr == NULL); 474eda14cbcSMatt Macy assert(size < (1024 * 1024)); 475eda14cbcSMatt Macy 476eda14cbcSMatt Macy cp->ci_bufptr = fmd_hdl_alloc(hdl, size, FMD_SLEEP); 477eda14cbcSMatt Macy cp->ci_bufsiz = size; 478eda14cbcSMatt Macy } 479eda14cbcSMatt Macy 480eda14cbcSMatt Macy void 481eda14cbcSMatt Macy fmd_buf_read(fmd_hdl_t *hdl, fmd_case_t *cp, 482eda14cbcSMatt Macy const char *name, void *buf, size_t size) 483eda14cbcSMatt Macy { 484e92ffd9bSMartin Matuska (void) hdl; 485e92ffd9bSMartin Matuska assert(strcmp(name, "data") == 0), (void) name; 486eda14cbcSMatt Macy assert(cp->ci_bufptr != NULL); 487eda14cbcSMatt Macy assert(size <= cp->ci_bufsiz); 488eda14cbcSMatt Macy 489da5137abSMartin Matuska memcpy(buf, cp->ci_bufptr, size); 490eda14cbcSMatt Macy } 491eda14cbcSMatt Macy 492eda14cbcSMatt Macy void 493eda14cbcSMatt Macy fmd_buf_write(fmd_hdl_t *hdl, fmd_case_t *cp, 494eda14cbcSMatt Macy const char *name, const void *buf, size_t size) 495eda14cbcSMatt Macy { 496e92ffd9bSMartin Matuska (void) hdl; 497e92ffd9bSMartin Matuska assert(strcmp(name, "data") == 0), (void) name; 498eda14cbcSMatt Macy assert(cp->ci_bufptr != NULL); 499eda14cbcSMatt Macy assert(cp->ci_bufsiz >= size); 500eda14cbcSMatt Macy 501da5137abSMartin Matuska memcpy(cp->ci_bufptr, buf, size); 502eda14cbcSMatt Macy } 503eda14cbcSMatt Macy 504eda14cbcSMatt Macy /* SERD Engines */ 505eda14cbcSMatt Macy 506eda14cbcSMatt Macy void 507eda14cbcSMatt Macy fmd_serd_create(fmd_hdl_t *hdl, const char *name, uint_t n, hrtime_t t) 508eda14cbcSMatt Macy { 509eda14cbcSMatt Macy fmd_module_t *mp = (fmd_module_t *)hdl; 510eda14cbcSMatt Macy 511eda14cbcSMatt Macy if (fmd_serd_eng_lookup(&mp->mod_serds, name) != NULL) { 512eda14cbcSMatt Macy zed_log_msg(LOG_ERR, "failed to create SERD engine '%s': " 513eda14cbcSMatt Macy " name already exists", name); 514eda14cbcSMatt Macy return; 515eda14cbcSMatt Macy } 516eda14cbcSMatt Macy 517eda14cbcSMatt Macy (void) fmd_serd_eng_insert(&mp->mod_serds, name, n, t); 518eda14cbcSMatt Macy } 519eda14cbcSMatt Macy 520eda14cbcSMatt Macy void 521eda14cbcSMatt Macy fmd_serd_destroy(fmd_hdl_t *hdl, const char *name) 522eda14cbcSMatt Macy { 523eda14cbcSMatt Macy fmd_module_t *mp = (fmd_module_t *)hdl; 524eda14cbcSMatt Macy 525eda14cbcSMatt Macy fmd_serd_eng_delete(&mp->mod_serds, name); 526eda14cbcSMatt Macy 527eda14cbcSMatt Macy fmd_hdl_debug(hdl, "serd_destroy %s", name); 528eda14cbcSMatt Macy } 529eda14cbcSMatt Macy 530eda14cbcSMatt Macy int 531eda14cbcSMatt Macy fmd_serd_exists(fmd_hdl_t *hdl, const char *name) 532eda14cbcSMatt Macy { 533eda14cbcSMatt Macy fmd_module_t *mp = (fmd_module_t *)hdl; 534eda14cbcSMatt Macy 535eda14cbcSMatt Macy return (fmd_serd_eng_lookup(&mp->mod_serds, name) != NULL); 536eda14cbcSMatt Macy } 537eda14cbcSMatt Macy 538eda14cbcSMatt Macy void 539eda14cbcSMatt Macy fmd_serd_reset(fmd_hdl_t *hdl, const char *name) 540eda14cbcSMatt Macy { 541eda14cbcSMatt Macy fmd_module_t *mp = (fmd_module_t *)hdl; 542eda14cbcSMatt Macy fmd_serd_eng_t *sgp; 543eda14cbcSMatt Macy 544eda14cbcSMatt Macy if ((sgp = fmd_serd_eng_lookup(&mp->mod_serds, name)) == NULL) { 545eda14cbcSMatt Macy zed_log_msg(LOG_ERR, "serd engine '%s' does not exist", name); 546eda14cbcSMatt Macy return; 547eda14cbcSMatt Macy } 548eda14cbcSMatt Macy 549eda14cbcSMatt Macy fmd_serd_eng_reset(sgp); 550eda14cbcSMatt Macy 551eda14cbcSMatt Macy fmd_hdl_debug(hdl, "serd_reset %s", name); 552eda14cbcSMatt Macy } 553eda14cbcSMatt Macy 554eda14cbcSMatt Macy int 555eda14cbcSMatt Macy fmd_serd_record(fmd_hdl_t *hdl, const char *name, fmd_event_t *ep) 556eda14cbcSMatt Macy { 557eda14cbcSMatt Macy fmd_module_t *mp = (fmd_module_t *)hdl; 558eda14cbcSMatt Macy fmd_serd_eng_t *sgp; 559eda14cbcSMatt Macy int err; 560eda14cbcSMatt Macy 561eda14cbcSMatt Macy if ((sgp = fmd_serd_eng_lookup(&mp->mod_serds, name)) == NULL) { 562eda14cbcSMatt Macy zed_log_msg(LOG_ERR, "failed to add record to SERD engine '%s'", 563eda14cbcSMatt Macy name); 564da5137abSMartin Matuska return (0); 565eda14cbcSMatt Macy } 566eda14cbcSMatt Macy err = fmd_serd_eng_record(sgp, ep->ev_hrt); 567eda14cbcSMatt Macy 568eda14cbcSMatt Macy return (err); 569eda14cbcSMatt Macy } 570eda14cbcSMatt Macy 571eda14cbcSMatt Macy /* FMD Timers */ 572eda14cbcSMatt Macy 573eda14cbcSMatt Macy static void 574eda14cbcSMatt Macy _timer_notify(union sigval sv) 575eda14cbcSMatt Macy { 576eda14cbcSMatt Macy fmd_timer_t *ftp = sv.sival_ptr; 577eda14cbcSMatt Macy fmd_hdl_t *hdl = ftp->ft_hdl; 578eda14cbcSMatt Macy fmd_module_t *mp = (fmd_module_t *)hdl; 579eda14cbcSMatt Macy const fmd_hdl_ops_t *ops = mp->mod_info->fmdi_ops; 580eda14cbcSMatt Macy struct itimerspec its; 581eda14cbcSMatt Macy 582eda14cbcSMatt Macy fmd_hdl_debug(hdl, "timer fired (%p)", ftp->ft_tid); 583eda14cbcSMatt Macy 584eda14cbcSMatt Macy /* disarm the timer */ 585da5137abSMartin Matuska memset(&its, 0, sizeof (struct itimerspec)); 586eda14cbcSMatt Macy timer_settime(ftp->ft_tid, 0, &its, NULL); 587eda14cbcSMatt Macy 588eda14cbcSMatt Macy /* Note that the fmdo_timeout can remove this timer */ 589eda14cbcSMatt Macy if (ops->fmdo_timeout != NULL) 590eda14cbcSMatt Macy ops->fmdo_timeout(hdl, ftp, ftp->ft_arg); 591eda14cbcSMatt Macy } 592eda14cbcSMatt Macy 593eda14cbcSMatt Macy /* 594eda14cbcSMatt Macy * Install a new timer which will fire at least delta nanoseconds after the 595eda14cbcSMatt Macy * current time. After the timeout has expired, the module's fmdo_timeout 596eda14cbcSMatt Macy * entry point is called. 597eda14cbcSMatt Macy */ 598eda14cbcSMatt Macy fmd_timer_t * 599eda14cbcSMatt Macy fmd_timer_install(fmd_hdl_t *hdl, void *arg, fmd_event_t *ep, hrtime_t delta) 600eda14cbcSMatt Macy { 601e92ffd9bSMartin Matuska (void) ep; 602eda14cbcSMatt Macy struct sigevent sev; 603eda14cbcSMatt Macy struct itimerspec its; 604eda14cbcSMatt Macy fmd_timer_t *ftp; 605eda14cbcSMatt Macy 606eda14cbcSMatt Macy ftp = fmd_hdl_alloc(hdl, sizeof (fmd_timer_t), FMD_SLEEP); 607eda14cbcSMatt Macy ftp->ft_arg = arg; 608eda14cbcSMatt Macy ftp->ft_hdl = hdl; 609eda14cbcSMatt Macy 610eda14cbcSMatt Macy its.it_value.tv_sec = delta / 1000000000; 611eda14cbcSMatt Macy its.it_value.tv_nsec = delta % 1000000000; 612eda14cbcSMatt Macy its.it_interval.tv_sec = its.it_value.tv_sec; 613eda14cbcSMatt Macy its.it_interval.tv_nsec = its.it_value.tv_nsec; 614eda14cbcSMatt Macy 615eda14cbcSMatt Macy sev.sigev_notify = SIGEV_THREAD; 616eda14cbcSMatt Macy sev.sigev_notify_function = _timer_notify; 617eda14cbcSMatt Macy sev.sigev_notify_attributes = NULL; 618eda14cbcSMatt Macy sev.sigev_value.sival_ptr = ftp; 619eda14cbcSMatt Macy 620eda14cbcSMatt Macy timer_create(CLOCK_REALTIME, &sev, &ftp->ft_tid); 621eda14cbcSMatt Macy timer_settime(ftp->ft_tid, 0, &its, NULL); 622eda14cbcSMatt Macy 623eda14cbcSMatt Macy fmd_hdl_debug(hdl, "installing timer for %d secs (%p)", 624eda14cbcSMatt Macy (int)its.it_value.tv_sec, ftp->ft_tid); 625eda14cbcSMatt Macy 626eda14cbcSMatt Macy return (ftp); 627eda14cbcSMatt Macy } 628eda14cbcSMatt Macy 629eda14cbcSMatt Macy void 630eda14cbcSMatt Macy fmd_timer_remove(fmd_hdl_t *hdl, fmd_timer_t *ftp) 631eda14cbcSMatt Macy { 632eda14cbcSMatt Macy fmd_hdl_debug(hdl, "removing timer (%p)", ftp->ft_tid); 633eda14cbcSMatt Macy 634eda14cbcSMatt Macy timer_delete(ftp->ft_tid); 635eda14cbcSMatt Macy 636eda14cbcSMatt Macy fmd_hdl_free(hdl, ftp, sizeof (fmd_timer_t)); 637eda14cbcSMatt Macy } 638eda14cbcSMatt Macy 639eda14cbcSMatt Macy /* Name-Value Pair Lists */ 640eda14cbcSMatt Macy 641eda14cbcSMatt Macy nvlist_t * 642eda14cbcSMatt Macy fmd_nvl_create_fault(fmd_hdl_t *hdl, const char *class, uint8_t certainty, 643eda14cbcSMatt Macy nvlist_t *asru, nvlist_t *fru, nvlist_t *resource) 644eda14cbcSMatt Macy { 645e92ffd9bSMartin Matuska (void) hdl; 646eda14cbcSMatt Macy nvlist_t *nvl; 647eda14cbcSMatt Macy int err = 0; 648eda14cbcSMatt Macy 649eda14cbcSMatt Macy if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) 650eda14cbcSMatt Macy zed_log_die("failed to xalloc fault nvlist"); 651eda14cbcSMatt Macy 652eda14cbcSMatt Macy err |= nvlist_add_uint8(nvl, FM_VERSION, FM_FAULT_VERSION); 653eda14cbcSMatt Macy err |= nvlist_add_string(nvl, FM_CLASS, class); 654eda14cbcSMatt Macy err |= nvlist_add_uint8(nvl, FM_FAULT_CERTAINTY, certainty); 655eda14cbcSMatt Macy 656eda14cbcSMatt Macy if (asru != NULL) 657eda14cbcSMatt Macy err |= nvlist_add_nvlist(nvl, FM_FAULT_ASRU, asru); 658eda14cbcSMatt Macy if (fru != NULL) 659eda14cbcSMatt Macy err |= nvlist_add_nvlist(nvl, FM_FAULT_FRU, fru); 660eda14cbcSMatt Macy if (resource != NULL) 661eda14cbcSMatt Macy err |= nvlist_add_nvlist(nvl, FM_FAULT_RESOURCE, resource); 662eda14cbcSMatt Macy 663eda14cbcSMatt Macy if (err) 664eda14cbcSMatt Macy zed_log_die("failed to populate nvlist: %s\n", strerror(err)); 665eda14cbcSMatt Macy 666eda14cbcSMatt Macy return (nvl); 667eda14cbcSMatt Macy } 668eda14cbcSMatt Macy 669eda14cbcSMatt Macy /* 670eda14cbcSMatt Macy * sourced from fmd_string.c 671eda14cbcSMatt Macy */ 672eda14cbcSMatt Macy static int 673eda14cbcSMatt Macy fmd_strmatch(const char *s, const char *p) 674eda14cbcSMatt Macy { 675eda14cbcSMatt Macy char c; 676eda14cbcSMatt Macy 677eda14cbcSMatt Macy if (p == NULL) 678eda14cbcSMatt Macy return (0); 679eda14cbcSMatt Macy 680eda14cbcSMatt Macy if (s == NULL) 681eda14cbcSMatt Macy s = ""; /* treat NULL string as the empty string */ 682eda14cbcSMatt Macy 683eda14cbcSMatt Macy do { 684eda14cbcSMatt Macy if ((c = *p++) == '\0') 685eda14cbcSMatt Macy return (*s == '\0'); 686eda14cbcSMatt Macy 687eda14cbcSMatt Macy if (c == '*') { 688eda14cbcSMatt Macy while (*p == '*') 689eda14cbcSMatt Macy p++; /* consecutive *'s can be collapsed */ 690eda14cbcSMatt Macy 691eda14cbcSMatt Macy if (*p == '\0') 692eda14cbcSMatt Macy return (1); 693eda14cbcSMatt Macy 694eda14cbcSMatt Macy while (*s != '\0') { 695eda14cbcSMatt Macy if (fmd_strmatch(s++, p) != 0) 696eda14cbcSMatt Macy return (1); 697eda14cbcSMatt Macy } 698eda14cbcSMatt Macy 699eda14cbcSMatt Macy return (0); 700eda14cbcSMatt Macy } 701eda14cbcSMatt Macy } while (c == *s++); 702eda14cbcSMatt Macy 703eda14cbcSMatt Macy return (0); 704eda14cbcSMatt Macy } 705eda14cbcSMatt Macy 706eda14cbcSMatt Macy int 707eda14cbcSMatt Macy fmd_nvl_class_match(fmd_hdl_t *hdl, nvlist_t *nvl, const char *pattern) 708eda14cbcSMatt Macy { 709e92ffd9bSMartin Matuska (void) hdl; 710eda14cbcSMatt Macy char *class; 711eda14cbcSMatt Macy 712eda14cbcSMatt Macy return (nvl != NULL && 713eda14cbcSMatt Macy nvlist_lookup_string(nvl, FM_CLASS, &class) == 0 && 714eda14cbcSMatt Macy fmd_strmatch(class, pattern)); 715eda14cbcSMatt Macy } 716eda14cbcSMatt Macy 717eda14cbcSMatt Macy nvlist_t * 718eda14cbcSMatt Macy fmd_nvl_alloc(fmd_hdl_t *hdl, int flags) 719eda14cbcSMatt Macy { 720e92ffd9bSMartin Matuska (void) hdl, (void) flags; 721eda14cbcSMatt Macy nvlist_t *nvl = NULL; 722eda14cbcSMatt Macy 723eda14cbcSMatt Macy if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) 724eda14cbcSMatt Macy return (NULL); 725eda14cbcSMatt Macy 726eda14cbcSMatt Macy return (nvl); 727eda14cbcSMatt Macy } 728eda14cbcSMatt Macy 729eda14cbcSMatt Macy 730eda14cbcSMatt Macy /* 731eda14cbcSMatt Macy * ZED Agent specific APIs 732eda14cbcSMatt Macy */ 733eda14cbcSMatt Macy 734eda14cbcSMatt Macy fmd_hdl_t * 735eda14cbcSMatt Macy fmd_module_hdl(const char *name) 736eda14cbcSMatt Macy { 737eda14cbcSMatt Macy if (strcmp(name, "zfs-retire") == 0) 738eda14cbcSMatt Macy return ((fmd_hdl_t *)&zfs_retire_module); 739eda14cbcSMatt Macy if (strcmp(name, "zfs-diagnosis") == 0) 740eda14cbcSMatt Macy return ((fmd_hdl_t *)&zfs_diagnosis_module); 741eda14cbcSMatt Macy 742eda14cbcSMatt Macy return (NULL); 743eda14cbcSMatt Macy } 744eda14cbcSMatt Macy 745eda14cbcSMatt Macy boolean_t 746eda14cbcSMatt Macy fmd_module_initialized(fmd_hdl_t *hdl) 747eda14cbcSMatt Macy { 748eda14cbcSMatt Macy fmd_module_t *mp = (fmd_module_t *)hdl; 749eda14cbcSMatt Macy 750eda14cbcSMatt Macy return (mp->mod_info != NULL); 751eda14cbcSMatt Macy } 752eda14cbcSMatt Macy 753eda14cbcSMatt Macy /* 754eda14cbcSMatt Macy * fmd_module_recv is called for each event that is received by 755eda14cbcSMatt Macy * the fault manager that has a class that matches one of the 756eda14cbcSMatt Macy * module's subscriptions. 757eda14cbcSMatt Macy */ 758eda14cbcSMatt Macy void 759eda14cbcSMatt Macy fmd_module_recv(fmd_hdl_t *hdl, nvlist_t *nvl, const char *class) 760eda14cbcSMatt Macy { 761eda14cbcSMatt Macy fmd_module_t *mp = (fmd_module_t *)hdl; 762eda14cbcSMatt Macy const fmd_hdl_ops_t *ops = mp->mod_info->fmdi_ops; 763eda14cbcSMatt Macy fmd_event_t faux_event = {0}; 764eda14cbcSMatt Macy int64_t *tv; 765eda14cbcSMatt Macy uint_t n; 766eda14cbcSMatt Macy 767eda14cbcSMatt Macy /* 768eda14cbcSMatt Macy * Will need to normalized this if we persistently store the case data 769eda14cbcSMatt Macy */ 770eda14cbcSMatt Macy if (nvlist_lookup_int64_array(nvl, FM_EREPORT_TIME, &tv, &n) == 0) 771eda14cbcSMatt Macy faux_event.ev_hrt = tv[0] * NANOSEC + tv[1]; 772eda14cbcSMatt Macy else 773eda14cbcSMatt Macy faux_event.ev_hrt = 0; 774eda14cbcSMatt Macy 775eda14cbcSMatt Macy ops->fmdo_recv(hdl, &faux_event, nvl, class); 776eda14cbcSMatt Macy 777eda14cbcSMatt Macy mp->mod_stats.ms_accepted.fmds_value.ui64++; 778eda14cbcSMatt Macy 779eda14cbcSMatt Macy /* TBD - should we initiate fm_module_gc() periodically? */ 780eda14cbcSMatt Macy } 781