void topo_method_unregister(topo_mod_t *mod, tnode_t *node, const char *name) { topo_imethod_t *mp; topo_node_lock(node); for (mp = topo_list_next(&node->tn_methods); mp != NULL; mp = topo_list_next(mp)) { if (strcmp(name, mp->tim_name) == 0) break; } if (mp == NULL) { topo_node_unlock(node); return; } topo_list_delete(&node->tn_methods, mp); topo_node_unlock(node); if (mp->tim_name != NULL) topo_mod_strfree(mod, mp->tim_name); if (mp->tim_desc != NULL) topo_mod_strfree(mod, mp->tim_desc); topo_mod_free(mod, mp, sizeof (topo_imethod_t)); }
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); }
int disk_declare_path(topo_mod_t *mod, tnode_t *parent, topo_list_t *listp, const char *path) { dev_di_node_t *dnode; int i; /* * Check for match using physical phci (ddn_ppath). Use * di_devfs_path_match so generic.vs.non-generic names match. */ for (dnode = topo_list_next(listp); dnode != NULL; dnode = topo_list_next(dnode)) { if (dnode->ddn_ppath == NULL) continue; for (i = 0; i < dnode->ddn_ppath_count; i++) { if (di_devfs_path_match(dnode->ddn_ppath[0], path)) return (disk_declare(mod, parent, dnode, NULL)); } } topo_mod_dprintf(mod, "disk_declare_path: " "failed to find disk matching path %s", path); return (0); }
topo_walk_t * topo_walk_init(topo_hdl_t *thp, const char *scheme, topo_walk_cb_t cb_f, void *pdata, int *errp) { ttree_t *tp; topo_walk_t *wp; for (tp = topo_list_next(&thp->th_trees); tp != NULL; tp = topo_list_next(tp)) { if (strcmp(scheme, tp->tt_scheme) == 0) { /* * Hold the root node and start walk at the first * child node */ assert(tp->tt_root != NULL); if ((wp = topo_node_walk_init(thp, NULL, tp->tt_root, cb_f, pdata, errp)) == NULL) /* errp set */ return (NULL); return (wp); } } *errp = ETOPO_WALK_NOTFOUND; return (NULL); }
tnode_t * topo_node_lookup(tnode_t *pnode, const char *name, topo_instance_t inst) { int h; tnode_t *node; topo_nodehash_t *nhp; topo_node_lock(pnode); for (nhp = topo_list_next(&pnode->tn_children); nhp != NULL; nhp = topo_list_next(nhp)) { if (strcmp(nhp->th_name, name) == 0) { if (inst > nhp->th_range.tr_max || inst < nhp->th_range.tr_min) { topo_node_unlock(pnode); return (NULL); } h = topo_node_hash(nhp, inst); node = nhp->th_nodearr[h]; topo_node_unlock(pnode); return (node); } } topo_node_unlock(pnode); return (NULL); }
/* * Try to find a disk based on the bridge-port property. This is most often used * for SATA devices which are attached to a SAS controller and are therefore * behind a SATL bridge port. SES only knows of devices based on this SAS WWN, * not based on any SATA GUIDs. */ int disk_declare_bridge(topo_mod_t *mod, tnode_t *parent, topo_list_t *listp, const char *addr, tnode_t **childp) { dev_di_node_t *dnode; int i; /* Check for match using addr. */ for (dnode = topo_list_next(listp); dnode != NULL; dnode = topo_list_next(dnode)) { if (dnode->ddn_bridge_port == NULL) continue; for (i = 0; i < dnode->ddn_ppath_count; i++) { if ((dnode->ddn_bridge_port[i] != NULL) && (strncmp(dnode->ddn_bridge_port[i], addr, strcspn(dnode->ddn_bridge_port[i], ":"))) == 0) { topo_mod_dprintf(mod, "disk_declare_bridge: " "found disk matching bridge %s", addr); return (disk_declare(mod, parent, dnode, childp)); } } } topo_mod_dprintf(mod, "disk_declare_bridge: " "failed to find disk matching bridge %s", addr); return (1); }
int topo_prop_getpgrp(tnode_t *node, const char *pgname, nvlist_t **pgrp, int *err) { int ret; topo_hdl_t *thp = node->tn_hdl; nvlist_t *nvl, *pvnvl; topo_pgroup_t *pg; topo_propval_t *pv; topo_proplist_t *pvl; if (topo_hdl_nvalloc(thp, &nvl, 0) != 0) { *err = ETOPO_NOMEM; return (-1); } 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) continue; if (nvlist_add_string(nvl, TOPO_PROP_GROUP_NAME, pg->tpg_info->tpi_name) != 0 || nvlist_add_string(nvl, TOPO_PROP_GROUP_NSTAB, topo_stability2name(pg->tpg_info->tpi_namestab)) != 0 || nvlist_add_string(nvl, TOPO_PROP_GROUP_DSTAB, topo_stability2name(pg->tpg_info->tpi_datastab)) != 0 || nvlist_add_int32(nvl, TOPO_PROP_GROUP_VERSION, pg->tpg_info->tpi_version) != 0) return (get_pgrp_seterror(node, nvl, err, ETOPO_PROP_NVL)); for (pvl = topo_list_next(&pg->tpg_pvals); pvl != NULL; pvl = topo_list_next(pvl)) { pv = pvl->tp_pval; if (prop_val_add(node, &pvnvl, pv, err) < 0) { return (get_pgrp_seterror(node, nvl, err, *err)); } if ((ret = nvlist_add_nvlist(nvl, TOPO_PROP_VAL, pvnvl)) != 0) { nvlist_free(pvnvl); return (get_pgrp_seterror(node, nvl, err, ret)); } nvlist_free(pvnvl); } topo_node_unlock(node); *pgrp = nvl; return (0); } topo_node_unlock(node); *err = ETOPO_PROP_NOENT; return (-1); }
tnode_t * topo_hdl_root(topo_hdl_t *thp, const char *scheme) { ttree_t *tp; for (tp = topo_list_next(&thp->th_trees); tp != NULL; tp = topo_list_next(tp)) { if (strcmp(scheme, tp->tt_scheme) == 0) return (tp->tt_root); } return (NULL); }
int topo_node_range_create(topo_mod_t *mod, tnode_t *pnode, const char *name, topo_instance_t min, topo_instance_t max) { topo_nodehash_t *nhp; topo_node_lock(pnode); assert((pnode->tn_state & TOPO_NODE_BOUND) || (pnode->tn_state & TOPO_NODE_ROOT)); for (nhp = topo_list_next(&pnode->tn_children); nhp != NULL; nhp = topo_list_next(nhp)) { if (strcmp(nhp->th_name, name) == 0) return (node_create_seterror(mod, pnode, NULL, ETOPO_NODE_DUP)); } if (min < 0 || max < min) return (node_create_seterror(mod, pnode, NULL, ETOPO_NODE_INVAL)); if ((nhp = topo_mod_zalloc(mod, sizeof (topo_nodehash_t))) == NULL) return (node_create_seterror(mod, pnode, nhp, ETOPO_NOMEM)); if ((nhp->th_name = topo_mod_strdup(mod, name)) == NULL) return (node_create_seterror(mod, pnode, nhp, ETOPO_NOMEM)); nhp->th_arrlen = max - min + 1; if ((nhp->th_nodearr = topo_mod_zalloc(mod, nhp->th_arrlen * sizeof (tnode_t *))) == NULL) return (node_create_seterror(mod, pnode, nhp, ETOPO_NOMEM)); nhp->th_range.tr_min = min; nhp->th_range.tr_max = max; nhp->th_enum = mod; topo_mod_hold(mod); /* * Add these nodes to parent child list */ topo_list_append(&pnode->tn_children, nhp); topo_node_unlock(pnode); topo_dprintf(TOPO_DBG_MOD, "created node range %s[%d-%d]\n", name, min, max); return (0); }
topo_imethod_t * topo_method_lookup(tnode_t *node, const char *name) { topo_imethod_t *mp; for (mp = topo_list_next(&node->tn_methods); mp != NULL; mp = topo_list_next(mp)) { if (strcmp(name, mp->tim_name) == 0) { topo_node_unlock(node); return (mp); } } return (NULL); }
static topo_pgroup_t * pgroup_get(tnode_t *node, const char *pgname) { topo_pgroup_t *pg; /* * Check for an existing pgroup */ for (pg = topo_list_next(&node->tn_pgroups); pg != NULL; pg = topo_list_next(pg)) { if (strcmp(pg->tpg_info->tpi_name, pgname) == 0) { return (pg); } } return (NULL); }
static topo_propval_t * propval_get(topo_pgroup_t *pg, const char *pname) { topo_proplist_t *pvl; if (pg == NULL) return (NULL); for (pvl = topo_list_next(&pg->tpg_pvals); pvl != NULL; pvl = topo_list_next(pvl)) { if (strcmp(pvl->tp_pval->tp_name, pname) == 0) return (pvl->tp_pval); } return (NULL); }
int topo_tree_enum_all(topo_hdl_t *thp) { int err = 0; ttree_t *tp; for (tp = topo_list_next(&thp->th_trees); tp != NULL; tp = topo_list_next(tp)) { err |= topo_tree_enum(thp, tp); } if (err != 0) return (-1); else return (0); }
int topo_pgroup_create(tnode_t *node, const topo_pgroup_info_t *pinfo, int *err) { topo_pgroup_t *pg; topo_ipgroup_info_t *pip; topo_hdl_t *thp = node->tn_hdl; *err = 0; topo_node_lock(node); /* * Check for an existing pgroup */ for (pg = topo_list_next(&node->tn_pgroups); pg != NULL; pg = topo_list_next(pg)) { if (strcmp(pg->tpg_info->tpi_name, pinfo->tpi_name) == 0) { *err = ETOPO_PROP_DEFD; topo_node_unlock(node); return (-1); } } if ((pg = topo_hdl_zalloc(thp, sizeof (topo_pgroup_t))) == NULL) { *err = ETOPO_NOMEM; topo_node_unlock(node); return (-1); } if ((pip = topo_hdl_zalloc(thp, sizeof (topo_ipgroup_info_t))) == NULL) return (pgroup_seterr(node, pg, pip, err)); if ((pip->tpi_name = topo_hdl_strdup(thp, pinfo->tpi_name)) == NULL) return (pgroup_seterr(node, pg, pip, err)); pip->tpi_namestab = pinfo->tpi_namestab; pip->tpi_datastab = pinfo->tpi_datastab; pip->tpi_version = pinfo->tpi_version; pg->tpg_info = pip; topo_list_append(&node->tn_pgroups, pg); topo_node_unlock(node); return (0); }
/* * Simple API to determine if the specified node supports a given topo method * (specified by the method name and version). Returns true if supported, false * otherwise. */ boolean_t topo_method_supported(tnode_t *node, const char *name, topo_version_t vers) { topo_imethod_t *mp; topo_node_lock(node); for (mp = topo_list_next(&node->tn_methods); mp != NULL; mp = topo_list_next(mp)) { if ((strcmp(name, mp->tim_name) == 0) && (vers == mp->tim_version)) { topo_node_unlock(node); return (B_TRUE); } } topo_node_unlock(node); return (B_FALSE); }
void dev_list_free(topo_mod_t *mod, topo_list_t *listp) { dev_di_node_t *dnode; while ((dnode = topo_list_next(listp)) != NULL) { /* order of delete/free is important */ topo_list_delete(listp, dnode); dev_di_node_free(mod, dnode); } }
void topo_node_range_destroy(tnode_t *pnode, const char *name) { int i; topo_nodehash_t *nhp; topo_mod_t *mod; topo_node_lock(pnode); for (nhp = topo_list_next(&pnode->tn_children); nhp != NULL; nhp = topo_list_next(nhp)) { if (strcmp(nhp->th_name, name) == 0) { break; } } if (nhp == NULL) { topo_node_unlock(pnode); return; } topo_list_delete(&pnode->tn_children, nhp); topo_node_unlock(pnode); /* * Should be an empty node range */ for (i = 0; i < nhp->th_arrlen; i++) { topo_node_unbind(nhp->th_nodearr[i]); } mod = nhp->th_enum; if (nhp->th_name != NULL) topo_mod_strfree(mod, nhp->th_name); if (nhp->th_nodearr != NULL) { topo_mod_free(mod, nhp->th_nodearr, nhp->th_arrlen * sizeof (tnode_t *)); } topo_mod_free(mod, nhp, sizeof (topo_nodehash_t)); topo_mod_rele(mod); }
int topo_method_call(tnode_t *node, const char *method, topo_version_t version, nvlist_t *in, nvlist_t **out, int *err) { int rc, save; topo_imethod_t *mp; for (mp = topo_list_next(&node->tn_methods); mp != NULL; mp = topo_list_next(mp)) { if (strcmp(method, mp->tim_name) != 0) continue; if (version < mp->tim_version) { *err = ETOPO_METHOD_VEROLD; return (-1); } else if (version > mp->tim_version) { *err = ETOPO_METHOD_VERNEW; return (-1); } topo_method_enter(mp); save = mp->tim_mod->tm_errno; mp->tim_mod->tm_errno = 0; if ((rc = mp->tim_func(mp->tim_mod, node, version, in, out)) < 0) { if (mp->tim_mod->tm_errno == 0) *err = ETOPO_METHOD_FAIL; else *err = mp->tim_mod->tm_errno; } mp->tim_mod->tm_errno = save; topo_method_exit(mp); return (rc); } *err = ETOPO_METHOD_NOTSUP; return (-1); }
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_close(topo_hdl_t *thp) { ttree_t *tp; topo_hdl_lock(thp); if (thp->th_platform != NULL) topo_hdl_strfree(thp, thp->th_platform); if (thp->th_isa != NULL) topo_hdl_strfree(thp, thp->th_isa); if (thp->th_machine != NULL) topo_hdl_strfree(thp, thp->th_machine); if (thp->th_product != NULL) topo_hdl_strfree(thp, thp->th_product); if (thp->th_rootdir != NULL) topo_hdl_strfree(thp, thp->th_rootdir); if (thp->th_ipmi != NULL) ipmi_close(thp->th_ipmi); if (thp->th_smbios != NULL) smbios_close(thp->th_smbios); if (thp->th_pcidb != NULL) pcidb_close(thp->th_pcidb); /* * Clean-up snapshot */ topo_snap_destroy(thp); /* * Clean-up trees */ while ((tp = topo_list_next(&thp->th_trees)) != NULL) { topo_list_delete(&thp->th_trees, tp); topo_tree_destroy(tp); } /* * Unload all plugins */ topo_modhash_unload_all(thp); if (thp->th_modhash != NULL) topo_modhash_destroy(thp); if (thp->th_alloc != NULL) topo_free(thp->th_alloc, sizeof (topo_alloc_t)); topo_hdl_unlock(thp); topo_free(thp, sizeof (topo_hdl_t)); }
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); }
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); }
void topo_method_unregister_all(topo_mod_t *mod, tnode_t *node) { topo_imethod_t *mp; topo_node_lock(node); while ((mp = topo_list_next(&node->tn_methods)) != NULL) { topo_list_delete(&node->tn_methods, mp); if (mp->tim_name != NULL) topo_mod_strfree(mod, mp->tim_name); if (mp->tim_desc != NULL) topo_mod_strfree(mod, mp->tim_desc); topo_mod_free(mod, mp, sizeof (topo_imethod_t)); } topo_node_unlock(node); }
static void topo_node_destroy(tnode_t *node) { int i; tnode_t *pnode = node->tn_parent; topo_nodehash_t *nhp; topo_mod_t *hmod, *mod = node->tn_enum; if (node == NULL) return; assert(node->tn_refs == 0); topo_dprintf(TOPO_DBG_TREE, "destroying node %s=%d\n", node->tn_name, node->tn_instance); /* * If not a root node, remove this node from the parent's node hash */ if (!(node->tn_state & TOPO_NODE_ROOT)) { topo_node_lock(pnode); nhp = node->tn_phash; for (i = 0; i < nhp->th_arrlen; i++) { if (node == nhp->th_nodearr[i]) { nhp->th_nodearr[i] = NULL; /* * Release hold on parent */ --pnode->tn_refs; if (pnode->tn_refs == 0) topo_node_destroy(pnode); } } topo_node_unlock(pnode); } topo_node_unlock(node); /* * Allow enumerator to clean-up private data and then release * ref count */ if (mod->tm_info->tmi_release != NULL) mod->tm_info->tmi_release(mod, node); topo_method_unregister_all(mod, node); /* * Destroy all node hash lists */ while ((nhp = topo_list_next(&node->tn_children)) != NULL) { for (i = 0; i < nhp->th_arrlen; i++) { assert(nhp->th_nodearr[i] == NULL); } hmod = nhp->th_enum; topo_mod_strfree(hmod, nhp->th_name); topo_mod_free(hmod, nhp->th_nodearr, nhp->th_arrlen * sizeof (tnode_t *)); topo_list_delete(&node->tn_children, nhp); topo_mod_free(hmod, nhp, sizeof (topo_nodehash_t)); topo_mod_rele(hmod); } /* * Destroy all property data structures, free the node and release * the module that created it */ topo_pgroup_destroy_all(node); topo_mod_free(mod, node, sizeof (tnode_t)); topo_mod_rele(mod); }
tnode_t * topo_node_bind(topo_mod_t *mod, tnode_t *pnode, const char *name, topo_instance_t inst, nvlist_t *fmri, void *priv) { int h, err; tnode_t *node; topo_nodehash_t *nhp; topo_node_lock(pnode); for (nhp = topo_list_next(&pnode->tn_children); nhp != NULL; nhp = topo_list_next(nhp)) { if (strcmp(nhp->th_name, name) == 0) { if (inst > nhp->th_range.tr_max || inst < nhp->th_range.tr_min) return (node_bind_seterror(mod, pnode, NULL, ETOPO_NODE_INVAL)); h = topo_node_hash(nhp, inst); if (nhp->th_nodearr[h] != NULL) return (node_bind_seterror(mod, pnode, NULL, ETOPO_NODE_BOUND)); else break; } } if (nhp == NULL) return (node_bind_seterror(mod, pnode, NULL, ETOPO_NODE_NOENT)); if ((node = topo_mod_zalloc(mod, sizeof (tnode_t))) == NULL) return (node_bind_seterror(mod, pnode, NULL, ETOPO_NOMEM)); (void) pthread_mutex_init(&node->tn_lock, NULL); node->tn_enum = mod; node->tn_hdl = mod->tm_hdl; node->tn_parent = pnode; node->tn_name = nhp->th_name; node->tn_instance = inst; node->tn_phash = nhp; node->tn_refs = 0; /* Ref count module that bound this node */ topo_mod_hold(mod); if (fmri == NULL) return (node_bind_seterror(mod, pnode, node, ETOPO_NODE_INVAL)); if (topo_pgroup_create(node, TOPO_PGROUP_PROTOCOL, TOPO_STABILITY_PRIVATE, &err) < 0) return (node_bind_seterror(mod, pnode, node, err)); if (topo_prop_set_fmri(node, TOPO_PGROUP_PROTOCOL, TOPO_PROP_RESOURCE, TOPO_PROP_SET_ONCE, fmri, &err) < 0) return (node_bind_seterror(mod, pnode, node, err)); topo_dprintf(TOPO_DBG_MOD, "node bound %s=%d\n", node->tn_name, node->tn_instance); node->tn_state |= TOPO_NODE_BOUND; node->tn_priv = priv; topo_node_hold(node); nhp->th_nodearr[h] = node; ++pnode->tn_refs; topo_node_unlock(pnode); if (topo_pgroup_create(node, TOPO_PGROUP_SYSTEM, TOPO_STABILITY_PRIVATE, &err) == 0) { (void) topo_prop_inherit(node, TOPO_PGROUP_SYSTEM, TOPO_PROP_PLATFORM, &err); (void) topo_prop_inherit(node, TOPO_PGROUP_SYSTEM, TOPO_PROP_ISA, &err); (void) topo_prop_inherit(node, TOPO_PGROUP_SYSTEM, TOPO_PROP_MACHINE, &err); } return (node); }
/*ARGSUSED*/ int topo_method_sensor_failure(topo_mod_t *mod, tnode_t *node, topo_version_t version, nvlist_t *in, nvlist_t **out) { const char *name = topo_node_name(node); topo_faclist_t faclist, *fp; int err; nvlist_t *nvl, *props, *propval, *tmp; int ret = -1; uint32_t type, state, units; nvpair_t *elem; double reading; char *propname; boolean_t has_reading; struct sensor_errinfo seinfo; if (strcmp(name, PSU) != 0 && strcmp(name, FAN) != 0) return (topo_mod_seterrno(mod, ETOPO_METHOD_NOTSUP)); if (topo_node_facility(mod->tm_hdl, node, TOPO_FAC_TYPE_SENSOR, TOPO_FAC_TYPE_ANY, &faclist, &err) != 0) return (topo_mod_seterrno(mod, ETOPO_METHOD_NOTSUP)); if (topo_mod_nvalloc(mod, &nvl, NV_UNIQUE_NAME) != 0) goto error; for (fp = topo_list_next(&faclist.tf_list); fp != NULL; fp = topo_list_next(fp)) { if (topo_prop_getpgrp(fp->tf_node, TOPO_PGROUP_FACILITY, &props, &err) != 0) { nvlist_free(nvl); goto error; } type = state = units = 0; reading = 0; has_reading = B_FALSE; elem = NULL; while ((elem = nvlist_next_nvpair(props, elem)) != NULL) { if (strcmp(nvpair_name(elem), TOPO_PROP_VAL) != 0 || nvpair_type(elem) != DATA_TYPE_NVLIST) continue; (void) nvpair_value_nvlist(elem, &propval); if (nvlist_lookup_string(propval, TOPO_PROP_VAL_NAME, &propname) != 0) continue; if (strcmp(propname, TOPO_FACILITY_TYPE) == 0) { (void) nvlist_lookup_uint32(propval, TOPO_PROP_VAL_VAL, &type); } else if (strcmp(propname, TOPO_SENSOR_STATE) == 0) { (void) nvlist_lookup_uint32(propval, TOPO_PROP_VAL_VAL, &state); } else if (strcmp(propname, TOPO_SENSOR_UNITS) == 0) { (void) nvlist_lookup_uint32(propval, TOPO_PROP_VAL_VAL, &units); } else if (strcmp(propname, TOPO_SENSOR_READING) == 0) { has_reading = B_TRUE; (void) nvlist_lookup_double(propval, TOPO_PROP_VAL_VAL, &reading); } } if (topo_sensor_failed(type, state, &seinfo)) { tmp = NULL; if (topo_mod_nvalloc(mod, &tmp, NV_UNIQUE_NAME) != 0 || nvlist_add_uint32(tmp, TOPO_FACILITY_TYPE, type) != 0 || nvlist_add_uint32(tmp, TOPO_SENSOR_STATE, state) != 0 || nvlist_add_uint32(tmp, TOPO_SENSOR_UNITS, units) != 0 || nvlist_add_boolean_value(tmp, "nonrecov", seinfo.se_nonrecov) != 0 || nvlist_add_boolean_value(tmp, "predictive", seinfo.se_predictive) != 0 || nvlist_add_uint32(tmp, "source", seinfo.se_src) != 0 || (has_reading && nvlist_add_double(tmp, TOPO_SENSOR_READING, reading) != 0) || nvlist_add_nvlist(nvl, topo_node_name(fp->tf_node), tmp) != 0) { nvlist_free(props); nvlist_free(tmp); nvlist_free(nvl); ret = topo_mod_seterrno(mod, ETOPO_METHOD_NOMEM); goto error; } nvlist_free(tmp); } nvlist_free(props); } *out = nvl; ret = 0; error: while ((fp = topo_list_next(&faclist.tf_list)) != NULL) { topo_list_delete(&faclist.tf_list, fp); topo_mod_free(mod, fp, sizeof (topo_faclist_t)); } return (ret); }
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; } }
static int dev_di_node_add(di_node_t node, char *devid, disk_cbdata_t *cbp) { topo_mod_t *mod = cbp->dcb_mod; dev_di_node_t *dnode; di_path_t pnode; char *path; int mlen; char *minorpath; char *extn = ":a"; char *s; int64_t *nblocksp; uint64_t nblocks; int *dblksizep; uint_t dblksize; char lentry[MAXPATHLEN]; int pathcount; int *inq_dtype, itype; int i; if (devid) { /* * Check for list duplicate using devid search. * Note if there is no devid, then we can end up with duplicates * in the list, but this doesn't do any harm. */ for (dnode = topo_list_next(cbp->dcb_list); dnode != NULL; dnode = topo_list_next(dnode)) { if (dnode->ddn_devid && devid_str_compare(dnode->ddn_devid, devid) == 0) { topo_mod_dprintf(mod, "dev_di_node_add: " "already there %s\n", devid); return (0); } } } if ((dnode = topo_mod_zalloc(mod, sizeof (dev_di_node_t))) == NULL) return (-1); if (devid) { /* Establish the devid. */ dnode->ddn_devid = topo_mod_strdup(mod, devid); if (dnode->ddn_devid == NULL) goto error; } /* Establish the devinfo dpath */ if ((path = di_devfs_path(node)) == NULL) { (void) topo_mod_seterrno(mod, errno); goto error; } dnode->ddn_dpath = topo_mod_strdup(mod, path); di_devfs_path_free(path); if (dnode->ddn_dpath == NULL) goto error; /* * Establish the physical ppath and target ports. If the device is * non-mpxio then dpath and ppath are the same, and the target port is a * property of the device node. * * If dpath is a client node under scsi_vhci, then iterate over all * paths and get their physical paths and target port properrties. * di_path_client_next_path call below will * return non-NULL, and ppath is set to the physical path to the first * pathinfo node. * * NOTE: It is possible to get a generic.vs.non-generic path * for di_devfs_path.vs.di_path_devfs_path like: * xml: /pci@7b,0/pci1022,7458@11/pci1000,3060@2/sd@2,0 * pnode: /pci@7b,0/pci1022,7458@11/pci1000,3060@2/disk@2,0 * To resolve this issue disk_declare_path() needs to use the * special di_devfs_path_match() interface. */ pathcount = 0; pnode = NULL; while ((pnode = di_path_client_next_path(node, pnode)) != NULL) { pathcount++; } if (pathcount == 0) { if ((dnode->ddn_ppath = topo_mod_zalloc(mod, sizeof (char *))) == NULL) goto error; dnode->ddn_ppath_count = 1; if ((dnode->ddn_ppath[0] = topo_mod_strdup(mod, dnode->ddn_dpath)) == NULL) goto error; if ((dnode->ddn_target_port = topo_mod_zalloc(mod, sizeof (char *))) == NULL) goto error; if ((dnode->ddn_attached_port = topo_mod_zalloc(mod, sizeof (char *))) == NULL) goto error; if ((dnode->ddn_bridge_port = topo_mod_zalloc(mod, sizeof (char *))) == NULL) goto error; /* There should be only one target port for a devinfo node. */ if ((di_prop_lookup_strings(DDI_DEV_T_ANY, node, SCSI_ADDR_PROP_TARGET_PORT, &s)) == 1) { if ((dnode->ddn_target_port[0] = topo_mod_strdup(mod, scsi_wwnstr_skip_ua_prefix(s))) == NULL) goto error; } if ((di_prop_lookup_strings(DDI_DEV_T_ANY, node, SCSI_ADDR_PROP_ATTACHED_PORT, &s)) == 1) { /* There should be one attached port if any. */ if ((dnode->ddn_attached_port[0] = topo_mod_strdup(mod, scsi_wwnstr_skip_ua_prefix(s))) == NULL) goto error; } if ((di_prop_lookup_strings(DDI_DEV_T_ANY, node, SCSI_ADDR_PROP_BRIDGE_PORT, &s)) == 1) { /* There should be one bridge port if any. */ if ((dnode->ddn_bridge_port[0] = topo_mod_strdup(mod, scsi_wwnstr_skip_ua_prefix(s))) == NULL) goto error; } } else { /* processing a scsi_vhci device. */ if ((dnode->ddn_ppath = topo_mod_zalloc(mod, pathcount * sizeof (char *))) == NULL) goto error; dnode->ddn_ppath_count = pathcount; if ((dnode->ddn_target_port = topo_mod_zalloc(mod, pathcount * sizeof (char *))) == NULL) goto error; if ((dnode->ddn_attached_port = topo_mod_zalloc(mod, pathcount * sizeof (char *))) == NULL) goto error; if ((dnode->ddn_bridge_port = topo_mod_zalloc(mod, pathcount * sizeof (char *))) == NULL) goto error; pnode = NULL; pathcount = 0; while ((pnode = di_path_client_next_path(node, pnode)) != NULL) { if ((path = di_path_devfs_path(pnode)) == NULL) { (void) topo_mod_seterrno(mod, errno); goto error; } dnode->ddn_ppath[pathcount] = topo_mod_strdup(mod, path); di_devfs_path_free(path); if (dnode->ddn_ppath[pathcount] == NULL) goto error; if ((di_path_prop_lookup_strings(pnode, SCSI_ADDR_PROP_TARGET_PORT, &s)) == 1) { if ((dnode->ddn_target_port[pathcount] = topo_mod_strdup(mod, scsi_wwnstr_skip_ua_prefix(s))) == NULL) goto error; } if ((di_path_prop_lookup_strings(pnode, SCSI_ADDR_PROP_ATTACHED_PORT, &s)) == 1) { if ((dnode->ddn_attached_port[pathcount] = topo_mod_strdup(mod, scsi_wwnstr_skip_ua_prefix(s))) == NULL) goto error; } if ((di_path_prop_lookup_strings(pnode, SCSI_ADDR_PROP_BRIDGE_PORT, &s)) == 1) { if ((dnode->ddn_bridge_port[pathcount] = topo_mod_strdup(mod, scsi_wwnstr_skip_ua_prefix(s))) == NULL) goto error; } pathcount++; } } /* * Find the public /dev name for a disk by adding a minor name and using * di_devlink interface for reverse translation (use devinfo path). */ if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "inquiry-device-type", &inq_dtype) > 0) { dnode->ddn_dtype = *inq_dtype; itype = (*inq_dtype) & DTYPE_MASK; if (itype == DTYPE_DIRECT) { mlen = strlen(dnode->ddn_dpath) + strlen(extn) + 1; if ((minorpath = topo_mod_alloc(mod, mlen)) == NULL) goto error; (void) snprintf(minorpath, mlen, "%s%s", dnode->ddn_dpath, extn); cbp->dcb_dnode = dnode; (void) di_devlink_walk(cbp->dcb_devhdl, "^dsk/", minorpath, DI_PRIMARY_LINK, cbp, disk_devlink_callback); topo_mod_free(mod, minorpath, mlen); if (dnode->ddn_lpath == NULL) { topo_mod_dprintf(mod, "dev_di_node_add: " "failed to determine logical path"); } } } else { dnode->ddn_dtype = DTYPE_UNKNOWN; } /* cache various bits of optional information about the device. */ if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, INQUIRY_VENDOR_ID, &s) > 0) { if ((dnode->ddn_mfg = disk_trim_whitespace(mod, s)) == NULL) goto error; } if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, INQUIRY_PRODUCT_ID, &s) > 0) { if ((dnode->ddn_model = disk_trim_whitespace(mod, s)) == NULL) goto error; } if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, INQUIRY_REVISION_ID, &s) > 0) { if ((dnode->ddn_firm = disk_trim_whitespace(mod, s)) == NULL) goto error; } if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, INQUIRY_SERIAL_NO, &s) > 0) { if ((dnode->ddn_serial = disk_trim_whitespace(mod, s)) == NULL) goto error; } if (di_prop_lookup_int64(DDI_DEV_T_ANY, node, "device-nblocks", &nblocksp) > 0) { nblocks = (uint64_t)*nblocksp; /* * To save kernel memory, the driver may not define * "device-dblksize" when its value is default DEV_BSIZE. */ if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "device-dblksize", &dblksizep) > 0) dblksize = (uint_t)*dblksizep; else dblksize = DEV_BSIZE; /* default value */ (void) snprintf(lentry, sizeof (lentry), "%" PRIu64, nblocks * dblksize); if ((dnode->ddn_cap = topo_mod_strdup(mod, lentry)) == NULL) goto error; } topo_mod_dprintf(mod, "dev_di_node_add: " "adding %s\n", devid ? dnode->ddn_devid : "NULL devid"); topo_mod_dprintf(mod, " " " %s\n", dnode->ddn_dpath); for (i = 0; i < dnode->ddn_ppath_count; i++) { topo_mod_dprintf(mod, " " " %s\n", dnode->ddn_ppath[i]); } topo_list_append(cbp->dcb_list, dnode); return (0); error: dev_di_node_free(mod, dnode); return (-1); }