static int step_sibling(tnode_t *cnp, topo_walk_t *wp, int flag, int bottomup) { int status; tnode_t *nnp; nnp = topo_child_next(cnp->tn_parent, cnp); if (nnp == NULL) { topo_dprintf(wp->tw_thp, TOPO_DBG_WALK, "step_sibling: TOPO_WALK_TERMINATE for %s=%d\n", cnp->tn_name, cnp->tn_instance); return (TOPO_WALK_TERMINATE); } topo_dprintf(wp->tw_thp, TOPO_DBG_WALK, "step_sibling: through sibling node %s=%d to %s=%d\n", cnp->tn_name, cnp->tn_instance, nnp->tn_name, nnp->tn_instance); topo_node_hold(nnp); /* released on return from walk_step */ wp->tw_node = nnp; if (bottomup == 1) status = topo_walk_bottomup(wp, flag); else status = topo_walk_step(wp, flag); return (status); }
int topo_method_invoke(tnode_t *node, const char *method, topo_version_t version, nvlist_t *in, nvlist_t **out, int *err) { int rc; topo_node_hold(node); rc = topo_method_call(node, method, version, in, out, err); topo_node_rele(node); return (rc); }
int topo_walk_bysibling(topo_walk_t *wp, const char *name, topo_instance_t inst) { int status; tnode_t *cnp, *pnp; cnp = wp->tw_node; pnp = topo_node_parent(cnp); assert(pnp != NULL); topo_node_hold(pnp); wp->tw_node = pnp; status = topo_walk_byid(wp, name, inst); topo_node_rele(pnp); wp->tw_node = cnp; return (status); }
ttree_t * topo_tree_create(topo_hdl_t *thp, topo_mod_t *mod, const char *scheme) { ttree_t *tp; tnode_t *rp; if ((tp = topo_mod_zalloc(mod, sizeof (ttree_t))) == NULL) return (set_create_error(thp, NULL, ETOPO_NOMEM)); tp->tt_mod = mod; if ((tp->tt_scheme = topo_mod_strdup(mod, scheme)) == NULL) return (set_create_error(thp, tp, ETOPO_NOMEM)); /* * Initialize a private walker for internal use */ if ((tp->tt_walk = topo_mod_zalloc(mod, sizeof (topo_walk_t))) == NULL) return (set_create_error(thp, tp, ETOPO_NOMEM)); /* * Create the root of this tree: LINKED but never BOUND */ if ((rp = topo_mod_zalloc(mod, sizeof (tnode_t))) == NULL) return (set_create_error(thp, tp, 0)); /* th_errno set */ rp->tn_state = TOPO_NODE_ROOT | TOPO_NODE_INIT; rp->tn_name = tp->tt_scheme; rp->tn_instance = 0; rp->tn_enum = mod; rp->tn_hdl = thp; topo_node_hold(rp); tp->tt_walk->tw_root = rp; tp->tt_walk->tw_thp = thp; topo_mod_hold(mod); /* released when root node destroyed */ tp->tt_root = rp; return (tp); }
int topo_walk_byid(topo_walk_t *wp, const char *name, topo_instance_t inst) { int status; tnode_t *nnp, *cnp; cnp = wp->tw_node; nnp = topo_node_lookup(cnp, name, inst); if (nnp == NULL) return (TOPO_WALK_TERMINATE); topo_node_hold(nnp); wp->tw_node = nnp; if (wp->tw_mod != NULL) status = wp->tw_cb(wp->tw_mod, nnp, wp->tw_pdata); else status = wp->tw_cb(wp->tw_thp, nnp, wp->tw_pdata); topo_node_rele(nnp); wp->tw_node = cnp; return (status); }
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); }
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; } }