void _fmd_init(fmd_hdl_t *hdl) { sp_monitor_t *smp; int error; char *msg; if (fmd_hdl_register(hdl, FMD_API_VERSION, &fmd_info) != 0) return; smp = fmd_hdl_zalloc(hdl, sizeof (sp_monitor_t), FMD_SLEEP); fmd_hdl_setspecific(hdl, smp); if ((smp->sm_hdl = ipmi_open(&error, &msg, IPMI_TRANSPORT_BMC, NULL)) == NULL) { /* * If /dev/ipmi0 doesn't exist on the system, then unload the * module without doing anything. */ if (error != EIPMI_BMC_OPEN_FAILED) fmd_hdl_abort(hdl, "failed to initialize IPMI " "connection: %s\n", msg); fmd_hdl_debug(hdl, "failed to load: no IPMI connection " "present"); fmd_hdl_free(hdl, smp, sizeof (sp_monitor_t)); fmd_hdl_unregister(hdl); return; } /* * Attempt an initial uptime() call. If the IPMI command is * unrecognized, then this is an unsupported platform and the module * should be unloaded. Any other error is treated is transient failure. */ if ((error = ipmi_sunoem_uptime(smp->sm_hdl, &smp->sm_seconds, &smp->sm_generation)) != 0 && ipmi_errno(smp->sm_hdl) == EIPMI_INVALID_COMMAND) { fmd_hdl_debug(hdl, "failed to load: uptime command " "not supported"); ipmi_close(smp->sm_hdl); fmd_hdl_free(hdl, smp, sizeof (sp_monitor_t)); fmd_hdl_unregister(hdl); return; } smp->sm_interval = fmd_prop_get_int64(hdl, "interval"); if (error == 0) fmd_hdl_debug(hdl, "successfully loaded, uptime = %u seconds " "(generation %u)", smp->sm_seconds, smp->sm_generation); else fmd_hdl_debug(hdl, "successfully loaded, but uptime call " "failed: %s", ipmi_errmsg(smp->sm_hdl)); /* * Setup the recurring timer. */ (void) fmd_timer_install(hdl, NULL, NULL, 0); }
static void gmem_dimm_free(fmd_hdl_t *hdl, gmem_dimm_t *dimm, int destroy) { gmem_case_t *cc = &dimm->dimm_case; int i; gmem_mq_t *q; tstamp_t *tsp, *next; if (cc->cc_cp != NULL) { gmem_case_fini(hdl, cc->cc_cp, destroy); if (cc->cc_serdnm != NULL) { if (fmd_serd_exists(hdl, cc->cc_serdnm) && destroy) fmd_serd_destroy(hdl, cc->cc_serdnm); fmd_hdl_strfree(hdl, cc->cc_serdnm); } } gmem_fmri_fini(hdl, &dimm->dimm_asru, destroy); for (i = 0; i < GMEM_MAX_CKWDS; i++) { while ((q = gmem_list_next(&dimm->mq_root[i])) != NULL) { if (q->mq_serdnm != NULL) { if (fmd_serd_exists(hdl, q->mq_serdnm)) fmd_serd_destroy(hdl, q->mq_serdnm); fmd_hdl_strfree(hdl, q->mq_serdnm); q->mq_serdnm = NULL; } for (tsp = gmem_list_next(&q->mq_dupce_tstamp); tsp != NULL; tsp = next) { next = gmem_list_next(tsp); gmem_list_delete(&q->mq_dupce_tstamp, &tsp->ts_l); fmd_hdl_free(hdl, tsp, sizeof (tstamp_t)); } gmem_list_delete(&dimm->mq_root[i], q); fmd_hdl_free(hdl, q, sizeof (gmem_mq_t)); } } if (destroy) fmd_buf_destroy(hdl, NULL, dimm->dimm_bufname); gmem_list_delete(&gmem.gm_dimms, dimm); fmd_hdl_free(hdl, dimm, sizeof (gmem_dimm_t)); }
nvlist_t * cmd_fault_add_location(fmd_hdl_t *hdl, nvlist_t *flt, const char *locstr) { char *t, *s; if (nvlist_lookup_string(flt, FM_FAULT_LOCATION, &t) == 0) return (flt); /* already has location value */ /* Replace occurrence of ": " with "/" to avoid confusing ILOM. */ t = fmd_hdl_zalloc(hdl, strlen(locstr) + 1, FMD_SLEEP); s = strstr(locstr, ": "); if (s != NULL) { (void) strncpy(t, locstr, s - locstr); (void) strcat(t, "/"); (void) strcat(t, s + 2); } else { (void) strcpy(t, locstr); } /* Also, remove any J number from end of this string. */ s = strstr(t, "/J"); if (s != NULL) *s = '\0'; if (nvlist_add_string(flt, FM_FAULT_LOCATION, t) != 0) fmd_hdl_error(hdl, "unable to alloc location for fault\n"); fmd_hdl_free(hdl, t, strlen(locstr) + 1); return (flt); }
static void cpumem_free(void *addr, size_t size) { assert(cpumem_hdl != NULL); fmd_hdl_free(cpumem_hdl, addr, size); }
static void cma_page_free(fmd_hdl_t *hdl, cma_page_t *page) { nvlist_free(page->pg_asru); nvlist_free(page->pg_rsrc); fmd_hdl_free(hdl, page, sizeof (cma_page_t)); }
static void branch_free(fmd_hdl_t *hdl, cmd_branch_t *branch, int destroy) { fmd_hdl_debug(hdl, "Free branch %s\n", branch->branch_unum); if (branch->branch_case.cc_cp != NULL) { if (destroy) { if (branch->branch_case.cc_serdnm != NULL) { fmd_serd_destroy(hdl, branch->branch_case.cc_serdnm); fmd_hdl_strfree(hdl, branch->branch_case.cc_serdnm); branch->branch_case.cc_serdnm = NULL; } } cmd_case_fini(hdl, branch->branch_case.cc_cp, destroy); } branch_dimmlist_free(hdl, branch); cmd_fmri_fini(hdl, &branch->branch_asru, destroy); if (destroy) fmd_buf_destroy(hdl, NULL, branch->branch_bufname); cmd_list_delete(&cmd.cmd_branches, branch); fmd_hdl_free(hdl, branch, sizeof (cmd_branch_t)); }
/* * Read back the persistent representation of an active case. */ static zfs_case_t * zfs_case_unserialize(fmd_hdl_t *hdl, fmd_case_t *cp) { zfs_case_t *zcp; zcp = fmd_hdl_zalloc(hdl, sizeof (zfs_case_t), FMD_SLEEP); zcp->zc_case = cp; fmd_buf_read(hdl, cp, CASE_DATA, &zcp->zc_data, sizeof (zcp->zc_data)); if (zcp->zc_data.zc_version > CASE_DATA_VERSION_SERD) { fmd_hdl_free(hdl, zcp, sizeof (zfs_case_t)); return (NULL); } /* * fmd_buf_read() will have already zeroed out the remainder of the * buffer, so we don't have to do anything special if the version * doesn't include the SERD engine name. */ if (zcp->zc_data.zc_has_remove_timer) zcp->zc_remove_timer = fmd_timer_install(hdl, zcp, NULL, zfs_remove_timeout); uu_list_node_init(zcp, &zcp->zc_node, zfs_case_pool); (void) uu_list_insert_before(zfs_cases, NULL, zcp); fmd_case_setspecific(hdl, cp, zcp); return (zcp); }
static void cmd_dimm_free(fmd_hdl_t *hdl, cmd_dimm_t *dimm, int destroy) { cmd_case_t *cc = &dimm->dimm_case; #ifdef sun4v cmd_branch_t *branch; #endif if (cc->cc_cp != NULL) { cmd_case_fini(hdl, cc->cc_cp, destroy); if (cc->cc_serdnm != NULL) { if (fmd_serd_exists(hdl, cc->cc_serdnm) && destroy) fmd_serd_destroy(hdl, cc->cc_serdnm); fmd_hdl_strfree(hdl, cc->cc_serdnm); } } if (dimm->dimm_bank != NULL) cmd_bank_remove_dimm(hdl, dimm->dimm_bank, dimm); #ifdef sun4v branch = cmd_branch_lookup_by_unum(hdl, dimm->dimm_unum); if (branch != NULL) cmd_branch_remove_dimm(hdl, branch, dimm); #endif cmd_fmri_fini(hdl, &dimm->dimm_asru, destroy); if (destroy) fmd_buf_destroy(hdl, NULL, dimm->dimm_bufname); cmd_list_delete(&cmd.cmd_dimms, dimm); fmd_hdl_free(hdl, dimm, sizeof (cmd_dimm_t)); }
/* * Teardown any transport infrastructure after all connections are closed. * Return 0 for success, or nonzero for failure. */ int etm_xport_fini(fmd_hdl_t *hdl, etm_xport_hdl_t tlhdl) { exs_hdl_t *hp = (exs_hdl_t *)tlhdl; exs_hdl_t *xp, **ppx; (void) pthread_mutex_lock(&List_lock); ppx = &Exh_head; for (xp = *ppx; xp; xp = xp->h_next) { if (xp != hp) ppx = &xp->h_next; else break; } if (xp != hp) { (void) pthread_mutex_unlock(&List_lock); fmd_hdl_abort(hdl, "xport - fini failed, tlhdl %p not on list", (void *)hp); } *ppx = hp->h_next; hp->h_next = NULL; if (hp->h_tid != EXS_TID_FREE) { hp->h_quit = 1; fmd_thr_signal(hdl, hp->h_tid); fmd_thr_destroy(hdl, hp->h_tid); } if (hp->h_server.c_sd != EXS_SD_FREE) (void) close(hp->h_server.c_sd); if (hp->h_client.c_sd != EXS_SD_FREE) (void) close(hp->h_client.c_sd); fmd_hdl_strfree(hdl, hp->h_endpt_id); fmd_hdl_free(hdl, hp, sizeof (exs_hdl_t)); if (Exh_head == NULL) { /* Undo one-time initializations */ exs_filter_fini(hdl); /* Destroy the accept/listen thread */ if (Acc_tid != EXS_TID_FREE) { Acc_quit = 1; fmd_thr_signal(hdl, Acc_tid); fmd_thr_destroy(hdl, Acc_tid); } if (Acc.c_sd != EXS_SD_FREE) EXS_CLOSE_CLR(Acc); } (void) pthread_mutex_unlock(&List_lock); return (0); }
static void cma_cpu_free(fmd_hdl_t *hdl, cma_cpu_t *cpu) { if (cpu->cpu_fmri != NULL) nvlist_free(cpu->cpu_fmri); if (cpu->cpu_uuid != NULL) fmd_hdl_strfree(hdl, cpu->cpu_uuid); fmd_hdl_free(hdl, cpu, sizeof (cma_cpu_t)); }
static void branch_dimmlist_free(fmd_hdl_t *hdl, cmd_branch_t *branch) { cmd_branch_memb_t *bm; while ((bm = cmd_list_next(&branch->branch_dimms)) != NULL) { cmd_list_delete(&branch->branch_dimms, bm); fmd_hdl_free(hdl, bm, sizeof (cmd_branch_memb_t)); } }
void _fmd_fini(fmd_hdl_t *hdl) { sp_monitor_t *smp = fmd_hdl_getspecific(hdl); if (smp) { ipmi_close(smp->sm_hdl); fmd_hdl_free(hdl, smp, sizeof (sp_monitor_t)); } }
static void free_notify_prefs(fmd_hdl_t *hdl, nvlist_t **prefs, uint_t nprefs) { int i; for (i = 0; i < nprefs; i++) { nvlist_free(prefs[i]); } fmd_hdl_free(hdl, prefs, sizeof (nvlist_t *) * nprefs); }
static int get_notify_prefs(fmd_hdl_t *hdl, nvlist_t *ev_nvl, nvlist_t ***pref_nvl, uint_t *nprefs) { nvlist_t *top_nvl, **np_nvlarr, *mech_nvl; nvlist_t **tmparr; int ret, i; uint_t nelem, nslelem; if ((ret = smf_notify_get_params(&top_nvl, ev_nvl)) != SCF_SUCCESS) { ret = scf_error(); if (ret != SCF_ERROR_NOT_FOUND) { fmd_hdl_debug(hdl, "Error looking up notification " "preferences (%s)", scf_strerror(ret)); return (ret); } return (ret); } if (nvlist_lookup_nvlist_array(top_nvl, SCF_NOTIFY_PARAMS, &np_nvlarr, &nelem) != 0) { fmd_hdl_debug(hdl, "Malformed preference nvlist\n"); ret = SCF_ERROR_INVALID_ARGUMENT; goto pref_done; } tmparr = fmd_hdl_alloc(hdl, nelem * sizeof (nvlist_t *), FMD_SLEEP); nslelem = 0; for (i = 0; i < nelem; i++) { if (nvlist_lookup_nvlist(np_nvlarr[i], "syslog", &mech_nvl) == 0) tmparr[nslelem++] = fmd_nvl_dup(hdl, mech_nvl, FMD_SLEEP); } if (nslelem != 0) { size_t sz = nslelem * sizeof (nvlist_t *); *pref_nvl = fmd_hdl_zalloc(hdl, sz, FMD_SLEEP); *nprefs = nslelem; bcopy(tmparr, *pref_nvl, sz); ret = 0; } else { *pref_nvl = NULL; *nprefs = 0; ret = SCF_ERROR_NOT_FOUND; } fmd_hdl_free(hdl, tmparr, nelem * sizeof (nvlist_t *)); pref_done: nvlist_free(top_nvl); return (ret); }
static void etm_xport_free_addr(fmd_hdl_t *hdl, etm_xport_addr_t addr) { if (addr == NULL) { etm_xport_stats.xport_free_addr_badargs.fmds_value.ui64++; return; } fmd_hdl_free(hdl, addr, sizeof (_etm_xport_addr_t)); } /* etm_xport_free_addr() */
etm_xport_conn_t etm_xport_close(fmd_hdl_t *hdl, etm_xport_conn_t conn) { etm_xport_conn_t rv; /* ret val */ _etm_xport_conn_t *_conn; /* connection handle */ int nev; /* -errno val */ _conn = conn; rv = _conn; /* assume success */ if ((nev = etm_xport_valid_conn(_conn)) < 0) { _conn = NULL; rv = NULL; goto func_ret; } /* close the device node */ (void) pthread_mutex_lock(&etm_xport_vldc_lock); if (close(_conn->fd) < 0) { /* errno assumed set by above call */ etm_xport_stats.xport_os_close_fail.fmds_value.ui64++; nev = (-errno); rv = NULL; } if (use_vldc && (_conn == etm_xport_vldc_conn)) { etm_xport_vldc_conn = NULL; } (void) pthread_mutex_unlock(&etm_xport_vldc_lock); func_ret: /* cleanup the connection */ if (_conn != NULL) { etm_xport_free_addr(hdl, _conn->addr); _conn->addr = NULL; _conn->magic_num = 0; _conn->fd = -1; fmd_hdl_free(hdl, _conn, sizeof (_etm_xport_conn_t)); } if (rv == NULL) { errno = (-nev); } return (rv); } /* etm_xport_close() */
static cmd_branch_t * branch_wrapv0(fmd_hdl_t *hdl, cmd_branch_pers_t *pers, size_t psz) { cmd_branch_t *branch; if (psz != sizeof (cmd_branch_pers_t)) { fmd_hdl_abort(hdl, "size of state doesn't match size of " "version 0 state (%u bytes).\n", sizeof (cmd_branch_pers_t)); } branch = fmd_hdl_zalloc(hdl, sizeof (cmd_branch_t), FMD_SLEEP); bcopy(pers, branch, sizeof (cmd_branch_pers_t)); fmd_hdl_free(hdl, pers, psz); return (branch); }
void etm_xport_free_addrv(fmd_hdl_t *hdl, etm_xport_addr_t *addrv) { _etm_xport_addr_t **_addrv; /* vector of addrs */ int i; /* vector index */ if (addrv == NULL) { etm_xport_stats.xport_free_addrv_badargs.fmds_value.ui64++; return; } _addrv = (void*)addrv; for (i = 0; _addrv[i] != NULL; i++) { etm_xport_free_addr(hdl, _addrv[i]); _addrv[i] = NULL; } fmd_hdl_free(hdl, _addrv, (i + 1) * sizeof (_etm_xport_addr_t *)); } /* etm_xport_free_addrv() */
void cmd_branch_remove_dimm(fmd_hdl_t *hdl, cmd_branch_t *branch, cmd_dimm_t *dimm) { cmd_branch_memb_t *bm; fmd_hdl_debug(hdl, "Detaching dimm %s from branch %s\n", dimm->dimm_unum, branch->branch_unum); for (bm = cmd_list_next(&branch->branch_dimms); bm != NULL; bm = cmd_list_next(bm)) { if (bm->dimm == dimm) { cmd_list_delete(&branch->branch_dimms, bm); fmd_hdl_free(hdl, bm, sizeof (cmd_branch_memb_t)); return; } } fmd_hdl_abort(hdl, "Attempt to disconnect dimm from non-parent branch\n"); }
void cmd_dimm_destroy(fmd_hdl_t *hdl, cmd_dimm_t *dimm) { int i; cmd_mq_t *q; for (i = 0; i < CMD_MAX_CKWDS; i++) { while ((q = cmd_list_next(&dimm->mq_root[i])) != NULL) { if (q->mq_serdnm != NULL) { if (fmd_serd_exists(hdl, q->mq_serdnm)) { fmd_serd_destroy(hdl, q->mq_serdnm); } fmd_hdl_strfree(hdl, q->mq_serdnm); q->mq_serdnm = NULL; } cmd_list_delete(&dimm->mq_root[i], q); fmd_hdl_free(hdl, q, sizeof (cmd_mq_t)); } } fmd_stat_destroy(hdl, 1, &(dimm->dimm_retstat)); cmd_dimm_free(hdl, dimm, FMD_B_TRUE); }
int etm_xport_fini(fmd_hdl_t *hdl) { fmd_hdl_debug(hdl, "info: xport finalizing\n"); if (use_vldc && (etm_xport_vldc_conn != NULL)) { (void) etm_xport_close(hdl, etm_xport_vldc_conn); etm_xport_vldc_conn = NULL; } /* free any long standing properties from FMD */ fmd_prop_free_string(hdl, etm_xport_addrs); /* cleanup the intermediate read buffer */ if (etm_xport_irb_tail != etm_xport_irb_head) { fmd_hdl_debug(hdl, "warning: xport %d bytes stale data\n", (int)(etm_xport_irb_tail - etm_xport_irb_head)); } fmd_hdl_free(hdl, etm_xport_irb_area, 2 * etm_xport_irb_mtu_sz); etm_xport_irb_area = NULL; etm_xport_irb_head = NULL; etm_xport_irb_tail = NULL; etm_xport_irb_mtu_sz = 0; /* cleanup statistics from FMD */ (void) fmd_stat_destroy(hdl, sizeof (etm_xport_stats) / sizeof (fmd_stat_t), (fmd_stat_t *)&etm_xport_stats); fmd_hdl_debug(hdl, "info: xport finalized ok\n"); return (0); } /* etm_xport_fini() */
etm_xport_conn_t etm_xport_open(fmd_hdl_t *hdl, etm_xport_addr_t addr) { _etm_xport_addr_t *_addr; /* address handle */ _etm_xport_conn_t *_conn; /* connection handle */ ssize_t n; /* gen use */ if ((n = etm_xport_valid_addr(addr)) < 0) { errno = (-n); return (NULL); } _addr = etm_xport_dup_addr(hdl, addr); /* allocate a connection handle and start populating it */ _conn = fmd_hdl_zalloc(hdl, sizeof (_etm_xport_conn_t), FMD_SLEEP); (void) pthread_mutex_lock(&etm_xport_vldc_lock); if (use_vldc == 0 || etm_xport_vldc_conn == NULL) { if ((_conn->fd = open(_addr->fn, ETM_XPORT_OPEN_FLAGS, 0)) == -1) { /* errno assumed set by above call */ etm_xport_free_addr(hdl, _addr); fmd_hdl_free(hdl, _conn, sizeof (_etm_xport_conn_t)); etm_xport_stats.xport_os_open_fail.fmds_value.ui64++; (void) pthread_mutex_unlock(&etm_xport_vldc_lock); return (NULL); } } if (use_vldc && etm_xport_vldc_conn == NULL) { vldc_opt_op_t op; /* Set the channel to reliable mode */ op.op_sel = VLDC_OP_SET; op.opt_sel = VLDC_OPT_MODE; op.opt_val = LDC_MODE_RELIABLE; if (ioctl(_conn->fd, VLDC_IOCTL_OPT_OP, &op) != 0) { /* errno assumed set by above call */ (void) close(_conn->fd); etm_xport_free_addr(hdl, _addr); fmd_hdl_free(hdl, _conn, sizeof (_etm_xport_conn_t)); etm_xport_stats.xport_os_ioctl_fail.fmds_value.ui64++; (void) pthread_mutex_unlock(&etm_xport_vldc_lock); return (NULL); } etm_xport_vldc_conn = _conn; } else if (use_vldc && etm_xport_vldc_conn != NULL) { _conn->fd = dup(etm_xport_vldc_conn->fd); } (void) pthread_mutex_unlock(&etm_xport_vldc_lock); /* return the fully formed connection handle */ _conn->magic_num = ETM_XPORT_DD_MAGIC_CONN; _conn->addr = _addr; return (_conn); } /* etm_xport_open() */
nvlist_t * cmd_mkboard_fru(fmd_hdl_t *hdl, char *frustr, char *serialstr, char *partstr) { char *nac, *nac_name; int n, i, len; nvlist_t *fru, **hc_list; if (frustr == NULL) return (NULL); if ((nac_name = strstr(frustr, "MB")) == NULL) return (NULL); len = strlen(nac_name) + 1; nac = fmd_hdl_zalloc(hdl, len, FMD_SLEEP); (void) strcpy(nac, nac_name); n = cmd_count_components(nac, '/'); fmd_hdl_debug(hdl, "cmd_mkboard_fru: nac=%s components=%d\n", nac, n); hc_list = fmd_hdl_zalloc(hdl, sizeof (nvlist_t *)*n, FMD_SLEEP); for (i = 0; i < n; i++) { (void) nvlist_alloc(&hc_list[i], NV_UNIQUE_NAME|NV_UNIQUE_NAME_TYPE, 0); } if (cmd_breakup_components(nac, "/", hc_list) < 0) { for (i = 0; i < n; i++) { if (hc_list[i] != NULL) nvlist_free(hc_list[i]); } fmd_hdl_free(hdl, hc_list, sizeof (nvlist_t *)*n); fmd_hdl_free(hdl, nac, len); return (NULL); } if (nvlist_alloc(&fru, NV_UNIQUE_NAME, 0) != 0) { for (i = 0; i < n; i++) { if (hc_list[i] != NULL) nvlist_free(hc_list[i]); } fmd_hdl_free(hdl, hc_list, sizeof (nvlist_t *)*n); fmd_hdl_free(hdl, nac, len); return (NULL); } if (nvlist_add_uint8(fru, FM_VERSION, FM_HC_SCHEME_VERSION) != 0 || nvlist_add_string(fru, FM_FMRI_SCHEME, FM_FMRI_SCHEME_HC) != 0 || nvlist_add_string(fru, FM_FMRI_HC_ROOT, "") != 0 || nvlist_add_uint32(fru, FM_FMRI_HC_LIST_SZ, n) != 0 || nvlist_add_nvlist_array(fru, FM_FMRI_HC_LIST, hc_list, n) != 0) { for (i = 0; i < n; i++) { if (hc_list[i] != NULL) nvlist_free(hc_list[i]); } fmd_hdl_free(hdl, hc_list, sizeof (nvlist_t *)*n); fmd_hdl_free(hdl, nac, len); nvlist_free(fru); return (NULL); } for (i = 0; i < n; i++) { if (hc_list[i] != NULL) nvlist_free(hc_list[i]); } fmd_hdl_free(hdl, hc_list, sizeof (nvlist_t *)*n); fmd_hdl_free(hdl, nac, len); if ((serialstr != NULL && nvlist_add_string(fru, FM_FMRI_HC_SERIAL_ID, serialstr) != 0) || (partstr != NULL && nvlist_add_string(fru, FM_FMRI_HC_PART, partstr) != 0)) { nvlist_free(fru); return (NULL); } return (fru); }