示例#1
0
int
prop_method_register(tnode_t *node, const char *pgname, const char *pname,
    topo_type_t ptype, const char *mname, topo_version_t version,
    const nvlist_t *args, int *err)
{
	topo_hdl_t *thp = node->tn_hdl;
	topo_propmethod_t *pm = NULL;
	topo_propval_t *pv = NULL;

	if ((pm = topo_hdl_zalloc(thp, sizeof (topo_propmethod_t))) == NULL)
		return (register_methoderror(node, pm, err, 1,
		    ETOPO_PROP_NOMEM));

	if ((pm->tpm_name = topo_hdl_strdup(thp, mname)) == NULL)
		return (register_methoderror(node, pm, err, 1,
		    ETOPO_PROP_NOMEM));

	pm->tpm_version = version;

	if (topo_hdl_nvdup(thp, (nvlist_t *)args, &pm->tpm_args) != 0)
		return (register_methoderror(node, pm, err, 1,
		    ETOPO_PROP_NOMEM));

	/*
	 * It's possible the property may already exist.  However we still want
	 * to allow the method to be registered.  This is to handle the case
	 * where we specify a prop method in an xml map to override the value
	 * that was set by the enumerator.
	 *
	 * By default, propmethod-backed properties are not MUTABLE.  This is
	 * done to simplify the programming model for modules that implement
	 * property methods as most propmethods tend to only support get
	 * operations.  Enumerator modules can override this by calling
	 * topo_prop_setmutable().  Propmethods that are registered via XML can
	 * be set as mutable via the optional "mutable" attribute, which will
	 * result in the xml parser calling topo_prop_setflags() after
	 * registering the propmethod.
	 */
	if ((pv = propval_get(pgroup_get(node, pgname), pname)) == NULL)
		if ((pv = prop_create(node, pgname, pname, ptype,
		    TOPO_PROP_IMMUTABLE, err)) == NULL) {
			/* node unlocked */
			return (register_methoderror(node, pm, err, 0, *err));
		}

	if (pv->tp_method != NULL)
		return (register_methoderror(node, pm, err, 1,
		    ETOPO_METHOD_DEFD));

	if (pv->tp_val != NULL) {
		nvlist_free(pv->tp_val);
		pv->tp_val = NULL;
	}
	pv->tp_method = pm;

	topo_node_unlock(node);

	return (0);
}
示例#2
0
static int
prop_val_add(tnode_t *node, nvlist_t **nvl, topo_propval_t *pv, int *err)
{
	if (pv->tp_method != NULL)
		if (prop_method_get(node, pv, pv->tp_method, NULL, err) < 0)
			return (-1);

	if (pv->tp_val == NULL) {
		*err = ETOPO_PROP_NOENT;
		return (-1);
	}

	if (topo_hdl_nvdup(pv->tp_hdl, pv->tp_val, nvl) != 0) {
		*err = ETOPO_PROP_NOMEM;
		return (-1);
	}

	return (0);
}
示例#3
0
int
topo_fmri_str2nvl(topo_hdl_t *thp, const char *fmristr, nvlist_t **fmri,
    int *err)
{
	char *f, buf[PATH_MAX];
	nvlist_t *out = NULL, *in = NULL;
	tnode_t *rnode;

	(void) strlcpy(buf, fmristr, sizeof (buf));
	if ((f = strchr(buf, ':')) == NULL)
		return (set_error(thp, ETOPO_FMRI_MALFORM, err,
		    TOPO_METH_STR2NVL, in));

	*f = '\0'; /* strip trailing FMRI path */

	if ((rnode = topo_hdl_root(thp, buf)) == NULL)
		return (set_error(thp, ETOPO_METHOD_NOTSUP, err,
		    TOPO_METH_STR2NVL, in));

	if (topo_hdl_nvalloc(thp, &in, NV_UNIQUE_NAME) != 0)
		return (set_error(thp, ETOPO_FMRI_NVL, err, TOPO_METH_STR2NVL,
		    in));

	if (nvlist_add_string(in, "fmri-string", fmristr) != 0)
		return (set_error(thp, ETOPO_FMRI_NVL, err, TOPO_METH_STR2NVL,
		    in));

	if (topo_method_invoke(rnode, TOPO_METH_STR2NVL,
	    TOPO_METH_STR2NVL_VERSION, in, &out, err) != 0)
		return (set_error(thp, *err, err, TOPO_METH_STR2NVL, in));

	nvlist_free(in);

	if (out == NULL ||
	    topo_hdl_nvdup(thp, out, fmri) != 0)
		return (set_error(thp, ETOPO_FMRI_NVL, err,
		    TOPO_METH_STR2NVL, out));

	nvlist_free(out);

	return (0);
}
示例#4
0
/*
 * topo_prop_getprop() and topo_prop_getprops() are private project functions
 * for fmtopo
 */
int
topo_prop_getprop(tnode_t *node, const char *pgname, const char *pname,
    nvlist_t *args, nvlist_t **prop, int *err)
{
	topo_hdl_t *thp = node->tn_hdl;
	topo_propval_t *pv;

	topo_node_lock(node);
	if ((pv = prop_get(node, pgname, pname, args, err)) == NULL) {
		(void) get_properror(node, err, *err);
		return (-1);
	}

	if (topo_hdl_nvdup(thp, pv->tp_val, prop) != 0) {
		(void) get_properror(node, err, ETOPO_NOMEM);
		return (-1);
	}
	topo_node_unlock(node);

	return (0);
}
示例#5
0
int
topo_fmri_fru(topo_hdl_t *thp, nvlist_t *nvl, nvlist_t **fru, int *err)
{
	nvlist_t *fp, *prop = NULL;

	if (fmri_prop(thp, nvl, TOPO_PGROUP_PROTOCOL, TOPO_PROP_FRU,
	    nvl, &prop, err) < 0)
		return (set_error(thp, *err, err, "topo_fmri_fru", NULL));

	if (nvlist_lookup_nvlist(prop, TOPO_PROP_VAL_VAL, &fp) != 0)
		return (set_error(thp, ETOPO_PROP_NVL, err, "topo_fmri_fru",
		    prop));

	if (topo_hdl_nvdup(thp, fp, fru) < 0)
		return (set_error(thp, ETOPO_PROP_NOMEM, err, "topo_fmri_fru",
		    prop));

	nvlist_free(prop);

	return (0);
}
示例#6
0
/*
 * topo_prop_setprop() is a private project function for fmtopo
 */
int
topo_prop_setprop(tnode_t *node, const char *pgname, nvlist_t *prop,
    int flag, nvlist_t *pargs, int *err)
{
	int ret;
	topo_hdl_t *thp = node->tn_hdl;
	topo_propval_t *pv;
	nvlist_t *nvl, *args;
	char *name;
	topo_type_t type;

	if (nvlist_lookup_string(prop, TOPO_PROP_VAL_NAME, &name) != 0) {
		*err = ETOPO_PROP_NAME;
		return (-1);
	}
	if (nvlist_lookup_uint32(prop, TOPO_PROP_VAL_TYPE, (uint32_t *)&type)
	    != 0) {
		*err = ETOPO_PROP_TYPE;
		return (-1);
	}

	topo_node_lock(node);
	if ((pv = prop_create(node, pgname, name, type, flag, err)) == NULL)
		return (-1); /* unlocked and err set */

	/*
	 * Set by method or set to new prop value.  If we fail, leave
	 * property in list with old value.
	 */
	if (pv->tp_method != NULL) {
		topo_propmethod_t *pm = pv->tp_method;

		if (topo_hdl_nvalloc(pv->tp_hdl, &args, NV_UNIQUE_NAME) < 0) {
			topo_node_unlock(node);
			*err = ETOPO_PROP_NOMEM;
			return (-1);
		}
		ret = nvlist_add_nvlist(args, TOPO_PROP_ARGS, pm->tpm_args);
		if (pargs != NULL)
			ret |= nvlist_add_nvlist(args, TOPO_PROP_PARGS, pargs);

		if (ret != 0) {
			topo_node_unlock(node);
			nvlist_free(args);
			*err = ETOPO_PROP_NVL;
			return (-1);
		}

		/*
		 *
		 * Grab a reference to the property and then unlock the node.
		 * This will allow property methods to safely re-enter the
		 * prop_get codepath, making it possible for property methods
		 * to access other property values on the same node w\o causing
		 * a deadlock.
		 *
		 * We don't technically need this now, since this interface is
		 * currently only used by fmtopo (which is single-threaded), but
		 * we may make this interface available to other parts of
		 * libtopo in the future, so best to make it MT-safe now.
		 */
		topo_prop_hold(pv);
		topo_node_unlock(node);
		ret = topo_method_call(node, pm->tpm_name, pm->tpm_version,
		    args, &nvl, err);
		topo_node_lock(node);
		topo_prop_rele(pv);

		nvlist_free(args);
	} else {
		if ((ret = topo_hdl_nvdup(thp, prop, &nvl)) != 0)
			*err = ETOPO_PROP_NOMEM;
	}

	if (ret != 0) {
		topo_node_unlock(node);
		return (-1);
	}

	pv->tp_val = nvl;
	topo_node_unlock(node);
	return (0);
}
示例#7
0
static int
prop_getval(tnode_t *node, const char *pgname, const char *pname, void *val,
    topo_type_t type, uint_t *nelems, int *err)
{
	int i, j, ret = 0;
	topo_hdl_t *thp = node->tn_hdl;
	topo_propval_t *pv;

	topo_node_lock(node);
	if ((pv = prop_get(node, pgname, pname, NULL, err))
	    == NULL)
		return (get_properror(node, err, *err));

	if (pv->tp_type != type)
		return (get_properror(node, err, ETOPO_PROP_TYPE));

	switch (type) {
		case TOPO_TYPE_INT32:
			ret = nvlist_lookup_int32(pv->tp_val, TOPO_PROP_VAL_VAL,
			    (int32_t *)val);
			break;
		case TOPO_TYPE_UINT32:
			ret = nvlist_lookup_uint32(pv->tp_val,
			    TOPO_PROP_VAL_VAL, (uint32_t *)val);
			break;
		case TOPO_TYPE_INT64:
			ret = nvlist_lookup_int64(pv->tp_val, TOPO_PROP_VAL_VAL,
			    (int64_t *)val);
			break;
		case TOPO_TYPE_UINT64:
			ret = nvlist_lookup_uint64(pv->tp_val,
			    TOPO_PROP_VAL_VAL, (uint64_t *)val);
			break;
		case TOPO_TYPE_DOUBLE:
			ret = nvlist_lookup_double(pv->tp_val,
			    TOPO_PROP_VAL_VAL, (double *)val);
			break;
		case TOPO_TYPE_STRING: {
			char *str;

			ret = nvlist_lookup_string(pv->tp_val,
			    TOPO_PROP_VAL_VAL, &str);
			if (ret == 0) {
				char *s2;
				if ((s2 = topo_hdl_strdup(thp, str)) == NULL)
					ret = -1;
				else
					*(char **)val = s2;
			}
			break;
		}
		case TOPO_TYPE_FMRI: {
			nvlist_t *nvl;

			ret = nvlist_lookup_nvlist(pv->tp_val,
			    TOPO_PROP_VAL_VAL, &nvl);
			if (ret == 0)
				ret = topo_hdl_nvdup(thp, nvl,
				    (nvlist_t **)val);
			break;
		}
		case TOPO_TYPE_INT32_ARRAY: {
			int32_t *a1, *a2;

			if ((ret = nvlist_lookup_int32_array(pv->tp_val,
			    TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
				break;
			if ((a1 = topo_hdl_alloc(thp, sizeof (int32_t) *
			    *nelems)) == NULL) {
				ret = ETOPO_NOMEM;
				break;
			}
			for (i = 0; i < *nelems; ++i)
				a1[i] = a2[i];
			*(int32_t **)val = a1;
			break;
		}
		case TOPO_TYPE_UINT32_ARRAY: {
			uint32_t *a1, *a2;

			if ((ret = nvlist_lookup_uint32_array(pv->tp_val,
			    TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
				break;
			if ((a1 = topo_hdl_alloc(thp, sizeof (uint32_t) *
			    *nelems)) == NULL) {
				ret = ETOPO_NOMEM;
				break;
			}
			for (i = 0; i < *nelems; ++i)
				a1[i] = a2[i];
			*(uint32_t **)val = a1;
			break;
		}
		case TOPO_TYPE_INT64_ARRAY: {
			int64_t *a1, *a2;

			if ((ret = nvlist_lookup_int64_array(pv->tp_val,
			    TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
				break;
			if ((a1 = topo_hdl_alloc(thp, sizeof (int64_t) *
			    *nelems)) == NULL) {
				ret = ETOPO_NOMEM;
				break;
			}
			for (i = 0; i < *nelems; ++i)
				a1[i] = a2[i];
			*(int64_t **)val = a1;
			break;
		}
		case TOPO_TYPE_UINT64_ARRAY: {
			uint64_t *a1, *a2;

			if ((ret = nvlist_lookup_uint64_array(pv->tp_val,
			    TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
				break;
			if ((a1 = topo_hdl_alloc(thp, sizeof (uint64_t) *
			    *nelems)) == NULL) {
				ret = ETOPO_NOMEM;
				break;
			}
			for (i = 0; i < *nelems; ++i)
				a1[i] = a2[i];
			*(uint64_t **)val = a1;
			break;
		}
		case TOPO_TYPE_STRING_ARRAY: {
			char **a1, **a2;

			if ((ret = nvlist_lookup_string_array(pv->tp_val,
			    TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
				break;
			if ((a1 = topo_hdl_alloc(thp, sizeof (char *) *
			    *nelems)) == NULL) {
				ret = ETOPO_NOMEM;
				break;
			}
			for (i = 0; i < *nelems; ++i) {
				if ((a1[i] = topo_hdl_strdup(thp, a2[i]))
				    == NULL) {
					for (j = 0; j < i; ++j)
						topo_hdl_free(thp, a1[j],
						    sizeof (char *));
					topo_hdl_free(thp, a1,
					    sizeof (char *) * *nelems);
					break;
				}
			}
			*(char ***)val = a1;
			break;
		}
		case TOPO_TYPE_FMRI_ARRAY: {
			nvlist_t **a1, **a2;

			if ((ret = nvlist_lookup_nvlist_array(pv->tp_val,
			    TOPO_PROP_VAL_VAL, &a2, nelems)) != 0)
				break;
			if ((a1 = topo_hdl_alloc(thp, sizeof (nvlist_t *) *
			    *nelems)) == NULL) {
				ret = ETOPO_NOMEM;
				break;
			}
			for (i = 0; i < *nelems; ++i) {
				if (topo_hdl_nvdup(thp, a2[i], &a1[i]) < 0) {
					for (j = 0; j < i; ++j)
						nvlist_free(a1[j]);
					topo_hdl_free(thp, a1,
					    sizeof (nvlist_t *) * *nelems);
					break;
				}
			}
			*(nvlist_t ***)val = a1;
			break;
		}
		default:
			ret = ETOPO_PROP_NOENT;
	}

	if (ret != 0)
		if (ret == ENOENT)
			return (get_properror(node, err, ETOPO_PROP_NOENT));
		else if (ret < ETOPO_UNKNOWN)
			return (get_properror(node, err, ETOPO_PROP_NVL));
		else
			return (get_properror(node, err, ret));

	topo_node_unlock(node);
	return (0);
}