7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * CDDL HEADER START
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * The contents of this file are subject to the terms of the
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi * Common Development and Distribution License (the "License").
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi * You may not use this file except in compliance with the License.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * See the License for the specific language governing permissions
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * and limitations under the License.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * When distributing Covered Code, include this CDDL HEADER in each
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * If applicable, add the following below this CDDL HEADER, with the
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * fields enclosed by brackets "[]" replaced with your own identifying
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * information: Portions Copyright [yyyy] [name of copyright owner]
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * CDDL HEADER END
f6e214c7418f43af38bd8c3a557e3d0a1d311cfaGavin Maltby * Copyright (c) 2006, 2010, Oracle and/or its affiliates. All rights reserved.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Snapshot Library Interfaces
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Consumers of topology data may use the interfaces in this file to open,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * snapshot and close a topology exported by FMRI scheme (hc, mem and cpu)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * builtin plugins and their helper modules. A topology handle is obtained
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * by calling topo_open(). Upon a successful return, the caller may use this
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * handle to open a new snapshot. Each snapshot is assigned a Universally
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Unique Identifier that in a future enchancement to the libtopo API will be
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * used as the file locator in /var/fm/topo to persist new snapshots or lookup
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * a previously captured snapshot. topo_snap_hold() will capture the current
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * system topology. All consumers of the topo_hdl_t argument will be
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * blocked from accessing the topology trees until the snapshot completes.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * A snapshot may be cleared by calling topo_snap_rele(). As with
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * topo_snap_hold(), all topology accesses are blocked until the topology
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * trees have been released and deallocated.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Walker Library Interfaces
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Once a snapshot has been taken with topo_snap_hold(), topo_hdl_t holders
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * may initiate topology tree walks on a scheme-tree basis. topo_walk_init()
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * will initiate the data structures required to walk any one one of the
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * FMRI scheme trees. The walker data structure, topo_walk_t, is an opaque
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * handle passed to topo_walk_step to begin the walk. At each node in the
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * topology tree, a callback function is called with access to the node at
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * which our current walk falls. The callback function is passed in during
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * calls to topo_walk_init() and used throughout the walk_step of the
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * scheme tree. At any time, the callback may terminate the walk by returning
c40d7343efa60b18ad1ceb316eb337caeea79046cindi * TOPO_WALK_TERMINATE or TOPO_WALK_ERR. TOPO_WALK_NEXT will continue the walk.
78432d5ed5122db8b0bbfa41e00d063bf8ae7171cy * The type of walk through the tree may be sibling first or child first by
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * respectively passing in TOPO_WALK_SIBLING or TOPO_WALK_CHILD to
c40d7343efa60b18ad1ceb316eb337caeea79046cindi * the topo_walk_step() function. Topology nodes
c40d7343efa60b18ad1ceb316eb337caeea79046cindi * associated with an outstanding walk are held in place and will not be
c40d7343efa60b18ad1ceb316eb337caeea79046cindi * deallocated until the walk through that node completes.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Once the walk has terminated, the walking process should call
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * topo_walk_fini() to clean-up resources created in topo_walk_init()
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * and release nodes that may be still held.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if ((thp = topo_zalloc(sizeof (topo_hdl_t), 0)) == NULL)
c40d7343efa60b18ad1ceb316eb337caeea79046cindi if ((tap = topo_zalloc(sizeof (topo_alloc_t), 0)) == NULL)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Install default allocators
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if ((thp->th_modhash = topo_modhash_create(thp)) == NULL)
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi * Set-up system information and search paths for modules
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi * and topology map files
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi (void) sysinfo(SI_PLATFORM, platform, sizeof (platform));
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi if ((shp = smbios_open(NULL, SMB_VERSION, 0, NULL)) != NULL) {
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi thp->th_product = topo_hdl_strdup(thp, thp->th_platform);
12cc75c814f0c017004a9bbc96429911e008601bcindi if (thp->th_rootdir == NULL || thp->th_platform == NULL ||
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi "failed to load builtin modules: %s\n",
6e1fa242609208de48dfe1939b8814d4dff455a5Stephen Hanson return (set_open_errno(thp, errp, topo_hdl_errno(thp)));
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Clean-up snapshot
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Clean-up trees
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi while ((tp = topo_list_next(&thp->th_trees)) != NULL) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Unload all plugins
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindistatic char *
394b58103aee8d26f7ae174cb67b85d44e5e5597Stephen Hansontopo_snap_create(topo_hdl_t *thp, int *errp, boolean_t need_force)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if ((thp->th_uuid = topo_hdl_zalloc(thp, TOPO_UUID_SIZE)) == NULL) {
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi topo_dprintf(thp, TOPO_DBG_ERR, "unable to allocate uuid: %s\n",
c93c462eec9d46f84d567abf52eb29a27c2e134bCheng Sean Ye if ((ustr = topo_hdl_strdup(thp, thp->th_uuid)) == NULL) {
8393544efeffe8042bf5273c148010b32fa827e2Hyon Kim "taking a DINFOFORCE snapshot\n");
8393544efeffe8042bf5273c148010b32fa827e2Hyon Kim DINFOSUBTREE | DINFOMINOR | DINFOPROP | DINFOPATH);
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi topo_dprintf(thp, TOPO_DBG_ERR, "enumeration failure: %s\n",
2eeaed14a5e2ed9bd811643ad5bffc3510ca0310robj "failed to refresh IPMI sdr repository: %s\n",
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*ARGSUSED*/
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindistatic char *
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecinditopo_snap_log_create(topo_hdl_t *thp, const char *uuid, int *errp)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi return ((char *)uuid);
a38fc4ea2efaea64cc89ed7a1ac251ae94199ae9Robert Johnstonfac_walker(topo_hdl_t *thp, tnode_t *node, void *arg)
a38fc4ea2efaea64cc89ed7a1ac251ae94199ae9Robert Johnston if (topo_method_supported(node, TOPO_METH_FAC_ENUM, 0)) {
a38fc4ea2efaea64cc89ed7a1ac251ae94199ae9Robert Johnston * If the facility enumeration method fails, note the failure,
a38fc4ea2efaea64cc89ed7a1ac251ae94199ae9Robert Johnston * but continue on with the walk.
a38fc4ea2efaea64cc89ed7a1ac251ae94199ae9Robert Johnston if (topo_method_invoke(node, TOPO_METH_FAC_ENUM, 0, NULL, &out,
a38fc4ea2efaea64cc89ed7a1ac251ae94199ae9Robert Johnston "facility enumeration method failed on node %s=%d "
a38fc4ea2efaea64cc89ed7a1ac251ae94199ae9Robert Johnston topo_node_instance(node), topo_strerror(err));
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Return snapshot id
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecinditopo_snap_hold(topo_hdl_t *thp, const char *uuid, int *errp)
a38fc4ea2efaea64cc89ed7a1ac251ae94199ae9Robert Johnston * Now walk the tree and invoke any facility enumeration methods
a38fc4ea2efaea64cc89ed7a1ac251ae94199ae9Robert Johnston if ((twp = topo_walk_init(thp, FM_FMRI_SCHEME_HC,
e5dcf7beb7c949f9234713d5818b581ec3825443Robert Johnston (void) topo_walk_step(twp, TOPO_WALK_CHILD);
a38fc4ea2efaea64cc89ed7a1ac251ae94199ae9Robert Johnston return (topo_snap_log_create(thp, uuid, errp));
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi/*ARGSUSED*/
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecinditopo_walk_destroy(topo_hdl_t *thp, tnode_t *node, void *notused)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Clean-up tree nodes from the bottom-up
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if ((twp->tw_node = topo_child_first(root)) != NULL) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi topo_node_hold(twp->tw_node); /* released at walk end */
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Tidy-up the root node
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi while ((nhp = topo_list_next(&root->tn_children)) != NULL) {
c93c462eec9d46f84d567abf52eb29a27c2e134bCheng Sean Ye * Clean-up our cached devinfo and prom tree handles.
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecinditopo_walk_init(topo_hdl_t *thp, const char *scheme, topo_walk_cb_t cb_f,
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Hold the root node and start walk at the first
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * child node
78432d5ed5122db8b0bbfa41e00d063bf8ae7171cystep_child(tnode_t *cnp, topo_walk_t *wp, int flag, int bottomup)
c40d7343efa60b18ad1ceb316eb337caeea79046cindi "step_child: TOPO_WALK_TERMINATE for %s=%d\n",
c40d7343efa60b18ad1ceb316eb337caeea79046cindi "step_child: walk through node %s=%d to %s=%d\n",
c40d7343efa60b18ad1ceb316eb337caeea79046cindi cnp->tn_name, cnp->tn_instance, nnp->tn_name, nnp->tn_instance);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi topo_node_hold(nnp); /* released on return from walk_step */
78432d5ed5122db8b0bbfa41e00d063bf8ae7171cystep_sibling(tnode_t *cnp, topo_walk_t *wp, int flag, int bottomup)
c40d7343efa60b18ad1ceb316eb337caeea79046cindi "step_sibling: TOPO_WALK_TERMINATE for %s=%d\n",
c40d7343efa60b18ad1ceb316eb337caeea79046cindi "step_sibling: through sibling node %s=%d to %s=%d\n",
c40d7343efa60b18ad1ceb316eb337caeea79046cindi cnp->tn_name, cnp->tn_instance, nnp->tn_name, nnp->tn_instance);
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi topo_node_hold(nnp); /* released on return from walk_step */
c40d7343efa60b18ad1ceb316eb337caeea79046cinditopo_walk_byid(topo_walk_t *wp, const char *name, topo_instance_t inst)
78432d5ed5122db8b0bbfa41e00d063bf8ae7171cytopo_walk_bysibling(topo_walk_t *wp, const char *name, topo_instance_t inst)
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (flag != TOPO_WALK_CHILD && flag != TOPO_WALK_SIBLING) {
c40d7343efa60b18ad1ceb316eb337caeea79046cindi * No more nodes to walk
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi "walk_step terminated\n");
c40d7343efa60b18ad1ceb316eb337caeea79046cindi * Walker callback says we're done
c40d7343efa60b18ad1ceb316eb337caeea79046cindi * No more nodes in this hash, skip to next node hash by stepping
78432d5ed5122db8b0bbfa41e00d063bf8ae7171cy * to next sibling (child-first walk) or next child (sibling-first
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if (flag != TOPO_WALK_CHILD && flag != TOPO_WALK_SIBLING) {
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * End of the line
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi "walk_bottomup terminated\n");
0eb822a1c0c2bea495647510b75f77f0e57633ebcindi "%s walk_bottomup through node %s=%d\n",
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi (flag == TOPO_WALK_CHILD ? "TOPO_WALK_CHILD" : "TOPO_WALK_SIBLING"),
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * At a leaf, run the callback
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi if ((status = wp->tw_cb(wp->tw_thp, cnp, wp->tw_pdata))
7aec1d6e253b21f9e9b7ef68b4d81ab9859b51fecindi * Try next child or sibling
c93c462eec9d46f84d567abf52eb29a27c2e134bCheng Sean Ye return (thp == NULL ? DI_NODE_NIL : thp->th_di);
c93c462eec9d46f84d567abf52eb29a27c2e134bCheng Sean Ye return (thp == NULL ? DI_PROM_HANDLE_NIL : thp->th_pi);