void topo_pgroup_destroy_all(tnode_t *node) { topo_hdl_t *thp = node->tn_hdl; topo_pgroup_t *pg; topo_proplist_t *pvl; topo_ipgroup_info_t *pip; topo_node_lock(node); while ((pg = topo_list_next(&node->tn_pgroups)) != NULL) { while ((pvl = topo_list_next(&pg->tpg_pvals)) != NULL) { topo_list_delete(&pg->tpg_pvals, pvl); topo_prop_rele(pvl->tp_pval); topo_hdl_free(thp, pvl, sizeof (topo_proplist_t)); } topo_list_delete(&node->tn_pgroups, pg); pip = pg->tpg_info; if (pip != NULL) { if (pip->tpi_name != NULL) topo_hdl_strfree(thp, (char *)pip->tpi_name); topo_hdl_free(thp, pip, sizeof (topo_pgroup_info_t)); } topo_hdl_free(thp, pg, sizeof (topo_pgroup_t)); } topo_node_unlock(node); }
static int pgroup_seterr(tnode_t *node, topo_pgroup_t *pg, topo_ipgroup_info_t *pip, int *err) { topo_hdl_t *thp = node->tn_hdl; if (pip != NULL) { if (pip->tpi_name != NULL) topo_hdl_strfree(thp, (char *)pip->tpi_name); topo_hdl_free(thp, pip, sizeof (topo_ipgroup_info_t)); } topo_hdl_free(thp, pg, sizeof (topo_pgroup_t)); *err = ETOPO_NOMEM; topo_node_unlock(node); return (-1); }
void topo_walk_fini(topo_walk_t *wp) { if (wp == NULL) return; topo_node_rele(wp->tw_root); topo_hdl_free(wp->tw_thp, wp, sizeof (topo_walk_t)); }
void topo_pgroup_destroy(tnode_t *node, const char *pname) { topo_hdl_t *thp = node->tn_hdl; topo_pgroup_t *pg; topo_proplist_t *pvl; topo_ipgroup_info_t *pip; topo_node_lock(node); for (pg = topo_list_next(&node->tn_pgroups); pg != NULL; pg = topo_list_next(pg)) { if (strcmp(pg->tpg_info->tpi_name, pname) == 0) { break; } } if (pg == NULL) { topo_node_unlock(node); return; } while ((pvl = topo_list_next(&pg->tpg_list)) != NULL) { topo_list_delete(&pg->tpg_pvals, pvl); topo_prop_rele(pvl->tp_pval); topo_hdl_free(thp, pvl, sizeof (topo_proplist_t)); } topo_list_delete(&node->tn_pgroups, pg); topo_node_unlock(node); pip = pg->tpg_info; if (pip != NULL) { if (pip->tpi_name != NULL) topo_hdl_strfree(thp, (char *)pip->tpi_name); topo_hdl_free(thp, pip, sizeof (topo_ipgroup_info_t)); } topo_hdl_free(thp, pg, sizeof (topo_pgroup_t)); }
void topo_file_unload(topo_hdl_t *thp, ttree_t *tp) { topo_file_t *tfp = tp->tt_file; if (tfp == NULL) return; if (tfp->tf_fileinfo != NULL) tf_info_free(tfp->tf_mod, tfp->tf_fileinfo); topo_hdl_free(thp, tfp, sizeof (topo_file_t)); tp->tt_file = NULL; }
static void propmethod_destroy(topo_hdl_t *thp, topo_propval_t *pv) { topo_propmethod_t *pm; pm = pv->tp_method; if (pm != NULL) { if (pm->tpm_name != NULL) topo_hdl_strfree(thp, pm->tpm_name); if (pm->tpm_args != NULL) nvlist_free(pm->tpm_args); topo_hdl_free(thp, pm, sizeof (topo_propmethod_t)); pv->tp_method = NULL; } }
static topo_propval_t * set_seterror(tnode_t *node, topo_proplist_t *pvl, int *errp, int err) { topo_hdl_t *thp = node->tn_hdl; topo_propval_t *pv; if (pvl != NULL) { pv = pvl->tp_pval; topo_propval_destroy(pv); topo_hdl_free(thp, pvl, sizeof (topo_proplist_t)); } topo_node_unlock(node); *errp = err; return (NULL); }
static void topo_propval_destroy(topo_propval_t *pv) { topo_hdl_t *thp; if (pv == NULL) return; thp = pv->tp_hdl; if (pv->tp_name != NULL) topo_hdl_strfree(thp, pv->tp_name); if (pv->tp_val != NULL) nvlist_free(pv->tp_val); propmethod_destroy(thp, pv); topo_hdl_free(thp, pv, sizeof (topo_propval_t)); }
static int register_methoderror(tnode_t *node, topo_propmethod_t *pm, int *errp, int l, int err) { topo_hdl_t *thp = node->tn_hdl; if (pm != NULL) { if (pm->tpm_name != NULL) topo_hdl_strfree(thp, pm->tpm_name); if (pm->tpm_args != NULL) nvlist_free(pm->tpm_args); topo_hdl_free(thp, pm, sizeof (topo_propmethod_t)); } *errp = err; if (l != 0) topo_node_unlock(node); return (-1); }
static void print_pgroup(topo_hdl_t *thp, tnode_t *node, const char *pgn, char *dstab, char *nstab, int32_t version) { int err; char buf[30]; topo_pgroup_info_t *pgi = NULL; if (pgn == NULL) return; if (node != NULL && (dstab == NULL || nstab == NULL || version == -1)) { if ((pgi = topo_pgroup_info(node, pgn, &err)) != NULL) { dstab = (char *)topo_stability2name(pgi->tpi_datastab); nstab = (char *)topo_stability2name(pgi->tpi_namestab); version = pgi->tpi_version; } } if (dstab == NULL || nstab == NULL || version == -1) { (void) printf(" group: %-30s version: - stability: -/-\n", pgn); } else if (!opt_V && strlen(pgn) > 30) { (void) snprintf(buf, 26, "%s", pgn); (void) snprintf(&buf[27], 4, "%s", DOTS); (void) printf(" group: %-30s version: %-3d stability: %s/%s\n", buf, version, nstab, dstab); } else { (void) printf(" group: %-30s version: %-3d stability: %s/%s\n", pgn, version, nstab, dstab); } if (pgi != NULL) { topo_hdl_strfree(thp, (char *)pgi->tpi_name); topo_hdl_free(thp, pgi, sizeof (topo_pgroup_info_t)); } }
void topo_prop_method_unregister(tnode_t *node, const char *pgname, const char *pname) { topo_propval_t *pv; topo_pgroup_t *pg; topo_proplist_t *pvl; topo_hdl_t *thp = node->tn_hdl; topo_node_lock(node); for (pg = topo_list_next(&node->tn_pgroups); pg != NULL; pg = topo_list_next(pg)) { if (strcmp(pg->tpg_info->tpi_name, pgname) == 0) { break; } } if (pg == NULL) { topo_node_unlock(node); return; } for (pvl = topo_list_next(&pg->tpg_list); pvl != NULL; pvl = topo_list_next(pvl)) { pv = pvl->tp_pval; if (strcmp(pv->tp_name, pname) == 0) { topo_list_delete(&pg->tpg_pvals, pvl); assert(pv->tp_refs == 1); topo_prop_rele(pv); topo_hdl_free(thp, pvl, sizeof (topo_proplist_t)); break; } } topo_node_unlock(node); }
topo_pgroup_info_t * topo_pgroup_info(tnode_t *node, const char *pgname, int *err) { topo_hdl_t *thp = node->tn_hdl; topo_pgroup_t *pg; topo_ipgroup_info_t *pip; topo_pgroup_info_t *info; topo_node_lock(node); for (pg = topo_list_next(&node->tn_pgroups); pg != NULL; pg = topo_list_next(pg)) { if (strcmp(pgname, pg->tpg_info->tpi_name) == 0) { if ((info = topo_hdl_alloc(thp, sizeof (topo_pgroup_info_t))) == NULL) return (NULL); pip = pg->tpg_info; if ((info->tpi_name = topo_hdl_strdup(thp, pip->tpi_name)) == NULL) { *err = ETOPO_PROP_NOMEM; topo_hdl_free(thp, info, sizeof (topo_pgroup_info_t)); topo_node_unlock(node); return (NULL); } info->tpi_namestab = pip->tpi_namestab; info->tpi_datastab = pip->tpi_datastab; info->tpi_version = pip->tpi_version; topo_node_unlock(node); return (info); } } *err = ETOPO_PROP_NOENT; topo_node_unlock(node); return (NULL); }
static int topo_add_disk(topo_hdl_t *thp, tnode_t *node, diskmon_t *target_diskp) { nvlist_t *fmri = NULL; nvlist_t *asru_fmri; nvlist_t *fru_fmri; char *devpath = NULL; char *capacity = NULL; char *firmrev = NULL; char *serial = NULL; char *manuf = NULL; char *model = NULL; char *cstr = NULL; char *buf; char *label; char *p; uint64_t ptr = 0; int buflen; int err; int orig_cstr_len; dm_fru_t *frup; diskmon_t *diskp; /* * Match this node to a disk in the configuration by looking at * our parent's fmri (and do that by getting our FMRI and chopping * off the last part). */ if (topo_node_resource(node, &fmri, &err) != 0) { log_msg(MM_TOPO, "topo_add_disk: Could not generate FMRI for " "node %p!\n", (void *)node); return (-1); } if (topo_fmri_nvl2str(thp, fmri, &cstr, &err) != 0) { log_msg(MM_TOPO, "topo_add_disk: Could not create string for " "node %p's FMRI!\n", (void *)node); nvlist_free(fmri); return (-1); } nvlist_free(fmri); /* * Chop off all but last path (since there's no way to get * the node's parent in the libtopo API). */ orig_cstr_len = strlen(cstr) + 1; p = strrchr(cstr, '/'); dm_assert(p != NULL); *p = 0; if (nvlist_lookup_uint64(g_topo2diskmon, cstr, &ptr) != 0) { log_msg(MM_TOPO, "No diskmon for parent of node %p.\n", node); topo_hdl_free(thp, cstr, orig_cstr_len); /* Skip this disk: */ return (0); } topo_hdl_free(thp, cstr, orig_cstr_len); diskp = (diskmon_t *)(uintptr_t)ptr; /* If we were called upon to update a particular disk, do it */ if (target_diskp != NULL && diskp != target_diskp) { return (0); } /* * Update the diskmon's ASRU and FRU with our information (this * information is cached in the diskmon so we don't have to do a * time-consuming topo traversal when we get an ereport). */ if (topo_prop_get_fmri(node, TOPO_PGROUP_PROTOCOL, TOPO_PROP_ASRU, &asru_fmri, &err) == 0) { diskmon_add_asru(diskp, asru_fmri); nvlist_free(asru_fmri); } if (topo_prop_get_fmri(node, TOPO_PGROUP_PROTOCOL, TOPO_PROP_FRU, &fru_fmri, &err) == 0) { diskmon_add_fru(diskp, fru_fmri); nvlist_free(fru_fmri); } if (topo_node_resource(node, &fmri, &err) == 0) { diskmon_add_disk_fmri(diskp, fmri); nvlist_free(fmri); } /* * Update the diskmon's location field with the disk's label */ if (diskp->location) dstrfree(diskp->location); if (topo_node_label(node, &label, &err) == 0) { diskp->location = dstrdup(label); topo_hdl_strfree(thp, label); } else diskp->location = dstrdup("unknown location"); /* * Check for a device path property (if the disk is configured, * it will be present) and add it to the diskmon's properties) */ if (topo_prop_get_string(node, TOPO_PGROUP_IO, TOPO_IO_DEV_PATH, &devpath, &err) == 0) { char devp[PATH_MAX]; /* * Consumers of the DISK_PROP_DEVPATH property expect a raw * minor device node */ (void) snprintf(devp, PATH_MAX, "%s:q,raw", devpath); (void) nvlist_add_string(diskp->props, DISK_PROP_DEVPATH, devp); topo_hdl_strfree(thp, devpath); } /* * Add the logical disk node, if it exists */ if (topo_prop_get_string(node, TOPO_STORAGE_PGROUP, TOPO_STORAGE_LOGICAL_DISK_NAME, &devpath, &err) == 0) { (void) nvlist_add_string(diskp->props, DISK_PROP_LOGNAME, devpath); topo_hdl_strfree(thp, devpath); } /* * Add the FRU information (if present in the node) to the diskmon's * fru data structure: */ (void) topo_prop_get_string(node, TOPO_STORAGE_PGROUP, TOPO_STORAGE_MODEL, &model, &err); (void) topo_prop_get_string(node, TOPO_STORAGE_PGROUP, TOPO_STORAGE_MANUFACTURER, &manuf, &err); (void) topo_prop_get_string(node, TOPO_STORAGE_PGROUP, TOPO_STORAGE_SERIAL_NUM, &serial, &err); (void) topo_prop_get_string(node, TOPO_STORAGE_PGROUP, TOPO_STORAGE_FIRMWARE_REV, &firmrev, &err); (void) topo_prop_get_string(node, TOPO_STORAGE_PGROUP, TOPO_STORAGE_CAPACITY, &capacity, &err); frup = new_dmfru(manuf, model, firmrev, serial, capacity == NULL ? 0 : strtoull(capacity, 0, 0)); /* * Update the disk's resource FMRI with the * SunService-required members: * FM_FMRI_HC_SERIAL_ID, FM_FMRI_HC_PART, and * FM_FMRI_HC_REVISION */ (void) nvlist_add_string(diskp->disk_res_fmri, FM_FMRI_HC_SERIAL_ID, serial); transform_model_string(manuf, model, &buf, &buflen); (void) nvlist_add_string(diskp->disk_res_fmri, FM_FMRI_HC_PART, buf); /* * Add the serial number to the ASRU so that when the resource * is marked faulty in the fmd resource cache, the hc scheme * plugin can detect when the disk is no longer installed (and so, * can clear the faulty state automatically across fmd restarts). * * The serial number is only updated when a disk comes online * because that's when the disk node exists in the topo tree. * It's ok to keep a stale value in the ASRU when the disk is removed * because it's only used as part of fault creation when the disk * is configured (online), at which point it will be updated with * the (current) serial number of the disk inserted. */ (void) nvlist_add_string(diskp->asru_fmri, FM_FMRI_HC_SERIAL_ID, serial); dfree(buf, buflen); (void) nvlist_add_string(diskp->disk_res_fmri, FM_FMRI_HC_REVISION, firmrev); if (model) { topo_hdl_strfree(thp, model); } if (manuf) { topo_hdl_strfree(thp, manuf); } if (serial) { topo_hdl_strfree(thp, serial); } if (firmrev) { topo_hdl_strfree(thp, firmrev); } if (capacity) { topo_hdl_strfree(thp, capacity); } /* Add the fru information to the diskmon: */ dm_assert(pthread_mutex_lock(&diskp->fru_mutex) == 0); dm_assert(diskp->frup == NULL); diskp->frup = frup; dm_assert(pthread_mutex_unlock(&diskp->fru_mutex) == 0); return (0); }
static int prop_getval(tnode_t *node, const char *pgname, const char *pname, void *val, topo_type_t type, uint_t *nelems, int *err) { int i, j, ret = 0; topo_hdl_t *thp = node->tn_hdl; topo_propval_t *pv; topo_node_lock(node); if ((pv = prop_get(node, pgname, pname, NULL, err)) == NULL) return (get_properror(node, err, *err)); if (pv->tp_type != type) return (get_properror(node, err, ETOPO_PROP_TYPE)); switch (type) { case TOPO_TYPE_INT32: ret = nvlist_lookup_int32(pv->tp_val, TOPO_PROP_VAL_VAL, (int32_t *)val); break; case TOPO_TYPE_UINT32: ret = nvlist_lookup_uint32(pv->tp_val, TOPO_PROP_VAL_VAL, (uint32_t *)val); break; case TOPO_TYPE_INT64: ret = nvlist_lookup_int64(pv->tp_val, TOPO_PROP_VAL_VAL, (int64_t *)val); break; case TOPO_TYPE_UINT64: ret = nvlist_lookup_uint64(pv->tp_val, TOPO_PROP_VAL_VAL, (uint64_t *)val); break; case TOPO_TYPE_DOUBLE: ret = nvlist_lookup_double(pv->tp_val, TOPO_PROP_VAL_VAL, (double *)val); break; case TOPO_TYPE_STRING: { char *str; ret = nvlist_lookup_string(pv->tp_val, TOPO_PROP_VAL_VAL, &str); if (ret == 0) { char *s2; if ((s2 = topo_hdl_strdup(thp, str)) == NULL) ret = -1; else *(char **)val = s2; } break; } case TOPO_TYPE_FMRI: { nvlist_t *nvl; ret = nvlist_lookup_nvlist(pv->tp_val, TOPO_PROP_VAL_VAL, &nvl); if (ret == 0) ret = topo_hdl_nvdup(thp, nvl, (nvlist_t **)val); break; } case TOPO_TYPE_INT32_ARRAY: { int32_t *a1, *a2; if ((ret = nvlist_lookup_int32_array(pv->tp_val, TOPO_PROP_VAL_VAL, &a2, nelems)) != 0) break; if ((a1 = topo_hdl_alloc(thp, sizeof (int32_t) * *nelems)) == NULL) { ret = ETOPO_NOMEM; break; } for (i = 0; i < *nelems; ++i) a1[i] = a2[i]; *(int32_t **)val = a1; break; } case TOPO_TYPE_UINT32_ARRAY: { uint32_t *a1, *a2; if ((ret = nvlist_lookup_uint32_array(pv->tp_val, TOPO_PROP_VAL_VAL, &a2, nelems)) != 0) break; if ((a1 = topo_hdl_alloc(thp, sizeof (uint32_t) * *nelems)) == NULL) { ret = ETOPO_NOMEM; break; } for (i = 0; i < *nelems; ++i) a1[i] = a2[i]; *(uint32_t **)val = a1; break; } case TOPO_TYPE_INT64_ARRAY: { int64_t *a1, *a2; if ((ret = nvlist_lookup_int64_array(pv->tp_val, TOPO_PROP_VAL_VAL, &a2, nelems)) != 0) break; if ((a1 = topo_hdl_alloc(thp, sizeof (int64_t) * *nelems)) == NULL) { ret = ETOPO_NOMEM; break; } for (i = 0; i < *nelems; ++i) a1[i] = a2[i]; *(int64_t **)val = a1; break; } case TOPO_TYPE_UINT64_ARRAY: { uint64_t *a1, *a2; if ((ret = nvlist_lookup_uint64_array(pv->tp_val, TOPO_PROP_VAL_VAL, &a2, nelems)) != 0) break; if ((a1 = topo_hdl_alloc(thp, sizeof (uint64_t) * *nelems)) == NULL) { ret = ETOPO_NOMEM; break; } for (i = 0; i < *nelems; ++i) a1[i] = a2[i]; *(uint64_t **)val = a1; break; } case TOPO_TYPE_STRING_ARRAY: { char **a1, **a2; if ((ret = nvlist_lookup_string_array(pv->tp_val, TOPO_PROP_VAL_VAL, &a2, nelems)) != 0) break; if ((a1 = topo_hdl_alloc(thp, sizeof (char *) * *nelems)) == NULL) { ret = ETOPO_NOMEM; break; } for (i = 0; i < *nelems; ++i) { if ((a1[i] = topo_hdl_strdup(thp, a2[i])) == NULL) { for (j = 0; j < i; ++j) topo_hdl_free(thp, a1[j], sizeof (char *)); topo_hdl_free(thp, a1, sizeof (char *) * *nelems); break; } } *(char ***)val = a1; break; } case TOPO_TYPE_FMRI_ARRAY: { nvlist_t **a1, **a2; if ((ret = nvlist_lookup_nvlist_array(pv->tp_val, TOPO_PROP_VAL_VAL, &a2, nelems)) != 0) break; if ((a1 = topo_hdl_alloc(thp, sizeof (nvlist_t *) * *nelems)) == NULL) { ret = ETOPO_NOMEM; break; } for (i = 0; i < *nelems; ++i) { if (topo_hdl_nvdup(thp, a2[i], &a1[i]) < 0) { for (j = 0; j < i; ++j) nvlist_free(a1[j]); topo_hdl_free(thp, a1, sizeof (nvlist_t *) * *nelems); break; } } *(nvlist_t ***)val = a1; break; } default: ret = ETOPO_PROP_NOENT; } if (ret != 0) if (ret == ENOENT) return (get_properror(node, err, ETOPO_PROP_NOENT)); else if (ret < ETOPO_UNKNOWN) return (get_properror(node, err, ETOPO_PROP_NVL)); else return (get_properror(node, err, ret)); topo_node_unlock(node); return (0); }
static void topo_snap_destroy(topo_hdl_t *thp) { int i; ttree_t *tp; topo_walk_t *twp; tnode_t *root; topo_nodehash_t *nhp; topo_mod_t *mod; for (tp = topo_list_next(&thp->th_trees); tp != NULL; tp = topo_list_next(tp)) { root = tp->tt_root; twp = tp->tt_walk; /* * Clean-up tree nodes from the bottom-up */ if ((twp->tw_node = topo_child_first(root)) != NULL) { twp->tw_cb = topo_walk_destroy; topo_node_hold(root); topo_node_hold(twp->tw_node); /* released at walk end */ (void) topo_walk_bottomup(twp, TOPO_WALK_CHILD); topo_node_rele(root); } /* * Tidy-up the root node */ while ((nhp = topo_list_next(&root->tn_children)) != NULL) { for (i = 0; i < nhp->th_arrlen; i++) { assert(nhp->th_nodearr[i] == NULL); } mod = nhp->th_enum; topo_mod_strfree(mod, nhp->th_name); topo_mod_free(mod, nhp->th_nodearr, nhp->th_arrlen * sizeof (tnode_t *)); topo_list_delete(&root->tn_children, nhp); topo_mod_free(mod, nhp, sizeof (topo_nodehash_t)); topo_mod_rele(mod); } } /* * Clean-up our cached devinfo and prom tree handles. */ if (thp->th_di != DI_NODE_NIL) { di_fini(thp->th_di); thp->th_di = DI_NODE_NIL; } if (thp->th_pi != DI_PROM_HANDLE_NIL) { di_prom_fini(thp->th_pi); thp->th_pi = DI_PROM_HANDLE_NIL; } if (thp->th_uuid != NULL) { topo_hdl_free(thp, thp->th_uuid, TOPO_UUID_SIZE); thp->th_uuid = NULL; } }