Beispiel #1
0
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));
}
Beispiel #2
0
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);
}
Beispiel #3
0
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);
}
Beispiel #4
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);
}
Beispiel #5
0
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);
}
Beispiel #6
0
/*
 * 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);
}
Beispiel #7
0
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);
}
Beispiel #8
0
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);
}
Beispiel #9
0
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);
}
Beispiel #10
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);
}
Beispiel #11
0
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);
}
Beispiel #12
0
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);
}
Beispiel #13
0
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);
}
Beispiel #14
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);
}
Beispiel #15
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);
}
Beispiel #16
0
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);
	}
}
Beispiel #17
0
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);

}
Beispiel #18
0
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);
}
Beispiel #19
0
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));
}
Beispiel #20
0
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));
}
Beispiel #21
0
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);
}
Beispiel #22
0
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);
}
Beispiel #23
0
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);
}
Beispiel #24
0
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);
}
Beispiel #25
0
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);
}
Beispiel #26
0
/*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);
}
Beispiel #27
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;
	}
}
Beispiel #28
0
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);
}