int topo_walk_bottomup(topo_walk_t *wp, int flag) { int status; tnode_t *cnp; if (wp == NULL) return (TOPO_WALK_ERR); cnp = wp->tw_node; if (flag != TOPO_WALK_CHILD && flag != TOPO_WALK_SIBLING) { topo_node_rele(cnp); return (TOPO_WALK_ERR); } /* * End of the line */ if (cnp == NULL) { topo_dprintf(wp->tw_thp, TOPO_DBG_WALK, "walk_bottomup terminated\n"); topo_node_rele(cnp); return (TOPO_WALK_TERMINATE); } topo_dprintf(wp->tw_thp, TOPO_DBG_WALK, "%s walk_bottomup through node %s=%d\n", (flag == TOPO_WALK_CHILD ? "TOPO_WALK_CHILD" : "TOPO_WALK_SIBLING"), cnp->tn_name, cnp->tn_instance); if (flag == TOPO_WALK_CHILD) status = step_child(cnp, wp, flag, 1); else status = step_sibling(cnp, wp, flag, 1); /* * At a leaf, run the callback */ if (status == TOPO_WALK_TERMINATE) { if ((status = wp->tw_cb(wp->tw_thp, cnp, wp->tw_pdata)) != TOPO_WALK_NEXT) { topo_node_rele(cnp); return (status); } } /* * Try next child or sibling */ if (status == TOPO_WALK_NEXT) { if (flag == TOPO_WALK_CHILD) status = step_sibling(cnp, wp, flag, 1); else status = step_child(cnp, wp, flag, 1); } topo_node_rele(cnp); /* done with current node */ return (status); }
int topo_walk_step(topo_walk_t *wp, int flag) { int status; tnode_t *cnp = wp->tw_node; if (flag != TOPO_WALK_CHILD && flag != TOPO_WALK_SIBLING) { topo_node_rele(cnp); return (TOPO_WALK_ERR); } /* * No more nodes to walk */ if (cnp == NULL) { topo_dprintf(wp->tw_thp, TOPO_DBG_WALK, "walk_step terminated\n"); topo_node_rele(cnp); return (TOPO_WALK_TERMINATE); } if (wp->tw_mod != NULL) status = wp->tw_cb(wp->tw_mod, cnp, wp->tw_pdata); else status = wp->tw_cb(wp->tw_thp, cnp, wp->tw_pdata); /* * Walker callback says we're done */ if (status != TOPO_WALK_NEXT) { topo_node_rele(cnp); return (status); } if (flag == TOPO_WALK_CHILD) status = step_child(cnp, wp, flag, 0); else status = step_sibling(cnp, wp, flag, 0); /* * No more nodes in this hash, skip to next node hash by stepping * to next sibling (child-first walk) or next child (sibling-first * walk). */ if (status == TOPO_WALK_TERMINATE) { if (flag == TOPO_WALK_CHILD) status = step_sibling(cnp, wp, flag, 0); else status = step_child(cnp, wp, flag, 0); } topo_node_rele(cnp); /* done with current node */ return (status); }
void topo_tree_destroy(ttree_t *tp) { topo_mod_t *mod; if (tp == NULL) return; mod = tp->tt_mod; if (tp->tt_walk != NULL) topo_mod_free(mod, tp->tt_walk, sizeof (topo_walk_t)); if (tp->tt_root != NULL) { assert(tp->tt_root->tn_refs == 1); topo_node_rele(tp->tt_root); } /* * Deallocate this last, because a pointer alias for tt_scheme * (stored in the root node's name field) may be used in * topo_node_rele(). */ if (tp->tt_scheme != NULL) topo_mod_strfree(mod, tp->tt_scheme); topo_mod_free(mod, tp, sizeof (ttree_t)); }
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)); }
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); }
void topo_node_unbind(tnode_t *node) { if (node == NULL) return; topo_node_lock(node); if (!(node->tn_state & TOPO_NODE_BOUND)) { topo_node_unlock(node); return; } node->tn_state &= ~TOPO_NODE_BOUND; topo_node_unlock(node); topo_node_rele(node); }
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); }
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); }
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; } }