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); }
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); }
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); }
/* * 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); }
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); }
/* * 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); }
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); }