/* * Validate that user is allowed to delegate specified permissions. * * In order to delegate "create" you must have "create" * and "allow". */ int dsl_deleg_can_allow(char *ddname, nvlist_t *nvp, cred_t *cr) { nvpair_t *whopair = NULL; int error; if ((error = dsl_deleg_access(ddname, ZFS_DELEG_PERM_ALLOW, cr)) != 0) return (error); while (whopair = nvlist_next_nvpair(nvp, whopair)) { nvlist_t *perms; nvpair_t *permpair = NULL; VERIFY(nvpair_value_nvlist(whopair, &perms) == 0); while (permpair = nvlist_next_nvpair(perms, permpair)) { const char *perm = nvpair_name(permpair); if (strcmp(perm, ZFS_DELEG_PERM_ALLOW) == 0) return (EPERM); if ((error = dsl_deleg_access(ddname, perm, cr)) != 0) return (error); } } return (0); }
static void print_fmri_pgroup(topo_hdl_t *thp, const char *pgn, nvlist_t *nvl) { char *dstab = NULL, *nstab = NULL; int32_t version = -1; nvlist_t *pnvl; nvpair_t *pnvp; (void) nvlist_lookup_string(nvl, TOPO_PROP_GROUP_NSTAB, &nstab); (void) nvlist_lookup_string(nvl, TOPO_PROP_GROUP_DSTAB, &dstab); (void) nvlist_lookup_int32(nvl, TOPO_PROP_GROUP_VERSION, &version); print_pgroup(thp, NULL, pgn, dstab, nstab, version); for (pnvp = nvlist_next_nvpair(nvl, NULL); pnvp != NULL; pnvp = nvlist_next_nvpair(nvl, pnvp)) { /* * Print property group and property name-value pair */ if (strcmp(TOPO_PROP_VAL, nvpair_name(pnvp)) == 0 && nvpair_type(pnvp) == DATA_TYPE_NVLIST) { (void) nvpair_value_nvlist(pnvp, &pnvl); print_prop_nameval(thp, NULL, pnvl); } } }
void setupInterfaces() { char *json; nvlist_t *data, *nvl; nvpair_t *pair; if ((json = mdataGet("sdc:nics")) == NULL) { dlog("WARN no NICs found in sdc:nics\n"); return; } if (nvlist_parse_json(json, strlen(json), &nvl, NVJSON_FORCE_INTEGER, NULL) != 0) { fatal(ERR_PARSE_JSON, "failed to parse nvpair json" " for sdc:nics: %s\n", strerror(errno)); } free(json); for (pair = nvlist_next_nvpair(nvl, NULL); pair != NULL; pair = nvlist_next_nvpair(nvl, pair)) { if (nvpair_type(pair) == DATA_TYPE_NVLIST) { if (nvpair_value_nvlist(pair, &data) != 0) { fatal(ERR_PARSE_JSON, "failed to parse nvpair json" " for NIC: %s\n", strerror(errno)); } setupInterface(data); } } nvlist_free(nvl); }
nvlist_t * fnvpair_value_nvlist(nvpair_t *nvp) { nvlist_t *rv; VERIFY0(nvpair_value_nvlist(nvp, &rv)); return (rv); }
static void mountNfsVolumes() { char *json; nvlist_t *data, *nvl; nvpair_t *pair; if ((json = mdataGet("docker:nfsvolumes")) == NULL) { dlog("No docker:nfsvolumes, nothing to mount\n"); return; } if (nvlist_parse_json(json, strlen(json), &nvl, NVJSON_FORCE_INTEGER, NULL) != 0) { fatal(ERR_PARSE_JSON, "failed to parse nvpair json" " for docker:nfsvolumes: %s\n", strerror(errno)); } free(json); for (pair = nvlist_next_nvpair(nvl, NULL); pair != NULL; pair = nvlist_next_nvpair(nvl, pair)) { if (nvpair_type(pair) == DATA_TYPE_NVLIST) { if (nvpair_value_nvlist(pair, &data) != 0) { fatal(ERR_PARSE_JSON, "failed to parse nvpair json" " for NFS volume: %s\n", strerror(errno)); } mountNfsVolume(data); } } nvlist_free(nvl); }
/* * This function takes the raw DSL properties, and filters out the user-defined * properties into a separate nvlist. */ static nvlist_t *process_user_props(zfs_handle_t *zhp, nvlist_t *props) { libzfs_handle_t *hdl = zhp->zfs_hdl; nvpair_t *elem; nvlist_t *propval; nvlist_t *nvl; if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0) { (void) no_memory(hdl); return (NULL); } elem = NULL; while ((elem = nvlist_next_nvpair(props, elem)) != NULL) { if (!zfs_prop_user(nvpair_name(elem))) continue; verify(nvpair_value_nvlist(elem, &propval) == 0); if (nvlist_add_nvlist(nvl, nvpair_name(elem), propval) != 0) { nvlist_free(nvl); return (NULL); } } return (nvl); }
void lzwu_print_error_log(zpool_handle_t *zhp) { nvlist_t *nverrlist = NULL; nvpair_t *elem; char *pathname; size_t len = MAXPATHLEN * 2; if (zpool_get_errlog(zhp, &nverrlist) != 0) { printf("errors: List of errors unavailable " "(insufficient privileges)\n"); return; } printf("errors: Permanent errors have been " "detected in the following files:\n\n"); pathname = malloc(len); elem = NULL; while ((elem = nvlist_next_nvpair(nverrlist, elem)) != NULL) { nvlist_t *nv; uint64_t dsobj, obj; verify(nvpair_value_nvlist(elem, &nv) == 0); verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_DATASET, &dsobj) == 0); verify(nvlist_lookup_uint64(nv, ZPOOL_ERR_OBJECT, &obj) == 0); zpool_obj_to_path(zhp, dsobj, obj, pathname, len); (void) printf("%7s %s\n", "", pathname); } free(pathname); nvlist_free(nverrlist); }
void zpool_read_cachefile(void) { int fd; struct stat stbf; void *buf = NULL; nvlist_t *nvlist, *child; nvpair_t *nvpair; uint64_t guid; int importrc = 0; printf("reading cachefile\n"); fd = open(ZPOOL_CACHE, O_RDONLY); if (fd < 0) return; if (fstat(fd, &stbf) || !stbf.st_size) goto out; buf = kmem_alloc(stbf.st_size, 0); if (!buf) goto out; if (read(fd, buf, stbf.st_size) != stbf.st_size) goto out; if (nvlist_unpack(buf, stbf.st_size, &nvlist, KM_PUSHPAGE) != 0) goto out; nvpair = NULL; while ((nvpair = nvlist_next_nvpair(nvlist, nvpair)) != NULL) { if (nvpair_type(nvpair) != DATA_TYPE_NVLIST) continue; VERIFY(nvpair_value_nvlist(nvpair, &child) == 0); printf("Cachefile has pool '%s'\n", nvpair_name(nvpair)); if (nvlist_lookup_uint64(child, ZPOOL_CONFIG_POOL_GUID, &guid) == 0) { printf("Cachefile has pool '%s' guid %llu\n", nvpair_name(nvpair), guid); importrc = zpool_import_by_guid(guid); printf("zpool import error %d\n", importrc); } } nvlist_free(nvlist); out: close(fd); if (buf) kmem_free(buf, stbf.st_size); }
static nvlist_t * find_disk_monitor_private_pgroup(tnode_t *node) { int err; nvlist_t *list_of_lists, *nvlp, *dupnvlp; nvlist_t *disk_monitor_pgrp = NULL; nvpair_t *nvp = NULL; char *pgroup_name; /* * topo_prop_get_all() returns an nvlist that contains other * nvlists (some of which are property groups). Since the private * property group we need will be among the list of property * groups returned (hopefully), we need to walk the list of nvlists * in the topo node's properties to find the property groups, then * check inside each embedded nvlist to see if it's the pgroup we're * looking for. */ if ((list_of_lists = topo_prop_getprops(node, &err)) != NULL) { /* * Go through the list of nvlists, looking for the * property group we need. */ while ((nvp = nvlist_next_nvpair(list_of_lists, nvp)) != NULL) { if (nvpair_type(nvp) != DATA_TYPE_NVLIST || strcmp(nvpair_name(nvp), TOPO_PROP_GROUP) != 0 || nvpair_value_nvlist(nvp, &nvlp) != 0) continue; dm_assert(nvlp != NULL); pgroup_name = NULL; if (nonunique_nvlist_lookup_string(nvlp, TOPO_PROP_GROUP_NAME, &pgroup_name) != 0 || strcmp(pgroup_name, DISK_MONITOR_PROPERTIES) != 0) continue; else { /* * Duplicate the nvlist so that when the * master nvlist is freed (below), we will * still refer to allocated memory. */ if (nvlist_dup(nvlp, &dupnvlp, 0) == 0) disk_monitor_pgrp = dupnvlp; else disk_monitor_pgrp = NULL; break; } } nvlist_free(list_of_lists); } return (disk_monitor_pgrp); }
static void dsl_deleg_unset_sync(void *arg, dmu_tx_t *tx) { dsl_deleg_arg_t *dda = arg; dsl_dir_t *dd; dsl_pool_t *dp = dmu_tx_pool(tx); objset_t *mos = dp->dp_meta_objset; nvpair_t *whopair = NULL; uint64_t zapobj; VERIFY0(dsl_dir_hold(dp, dda->dda_name, FTAG, &dd, NULL)); zapobj = dd->dd_phys->dd_deleg_zapobj; if (zapobj == 0) { dsl_dir_rele(dd, FTAG); return; } while ((whopair = nvlist_next_nvpair(dda->dda_nvlist, whopair))) { const char *whokey = nvpair_name(whopair); nvlist_t *perms; nvpair_t *permpair = NULL; uint64_t jumpobj; if (nvpair_value_nvlist(whopair, &perms) != 0) { if (zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj) == 0) { (void) zap_remove(mos, zapobj, whokey, tx); VERIFY(0 == zap_destroy(mos, jumpobj, tx)); } spa_history_log_internal_dd(dd, "permission who remove", tx, "%s", whokey); continue; } if (zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj) != 0) continue; while ((permpair = nvlist_next_nvpair(perms, permpair))) { const char *perm = nvpair_name(permpair); uint64_t n = 0; (void) zap_remove(mos, jumpobj, perm, tx); if (zap_count(mos, jumpobj, &n) == 0 && n == 0) { (void) zap_remove(mos, zapobj, whokey, tx); VERIFY(0 == zap_destroy(mos, jumpobj, tx)); } spa_history_log_internal_dd(dd, "permission remove", tx, "%s %s", whokey, perm); } } dsl_dir_rele(dd, FTAG); }
static PyObject * nvl2py(nvlist_t *nvl) { PyObject *pyo; nvpair_t *nvp; pyo = PyDict_New(); for (nvp = nvlist_next_nvpair(nvl, NULL); nvp; nvp = nvlist_next_nvpair(nvl, nvp)) { PyObject *pyval; char *sval; uint64_t ival; boolean_t bval; nvlist_t *nval; switch (nvpair_type(nvp)) { case DATA_TYPE_STRING: (void) nvpair_value_string(nvp, &sval); pyval = Py_BuildValue("s", sval); break; case DATA_TYPE_UINT64: (void) nvpair_value_uint64(nvp, &ival); pyval = Py_BuildValue("K", ival); break; case DATA_TYPE_NVLIST: (void) nvpair_value_nvlist(nvp, &nval); pyval = nvl2py(nval); break; case DATA_TYPE_BOOLEAN: Py_INCREF(Py_None); pyval = Py_None; break; case DATA_TYPE_BOOLEAN_VALUE: (void) nvpair_value_boolean_value(nvp, &bval); pyval = Py_BuildValue("i", bval); break; default: PyErr_SetNone(PyExc_ValueError); Py_DECREF(pyo); return (NULL); } PyDict_SetItemString(pyo, nvpair_name(nvp), pyval); Py_DECREF(pyval); } return (pyo); }
static void dsl_deleg_unset_sync(void *arg1, void *arg2, cred_t *cr, dmu_tx_t *tx) { dsl_dir_t *dd = arg1; nvlist_t *nvp = arg2; objset_t *mos = dd->dd_pool->dp_meta_objset; nvpair_t *whopair = NULL; uint64_t zapobj = dd->dd_phys->dd_deleg_zapobj; if (zapobj == 0) return; while (whopair = nvlist_next_nvpair(nvp, whopair)) { const char *whokey = nvpair_name(whopair); nvlist_t *perms; nvpair_t *permpair = NULL; uint64_t jumpobj; if (nvpair_value_nvlist(whopair, &perms) != 0) { if (zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj) == 0) { (void) zap_remove(mos, zapobj, whokey, tx); VERIFY(0 == zap_destroy(mos, jumpobj, tx)); } spa_history_internal_log(LOG_DS_PERM_WHO_REMOVE, dd->dd_pool->dp_spa, tx, cr, "%s dataset = %llu", whokey, dd->dd_phys->dd_head_dataset_obj); continue; } if (zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj) != 0) continue; while (permpair = nvlist_next_nvpair(perms, permpair)) { const char *perm = nvpair_name(permpair); uint64_t n = 0; (void) zap_remove(mos, jumpobj, perm, tx); if (zap_count(mos, jumpobj, &n) == 0 && n == 0) { (void) zap_remove(mos, zapobj, whokey, tx); VERIFY(0 == zap_destroy(mos, jumpobj, tx)); } spa_history_internal_log(LOG_DS_PERM_REMOVE, dd->dd_pool->dp_spa, tx, cr, "%s %s dataset = %llu", whokey, perm, dd->dd_phys->dd_head_dataset_obj); } } }
static int dsl_dataset_user_release_check(void *arg, dmu_tx_t *tx) { dsl_dataset_user_release_arg_t *ddura; dsl_holdfunc_t *holdfunc; dsl_pool_t *dp; nvpair_t *pair; if (!dmu_tx_is_syncing(tx)) return (0); dp = dmu_tx_pool(tx); ASSERT(RRW_WRITE_HELD(&dp->dp_config_rwlock)); ddura = arg; holdfunc = ddura->ddura_holdfunc; for (pair = nvlist_next_nvpair(ddura->ddura_holds, NULL); pair != NULL; pair = nvlist_next_nvpair(ddura->ddura_holds, pair)) { int error; dsl_dataset_t *ds; nvlist_t *holds; const char *snapname = nvpair_name(pair); error = nvpair_value_nvlist(pair, &holds); if (error != 0) error = (SET_ERROR(EINVAL)); else error = holdfunc(dp, snapname, FTAG, &ds); if (error == 0) { error = dsl_dataset_user_release_check_one(ddura, ds, holds, snapname); dsl_dataset_rele(ds, FTAG); } if (error != 0) { if (ddura->ddura_errlist != NULL) { fnvlist_add_int32(ddura->ddura_errlist, snapname, error); } /* * Non-existent snapshots are put on the errlist, * but don't cause an overall failure. */ if (error != ENOENT) return (error); } } return (0); }
static void dsl_deleg_set_sync(void *arg1, void *arg2, cred_t *cr, dmu_tx_t *tx) { dsl_dir_t *dd = arg1; nvlist_t *nvp = arg2; objset_t *mos = dd->dd_pool->dp_meta_objset; nvpair_t *whopair = NULL; uint64_t zapobj = dd->dd_phys->dd_deleg_zapobj; if (zapobj == 0) { dmu_buf_will_dirty(dd->dd_dbuf, tx); zapobj = dd->dd_phys->dd_deleg_zapobj = zap_create(mos, DMU_OT_DSL_PERMS, DMU_OT_NONE, 0, tx); } while (whopair = nvlist_next_nvpair(nvp, whopair)) { const char *whokey = nvpair_name(whopair); nvlist_t *perms; nvpair_t *permpair = NULL; uint64_t jumpobj; VERIFY(nvpair_value_nvlist(whopair, &perms) == 0); if (zap_lookup(mos, zapobj, whokey, 8, 1, &jumpobj) != 0) { jumpobj = zap_create(mos, DMU_OT_DSL_PERMS, DMU_OT_NONE, 0, tx); VERIFY(zap_update(mos, zapobj, whokey, 8, 1, &jumpobj, tx) == 0); } while (permpair = nvlist_next_nvpair(perms, permpair)) { const char *perm = nvpair_name(permpair); uint64_t n = 0; VERIFY(zap_update(mos, jumpobj, perm, 8, 1, &n, tx) == 0); spa_history_internal_log(LOG_DS_PERM_UPDATE, dd->dd_pool->dp_spa, tx, cr, "%s %s dataset = %llu", whokey, perm, dd->dd_phys->dd_head_dataset_obj); } } }
static int dsl_dataset_user_release_check(void *arg, dmu_tx_t *tx) { dsl_dataset_user_release_arg_t *ddura = arg; dsl_pool_t *dp = dmu_tx_pool(tx); nvpair_t *pair; int rv = 0; if (!dmu_tx_is_syncing(tx)) return (0); for (pair = nvlist_next_nvpair(ddura->ddura_holds, NULL); pair != NULL; pair = nvlist_next_nvpair(ddura->ddura_holds, pair)) { const char *name = nvpair_name(pair); int error; dsl_dataset_t *ds; nvlist_t *holds; error = nvpair_value_nvlist(pair, &holds); if (error != 0) return (EINVAL); error = dsl_dataset_hold(dp, name, FTAG, &ds); if (error == 0) { boolean_t deleteme; error = dsl_dataset_user_release_check_one(ds, holds, &deleteme); if (error == 0 && deleteme) { fnvlist_add_boolean(ddura->ddura_todelete, name); } dsl_dataset_rele(ds, FTAG); } if (error != 0) { if (ddura->ddura_errlist != NULL) { fnvlist_add_int32(ddura->ddura_errlist, name, error); } rv = error; } } return (rv); }
void zpool_get_load_policy(nvlist_t *nvl, zpool_load_policy_t *zlpp) { nvlist_t *policy; nvpair_t *elem; char *nm; /* Defaults */ zlpp->zlp_rewind = ZPOOL_NO_REWIND; zlpp->zlp_maxmeta = 0; zlpp->zlp_maxdata = UINT64_MAX; zlpp->zlp_txg = UINT64_MAX; if (nvl == NULL) return; elem = NULL; while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) { nm = nvpair_name(elem); if (strcmp(nm, ZPOOL_LOAD_POLICY) == 0) { if (nvpair_value_nvlist(elem, &policy) == 0) zpool_get_load_policy(policy, zlpp); return; } else if (strcmp(nm, ZPOOL_LOAD_REWIND_POLICY) == 0) { if (nvpair_value_uint32(elem, &zlpp->zlp_rewind) == 0) if (zlpp->zlp_rewind & ~ZPOOL_REWIND_POLICIES) zlpp->zlp_rewind = ZPOOL_NO_REWIND; } else if (strcmp(nm, ZPOOL_LOAD_REQUEST_TXG) == 0) { (void) nvpair_value_uint64(elem, &zlpp->zlp_txg); } else if (strcmp(nm, ZPOOL_LOAD_META_THRESH) == 0) { (void) nvpair_value_uint64(elem, &zlpp->zlp_maxmeta); } else if (strcmp(nm, ZPOOL_LOAD_DATA_THRESH) == 0) { (void) nvpair_value_uint64(elem, &zlpp->zlp_maxdata); } } if (zlpp->zlp_rewind == 0) zlpp->zlp_rewind = ZPOOL_NO_REWIND; }
/* * Called when the module is first loaded, this routine loads the configuration * file into the SPA namespace. It does not actually open or load the pools; it * only populates the namespace. */ void spa_config_load(void) { void *buf = NULL; nvlist_t *nvlist, *child; nvpair_t *nvpair; spa_t *spa; char pathname[128]; struct _buf *file; struct bootstat bst; /* * Open the configuration file. */ (void) snprintf(pathname, sizeof (pathname), "%s%s/%s", (rootdir != NULL) ? "./" : "", spa_config_dir, ZPOOL_CACHE_FILE); file = kobj_open_file(pathname); if (file == (struct _buf *)-1) return; if (kobj_fstat(file->_fd, &bst) != 0) goto out; buf = kmem_alloc(bst.st_size, KM_SLEEP); /* * Read the nvlist from the file. */ if (kobj_read_file(file, buf, bst.st_size, 0) < 0) goto out; /* * Unpack the nvlist. */ if (nvlist_unpack(buf, bst.st_size, &nvlist, KM_SLEEP) != 0) goto out; /* * Iterate over all elements in the nvlist, creating a new spa_t for * each one with the specified configuration. */ mutex_enter(&spa_namespace_lock); nvpair = NULL; while ((nvpair = nvlist_next_nvpair(nvlist, nvpair)) != NULL) { if (nvpair_type(nvpair) != DATA_TYPE_NVLIST) continue; VERIFY(nvpair_value_nvlist(nvpair, &child) == 0); if (spa_lookup(nvpair_name(nvpair)) != NULL) continue; spa = spa_add(nvpair_name(nvpair), NULL); /* * We blindly duplicate the configuration here. If it's * invalid, we will catch it when the pool is first opened. */ VERIFY(nvlist_dup(child, &spa->spa_config, 0) == 0); } mutex_exit(&spa_namespace_lock); nvlist_free(nvlist); out: if (buf != NULL) kmem_free(buf, bst.st_size); kobj_close_file(file); }
static void print_all_props(topo_hdl_t *thp, tnode_t *node, nvlist_t *p_nv, const char *group) { char *pgn = NULL, *dstab = NULL, *nstab = NULL; int32_t version; nvlist_t *pg_nv, *pv_nv; nvpair_t *nvp, *pg_nvp; int pg_done, match, all = strcmp(group, ALL) == 0; for (nvp = nvlist_next_nvpair(p_nv, NULL); nvp != NULL; nvp = nvlist_next_nvpair(p_nv, nvp)) { if (strcmp(TOPO_PROP_GROUP, nvpair_name(nvp)) != 0 || nvpair_type(nvp) != DATA_TYPE_NVLIST) continue; nstab = NULL; dstab = NULL; version = -1; pg_done = match = 0; (void) nvpair_value_nvlist(nvp, &pg_nv); for (pg_nvp = nvlist_next_nvpair(pg_nv, NULL); pg_nvp != NULL; pg_nvp = nvlist_next_nvpair(pg_nv, pg_nvp)) { /* * Print property group name and stability levels */ if (strcmp(TOPO_PROP_GROUP_NAME, nvpair_name(pg_nvp)) == 0 && nvpair_type(pg_nvp) == DATA_TYPE_STRING) { (void) nvpair_value_string(pg_nvp, &pgn); match = strcmp(group, pgn) == 0; continue; } if (strcmp(TOPO_PROP_GROUP_NSTAB, nvpair_name(pg_nvp)) == 0 && nvpair_type(pg_nvp) == DATA_TYPE_STRING) { (void) nvpair_value_string(pg_nvp, &nstab); continue; } if (strcmp(TOPO_PROP_GROUP_DSTAB, nvpair_name(pg_nvp)) == 0 && nvpair_type(pg_nvp) == DATA_TYPE_STRING) { (void) nvpair_value_string(pg_nvp, &dstab); continue; } if (strcmp(TOPO_PROP_GROUP_VERSION, nvpair_name(pg_nvp)) == 0 && nvpair_type(pg_nvp) == DATA_TYPE_INT32) { (void) nvpair_value_int32(pg_nvp, &version); continue; } if ((match || all) && !pg_done) { print_pgroup(thp, node, pgn, dstab, nstab, version); pg_done++; } /* * Print property group and property name-value pair */ if (strcmp(TOPO_PROP_VAL, nvpair_name(pg_nvp)) == 0 && nvpair_type(pg_nvp) == DATA_TYPE_NVLIST) { (void) nvpair_value_nvlist(pg_nvp, &pv_nv); if ((match || all) && pg_done) { print_prop_nameval(thp, node, pv_nv); } } } if (match && !all) return; } }
/* * nvlist_print - Prints elements in an event buffer */ static void nvlist_print_with_indent(FILE *fp, nvlist_t *nvl, int depth) { int i; char *name; uint_t nelem; nvpair_t *nvp; if (nvl == NULL) return; indent(fp, depth); (void) fprintf(fp, "nvlist version: %d\n", NVL_VERSION(nvl)); nvp = nvlist_next_nvpair(nvl, NULL); while (nvp) { data_type_t type = nvpair_type(nvp); indent(fp, depth); name = nvpair_name(nvp); (void) fprintf(fp, "\t%s =", name); nelem = 0; switch (type) { case DATA_TYPE_BOOLEAN: { (void) fprintf(fp, " 1"); break; } case DATA_TYPE_BOOLEAN_VALUE: { boolean_t val; (void) nvpair_value_boolean_value(nvp, &val); (void) fprintf(fp, " %d", val); break; } case DATA_TYPE_BYTE: { uchar_t val; (void) nvpair_value_byte(nvp, &val); (void) fprintf(fp, " 0x%2.2x", val); break; } case DATA_TYPE_INT8: { int8_t val; (void) nvpair_value_int8(nvp, &val); (void) fprintf(fp, " %d", val); break; } case DATA_TYPE_UINT8: { uint8_t val; (void) nvpair_value_uint8(nvp, &val); (void) fprintf(fp, " 0x%x", val); break; } case DATA_TYPE_INT16: { int16_t val; (void) nvpair_value_int16(nvp, &val); (void) fprintf(fp, " %d", val); break; } case DATA_TYPE_UINT16: { uint16_t val; (void) nvpair_value_uint16(nvp, &val); (void) fprintf(fp, " 0x%x", val); break; } case DATA_TYPE_INT32: { int32_t val; (void) nvpair_value_int32(nvp, &val); (void) fprintf(fp, " %d", val); break; } case DATA_TYPE_UINT32: { uint32_t val; (void) nvpair_value_uint32(nvp, &val); (void) fprintf(fp, " 0x%x", val); break; } case DATA_TYPE_INT64: { int64_t val; (void) nvpair_value_int64(nvp, &val); (void) fprintf(fp, " %lld", (longlong_t)val); break; } case DATA_TYPE_UINT64: { uint64_t val; (void) nvpair_value_uint64(nvp, &val); (void) fprintf(fp, " 0x%llx", (u_longlong_t)val); break; } case DATA_TYPE_DOUBLE: { double val; (void) nvpair_value_double(nvp, &val); (void) fprintf(fp, " 0x%llf", val); break; } case DATA_TYPE_STRING: { char *val; (void) nvpair_value_string(nvp, &val); (void) fprintf(fp, " %s", val); break; } case DATA_TYPE_BOOLEAN_ARRAY: { boolean_t *val; (void) nvpair_value_boolean_array(nvp, &val, &nelem); for (i = 0; i < nelem; i++) (void) fprintf(fp, " %d", val[i]); break; } case DATA_TYPE_BYTE_ARRAY: { uchar_t *val; (void) nvpair_value_byte_array(nvp, &val, &nelem); for (i = 0; i < nelem; i++) (void) fprintf(fp, " 0x%2.2x", val[i]); break; } case DATA_TYPE_INT8_ARRAY: { int8_t *val; (void) nvpair_value_int8_array(nvp, &val, &nelem); for (i = 0; i < nelem; i++) (void) fprintf(fp, " %d", val[i]); break; } case DATA_TYPE_UINT8_ARRAY: { uint8_t *val; (void) nvpair_value_uint8_array(nvp, &val, &nelem); for (i = 0; i < nelem; i++) (void) fprintf(fp, " 0x%x", val[i]); break; } case DATA_TYPE_INT16_ARRAY: { int16_t *val; (void) nvpair_value_int16_array(nvp, &val, &nelem); for (i = 0; i < nelem; i++) (void) fprintf(fp, " %d", val[i]); break; } case DATA_TYPE_UINT16_ARRAY: { uint16_t *val; (void) nvpair_value_uint16_array(nvp, &val, &nelem); for (i = 0; i < nelem; i++) (void) fprintf(fp, " 0x%x", val[i]); break; } case DATA_TYPE_INT32_ARRAY: { int32_t *val; (void) nvpair_value_int32_array(nvp, &val, &nelem); for (i = 0; i < nelem; i++) (void) fprintf(fp, " %d", val[i]); break; } case DATA_TYPE_UINT32_ARRAY: { uint32_t *val; (void) nvpair_value_uint32_array(nvp, &val, &nelem); for (i = 0; i < nelem; i++) (void) fprintf(fp, " 0x%x", val[i]); break; } case DATA_TYPE_INT64_ARRAY: { int64_t *val; (void) nvpair_value_int64_array(nvp, &val, &nelem); for (i = 0; i < nelem; i++) (void) fprintf(fp, " %lld", (longlong_t)val[i]); break; } case DATA_TYPE_UINT64_ARRAY: { uint64_t *val; (void) nvpair_value_uint64_array(nvp, &val, &nelem); for (i = 0; i < nelem; i++) (void) fprintf(fp, " 0x%llx", (u_longlong_t)val[i]); break; } case DATA_TYPE_STRING_ARRAY: { char **val; (void) nvpair_value_string_array(nvp, &val, &nelem); for (i = 0; i < nelem; i++) (void) fprintf(fp, " %s", val[i]); break; } case DATA_TYPE_HRTIME: { hrtime_t val; (void) nvpair_value_hrtime(nvp, &val); (void) fprintf(fp, " 0x%llx", val); break; } case DATA_TYPE_NVLIST: { nvlist_t *val; (void) nvpair_value_nvlist(nvp, &val); (void) fprintf(fp, " (embedded nvlist)\n"); nvlist_print_with_indent(fp, val, depth + 1); indent(fp, depth + 1); (void) fprintf(fp, "(end %s)\n", name); break; } case DATA_TYPE_NVLIST_ARRAY: { nvlist_t **val; (void) nvpair_value_nvlist_array(nvp, &val, &nelem); (void) fprintf(fp, " (array of embedded nvlists)\n"); for (i = 0; i < nelem; i++) { indent(fp, depth + 1); (void) fprintf(fp, "(start %s[%d])\n", name, i); nvlist_print_with_indent(fp, val[i], depth + 1); indent(fp, depth + 1); (void) fprintf(fp, "(end %s[%d])\n", name, i); } break; } default: (void) fprintf(fp, " unknown data type (%d)", type); break; } (void) fprintf(fp, "\n"); nvp = nvlist_next_nvpair(nvl, nvp); } }
static int topo_add_bay(topo_hdl_t *thp, tnode_t *node, walk_diskmon_t *wdp) { diskmon_t *target_diskp = wdp->target; nvlist_t *nvlp = find_disk_monitor_private_pgroup(node); nvlist_t *prop_nvlp; nvpair_t *nvp = NULL; char *prop_name, *prop_value; #define PNAME_MAX 128 char pname[PNAME_MAX]; char msgbuf[MAX_CONF_MSG_LEN]; char *indicator_name, *indicator_action; char *indrule_states, *indrule_actions; int err = 0, i; conf_err_t conferr; boolean_t conf_failure = B_FALSE; char *unadj_physid = NULL; char physid[MAXPATHLEN]; char *label; nvlist_t *diskprops = NULL; char *cstr = NULL; indicator_t *indp = NULL; indrule_t *indrp = NULL; void *p; diskmon_t *diskp; void *ptr; /* No private properties -- just ignore the port */ if (nvlp == NULL) return (0); /* * Look for a diskmon based on this node's FMRI string. * Once a diskmon has been created, it's not re-created. This is * essential for the times when the tree-walk is called after a * disk is inserted (or removed) -- in that case, the disk node * handler simply updates the FRU information in the diskmon. */ if ((p = fmri2ptr(thp, node, &cstr, &err)) != NULL) { diskp = (diskmon_t *)p; /* * Delete the FRU information from the diskmon. If a disk * is connected, its FRU information will be refreshed by * the disk node code. */ if (diskp->frup && (target_diskp == NULL || diskp == target_diskp)) { dm_assert(pthread_mutex_lock(&diskp->fru_mutex) == 0); dmfru_free(diskp->frup); diskp->frup = NULL; dm_assert(pthread_mutex_unlock(&diskp->fru_mutex) == 0); } wdp->pfmri = cstr; nvlist_free(nvlp); return (0); } /* * Determine the physical path to the attachment point */ if (topo_prop_get_string(node, TOPO_PGROUP_IO, TOPO_IO_AP_PATH, &unadj_physid, &err) == 0) { adjust_dynamic_ap(unadj_physid, physid); topo_hdl_strfree(thp, unadj_physid); } else { /* unadj_physid cannot have been allocated */ if (cstr) dstrfree(cstr); nvlist_free(nvlp); return (-1); } /* */ /* * Process the properties. If we encounter a property that * is not an indicator name, action, or rule, add it to the * disk's props list. */ /* Process indicators */ i = 0; indicator_name = NULL; indicator_action = NULL; do { if (indicator_name != NULL && indicator_action != NULL) { if (topoprop_indicator_add(&indp, indicator_name, indicator_action) != 0) { conf_failure = B_TRUE; } topo_hdl_strfree(thp, indicator_name); topo_hdl_strfree(thp, indicator_action); } (void) snprintf(pname, PNAME_MAX, BAY_IND_NAME "-%d", i); if (topo_prop_get_string(node, DISK_MONITOR_PROPERTIES, pname, &indicator_name, &err) != 0) break; (void) snprintf(pname, PNAME_MAX, BAY_IND_ACTION "-%d", i); if (topo_prop_get_string(node, DISK_MONITOR_PROPERTIES, pname, &indicator_action, &err) != 0) break; i++; } while (!conf_failure && indicator_name != NULL && indicator_action != NULL); if (!conf_failure && indp != NULL && (conferr = check_inds(indp)) != E_NO_ERROR) { conf_error_msg(conferr, msgbuf, MAX_CONF_MSG_LEN, NULL); log_msg(MM_CONF, "%s: Not adding disk to list\n", msgbuf); conf_failure = B_TRUE; } /* Process state rules and indicator actions */ i = 0; indrule_states = NULL; indrule_actions = NULL; do { if (indrule_states != NULL && indrule_actions != NULL) { if (topoprop_indrule_add(&indrp, indrule_states, indrule_actions) != 0) { conf_failure = B_TRUE; } topo_hdl_strfree(thp, indrule_states); topo_hdl_strfree(thp, indrule_actions); } (void) snprintf(pname, PNAME_MAX, BAY_INDRULE_STATES "-%d", i); if (topo_prop_get_string(node, DISK_MONITOR_PROPERTIES, pname, &indrule_states, &err) != 0) break; (void) snprintf(pname, PNAME_MAX, BAY_INDRULE_ACTIONS "-%d", i); if (topo_prop_get_string(node, DISK_MONITOR_PROPERTIES, pname, &indrule_actions, &err) != 0) break; i++; } while (!conf_failure && indrule_states != NULL && indrule_actions != NULL); if (!conf_failure && indrp != NULL && indp != NULL && ((conferr = check_indrules(indrp, (state_transition_t **)&ptr)) != E_NO_ERROR || (conferr = check_consistent_ind_indrules(indp, indrp, (ind_action_t **)&ptr)) != E_NO_ERROR)) { conf_error_msg(conferr, msgbuf, MAX_CONF_MSG_LEN, ptr); log_msg(MM_CONF, "%s: Not adding disk to list\n", msgbuf); conf_failure = B_TRUE; } /* * Now collect miscellaneous properties. * Each property is stored as an embedded nvlist named * TOPO_PROP_VAL. The property name is stored in the value for * key=TOPO_PROP_VAL_NAME and the property's value is * stored in the value for key=TOPO_PROP_VAL_VAL. This is all * necessary so we can subtractively decode the properties that * we do not directly handle (so that these properties are added to * the per-disk properties nvlist), increasing flexibility. */ (void) nvlist_alloc(&diskprops, NV_UNIQUE_NAME, 0); while ((nvp = nvlist_next_nvpair(nvlp, nvp)) != NULL) { /* Only care about embedded nvlists named TOPO_PROP_VAL */ if (nvpair_type(nvp) != DATA_TYPE_NVLIST || strcmp(nvpair_name(nvp), TOPO_PROP_VAL) != 0 || nvpair_value_nvlist(nvp, &prop_nvlp) != 0) continue; if (nonunique_nvlist_lookup_string(prop_nvlp, TOPO_PROP_VAL_NAME, &prop_name) != 0) continue; /* Filter out indicator properties */ if (strstr(prop_name, BAY_IND_NAME) != NULL || strstr(prop_name, BAY_IND_ACTION) != NULL || strstr(prop_name, BAY_INDRULE_STATES) != NULL || strstr(prop_name, BAY_INDRULE_ACTIONS) != NULL) continue; if (nonunique_nvlist_lookup_string(prop_nvlp, TOPO_PROP_VAL_VAL, &prop_value) != 0) continue; /* Add the property to the disk's prop list: */ if (nvlist_add_string(diskprops, prop_name, prop_value) != 0) log_msg(MM_TOPO, "Could not add disk property `%s' with " "value `%s'\n", prop_name, prop_value); } nvlist_free(nvlp); if (cstr != NULL) { namevalpr_t nvpr; nvlist_t *dmap_nvl; nvpr.name = DISK_AP_PROP_APID; nvpr.value = strncmp(physid, "/devices", 8) == 0 ? (physid + 8) : physid; /* * Set the diskmon's location to the value in this port's label. * If there's a disk plugged in, the location will be updated * to be the disk label (e.g. HD_ID_00). Until a disk is * inserted, though, there won't be a disk libtopo node * created. */ /* Pass physid without the leading "/devices": */ dmap_nvl = namevalpr_to_nvlist(&nvpr); diskp = new_diskmon(dmap_nvl, indp, indrp, diskprops); if (topo_node_label(node, &label, &err) == 0) { diskp->location = dstrdup(label); topo_hdl_strfree(thp, label); } else diskp->location = dstrdup("unknown location"); if (!conf_failure && diskp != NULL) { /* Add this diskmon to the disk list */ cfgdata_add_diskmon(config_data, diskp); if (nvlist_add_uint64(g_topo2diskmon, cstr, (uint64_t)(uintptr_t)diskp) != 0) { log_msg(MM_TOPO, "Could not add pointer to nvlist " "for `%s'!\n", cstr); } } else if (diskp != NULL) { diskmon_free(diskp); } else { if (dmap_nvl) nvlist_free(dmap_nvl); if (indp) ind_free(indp); if (indrp) indrule_free(indrp); if (diskprops) nvlist_free(diskprops); } wdp->pfmri = cstr; } return (0); }
/* * Called when the module is first loaded, this routine loads the configuration * file into the SPA namespace. It does not actually open or load the pools; it * only populates the namespace. */ void spa_config_load(void) { void *buf = NULL; nvlist_t *nvlist, *child; nvpair_t *nvpair; char *pathname; struct _buf *file; uint64_t fsize; /* * Open the configuration file. */ pathname = kmem_alloc(MAXPATHLEN, KM_SLEEP); (void) snprintf(pathname, MAXPATHLEN, "%s", spa_config_path); file = kobj_open_file(pathname); kmem_free(pathname, MAXPATHLEN); if (file == (struct _buf *)-1) return; if (kobj_get_filesize(file, &fsize) != 0) goto out; buf = kmem_alloc(fsize, KM_SLEEP); /* * Read the nvlist from the file. */ if (kobj_read_file(file, buf, fsize, 0) < 0) goto out; /* * Unpack the nvlist. */ if (nvlist_unpack(buf, fsize, &nvlist, KM_SLEEP) != 0) goto out; /* * Iterate over all elements in the nvlist, creating a new spa_t for * each one with the specified configuration. */ mutex_enter(&spa_namespace_lock); nvpair = NULL; while ((nvpair = nvlist_next_nvpair(nvlist, nvpair)) != NULL) { if (nvpair_type(nvpair) != DATA_TYPE_NVLIST) continue; VERIFY(nvpair_value_nvlist(nvpair, &child) == 0); if (spa_lookup(nvpair_name(nvpair)) != NULL) continue; (void) spa_add(nvpair_name(nvpair), child, NULL); } mutex_exit(&spa_namespace_lock); nvlist_free(nvlist); out: if (buf != NULL) kmem_free(buf, fsize); kobj_close_file(file); }
/* * Copy in a packed nvlist from the user and create a request set out of it. * If successful, return 0 and store a pointer to the set we've created. Returns * error code on error. */ int kcpc_copyin_set(kcpc_set_t **inset, void *ubuf, size_t len) { kcpc_set_t *set; int i; int j; char *packbuf; nvlist_t *nvl; nvpair_t *nvp = NULL; nvlist_t *attrs; nvpair_t *nvp_attr; kcpc_attr_t *attrp; nvlist_t **reqlist; uint_t nreqs; uint64_t uint64; uint32_t uint32; uint32_t setflags = (uint32_t)-1; char *string; char *name; if (len < CPC_MIN_PACKSIZE || len > CPC_MAX_PACKSIZE) return (EINVAL); packbuf = kmem_alloc(len, KM_SLEEP); if (copyin(ubuf, packbuf, len) == -1) { kmem_free(packbuf, len); return (EFAULT); } if (nvlist_unpack(packbuf, len, &nvl, KM_SLEEP) != 0) { kmem_free(packbuf, len); return (EINVAL); } /* * The nvlist has been unpacked so there is no need for the packed * representation from this point on. */ kmem_free(packbuf, len); i = 0; while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) { switch (nvpair_type(nvp)) { case DATA_TYPE_UINT32: if (strcmp(nvpair_name(nvp), "flags") != 0 || nvpair_value_uint32(nvp, &setflags) != 0) { nvlist_free(nvl); return (EINVAL); } break; case DATA_TYPE_NVLIST_ARRAY: if (strcmp(nvpair_name(nvp), "reqs") != 0 || nvpair_value_nvlist_array(nvp, &reqlist, &nreqs) != 0) { nvlist_free(nvl); return (EINVAL); } break; default: nvlist_free(nvl); return (EINVAL); } i++; } /* * There should be two members in the top-level nvlist: * an array of nvlists consisting of the requests, and flags. * Anything else is an invalid set. */ if (i != 2) { nvlist_free(nvl); return (EINVAL); } if (nreqs > CPC_MAX_NREQS) { nvlist_free(nvl); return (EINVAL); } /* * The requests are now stored in the nvlist array at reqlist. * Note that the use of kmem_zalloc() to alloc the kcpc_set_t means * we don't need to call the init routines for ks_lock and ks_condv. */ set = kmem_zalloc(sizeof (kcpc_set_t), KM_SLEEP); set->ks_req = (kcpc_request_t *)kmem_zalloc(sizeof (kcpc_request_t) * nreqs, KM_SLEEP); set->ks_nreqs = nreqs; /* * If the nvlist didn't contain a flags member, setflags was initialized * with an illegal value and this set will fail sanity checks later on. */ set->ks_flags = setflags; /* * Initialize bind/unbind set synchronization. */ set->ks_state &= ~KCPC_SET_BOUND; /* * Build the set up one request at a time, always keeping it self- * consistent so we can give it to kcpc_free_set() if we need to back * out and return and error. */ for (i = 0; i < nreqs; i++) { nvp = NULL; set->ks_req[i].kr_picnum = -1; while ((nvp = nvlist_next_nvpair(reqlist[i], nvp)) != NULL) { name = nvpair_name(nvp); switch (nvpair_type(nvp)) { case DATA_TYPE_UINT32: if (nvpair_value_uint32(nvp, &uint32) == EINVAL) goto inval; if (strcmp(name, "cr_flags") == 0) set->ks_req[i].kr_flags = uint32; if (strcmp(name, "cr_index") == 0) set->ks_req[i].kr_index = uint32; break; case DATA_TYPE_UINT64: if (nvpair_value_uint64(nvp, &uint64) == EINVAL) goto inval; if (strcmp(name, "cr_preset") == 0) set->ks_req[i].kr_preset = uint64; break; case DATA_TYPE_STRING: if (nvpair_value_string(nvp, &string) == EINVAL) goto inval; if (strcmp(name, "cr_event") == 0) (void) strncpy(set->ks_req[i].kr_event, string, CPC_MAX_EVENT_LEN); break; case DATA_TYPE_NVLIST: if (strcmp(name, "cr_attr") != 0) goto inval; if (nvpair_value_nvlist(nvp, &attrs) == EINVAL) goto inval; nvp_attr = NULL; /* * If the picnum has been specified as an * attribute, consume that attribute here and * remove it from the list of attributes. */ if (nvlist_lookup_uint64(attrs, "picnum", &uint64) == 0) { if (nvlist_remove(attrs, "picnum", DATA_TYPE_UINT64) != 0) panic("nvlist %p faulty", (void *)attrs); set->ks_req[i].kr_picnum = uint64; } if ((set->ks_req[i].kr_nattrs = kcpc_nvlist_npairs(attrs)) == 0) break; if (set->ks_req[i].kr_nattrs > CPC_MAX_ATTRS) goto inval; set->ks_req[i].kr_attr = kmem_alloc(set->ks_req[i].kr_nattrs * sizeof (kcpc_attr_t), KM_SLEEP); j = 0; while ((nvp_attr = nvlist_next_nvpair(attrs, nvp_attr)) != NULL) { attrp = &set->ks_req[i].kr_attr[j]; if (nvpair_type(nvp_attr) != DATA_TYPE_UINT64) goto inval; (void) strncpy(attrp->ka_name, nvpair_name(nvp_attr), CPC_MAX_ATTR_LEN); if (nvpair_value_uint64(nvp_attr, &(attrp->ka_val)) == EINVAL) goto inval; j++; } ASSERT(j == set->ks_req[i].kr_nattrs); default: break; } } } nvlist_free(nvl); *inset = set; return (0); inval: nvlist_free(nvl); kcpc_free_set(set); return (EINVAL); }
void amd_mc_create(topo_mod_t *mod, uint16_t smbid, tnode_t *pnode, const char *name, nvlist_t *auth, int32_t procnodeid, int32_t procnodes_per_pkg, int family, int model, int *nerrp) { tnode_t *mcnode; nvlist_t *rfmri, *fmri; nvpair_t *nvp; nvlist_t *mc = NULL; int i, err; int mcnum = procnodeid % procnodes_per_pkg; char *serial = NULL; char *part = NULL; char *rev = NULL; /* * Return with no error for anything before AMD family 0xf - we * won't generate even a generic memory topology for earlier * families. */ if (family < 0xf) return; if (topo_node_lookup(pnode, name, mcnum) != NULL) return; if (FM_AWARE_SMBIOS(mod)) { (void) topo_node_resource(pnode, &rfmri, &err); (void) nvlist_lookup_string(rfmri, "serial", &serial); (void) nvlist_lookup_string(rfmri, "part", &part); (void) nvlist_lookup_string(rfmri, "revision", &rev); } if (mkrsrc(mod, pnode, name, mcnum, auth, &fmri) != 0) { if (FM_AWARE_SMBIOS(mod)) nvlist_free(rfmri); whinge(mod, nerrp, "mc_create: mkrsrc failed\n"); return; } if (FM_AWARE_SMBIOS(mod)) { (void) nvlist_add_string(fmri, "serial", serial); (void) nvlist_add_string(fmri, "part", part); (void) nvlist_add_string(fmri, "revision", rev); nvlist_free(rfmri); } if ((mcnode = topo_node_bind(mod, pnode, name, mcnum, fmri)) == NULL) { nvlist_free(fmri); whinge(mod, nerrp, "mc_create: mc bind failed\n"); return; } if (topo_node_fru_set(mcnode, NULL, 0, &err) < 0) whinge(mod, nerrp, "mc_create: topo_node_fru_set failed\n"); if (FM_AWARE_SMBIOS(mod)) { if (topo_node_label_set(mcnode, NULL, &err) == -1) topo_mod_dprintf(mod, "Failed to set label\n"); } nvlist_free(fmri); if (topo_pgroup_create(mcnode, &mc_pgroup, &err) < 0) whinge(mod, nerrp, "mc_create: topo_pgroup_create failed\n"); if (topo_prop_set_int32(mcnode, PGNAME(MCT), MCT_PROCNODE_ID, TOPO_PROP_IMMUTABLE, procnodeid, nerrp) != 0) whinge(mod, nerrp, "mc_create: topo_prop_set_int32 failed to" "add node id\n"); if ((mc = amd_lookup_by_mcid(mod, topo_node_instance(pnode))) == NULL) { /* * If a memory-controller driver exists for this chip model * it has not attached or has otherwise malfunctioned; * alternatively no memory-controller driver exists for this * (presumably newly-released) cpu model. We fallback to * creating a generic maximal topology. */ if (amd_generic_mc_create(mod, smbid, pnode, mcnode, family, model, auth) != 0) whinge(mod, nerrp, "mc_create: amd_generic_mc_create failed\n"); return; } /* * Add memory controller properties */ for (nvp = nvlist_next_nvpair(mc, NULL); nvp != NULL; nvp = nvlist_next_nvpair(mc, nvp)) { char *name = nvpair_name(nvp); data_type_t type = nvpair_type(nvp); if (type == DATA_TYPE_NVLIST_ARRAY && (strcmp(name, "cslist") == 0 || strcmp(name, "dimmlist") == 0)) { continue; } else if (type == DATA_TYPE_UINT8 && strcmp(name, MC_NVLIST_VERSTR) == 0) { continue; } else if (type == DATA_TYPE_NVLIST && strcmp(name, "htconfig") == 0) { nvlist_t *htnvl; (void) nvpair_value_nvlist(nvp, &htnvl); if (amd_htconfig(mod, pnode, htnvl) != 0) whinge(mod, nerrp, "mc_create: amd_htconfig failed\n"); } else { if (nvprop_add(mod, nvp, PGNAME(MCT), mcnode) != 0) whinge(mod, nerrp, "mc_create: nvprop_add failed\n"); } } if (amd_dramchan_create(mod, mcnode, CHAN_NODE_NAME, auth) != 0 || amd_cs_create(mod, mcnode, CS_NODE_NAME, mc, auth) != 0 || amd_dimm_create(mod, smbid, mcnode, DIMM_NODE_NAME, mc, auth) != 0) whinge(mod, nerrp, "mc_create: create children failed\n"); /* * Free the fmris for the chip-selects allocated in amd_cs_create */ for (i = 0; i < MC_CHIP_NCS; i++) { if (cs_fmri[i] != NULL) { nvlist_free(cs_fmri[i]); cs_fmri[i] = NULL; } } nvlist_free(mc); }
/*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); }
/* ARGSUSED */ static int xattr_file_write(vnode_t *vp, uio_t *uiop, int ioflag, cred_t *cr, caller_context_t *ct) { int error = 0; char *buf; char *domain; uint32_t rid; ssize_t size = uiop->uio_resid; nvlist_t *nvp; nvpair_t *pair = NULL; vnode_t *ppvp; xvattr_t xvattr; xoptattr_t *xoap = NULL; /* Pointer to optional attributes */ if (vfs_has_feature(vp->v_vfsp, VFSFT_XVATTR) == 0) return (EINVAL); /* * Validate file offset and size. */ if (uiop->uio_loffset < (offset_t)0) return (EINVAL); if (size == 0) return (EINVAL); xva_init(&xvattr); if ((xoap = xva_getxoptattr(&xvattr)) == NULL) { return (EINVAL); } /* * Copy and unpack the nvlist */ buf = kmem_alloc(size, KM_SLEEP); if (uiomove((caddr_t)buf, size, UIO_WRITE, uiop)) { return (EFAULT); } if (nvlist_unpack(buf, size, &nvp, KM_SLEEP) != 0) { kmem_free(buf, size); uiop->uio_resid = size; return (EINVAL); } kmem_free(buf, size); /* * Fasttrack empty writes (nvlist with no nvpairs) */ if (nvlist_next_nvpair(nvp, NULL) == 0) return (0); ppvp = gfs_file_parent(gfs_file_parent(vp)); while (pair = nvlist_next_nvpair(nvp, pair)) { data_type_t type; f_attr_t attr; boolean_t value; uint64_t *time, *times; uint_t elem, nelems; nvlist_t *nvp_sid; uint8_t *scanstamp; /* * Validate the name and type of each attribute. * Log any unknown names and continue. This will * help if additional attributes are added later. */ type = nvpair_type(pair); if ((attr = name_to_attr(nvpair_name(pair))) == F_ATTR_INVAL) { cmn_err(CE_WARN, "Unknown attribute %s", nvpair_name(pair)); continue; } /* * Verify nvlist type matches required type and view is OK */ if (type != attr_to_data_type(attr) || (attr_to_xattr_view(attr) == XATTR_VIEW_READONLY)) { nvlist_free(nvp); return (EINVAL); } /* * For OWNERSID/GROUPSID make sure the target * file system support ephemeral ID's */ if ((attr == F_OWNERSID || attr == F_GROUPSID) && (!(vp->v_vfsp->vfs_flag & VFS_XID))) { nvlist_free(nvp); return (EINVAL); } /* * Retrieve data from nvpair */ switch (type) { case DATA_TYPE_BOOLEAN_VALUE: if (nvpair_value_boolean_value(pair, &value)) { nvlist_free(nvp); return (EINVAL); } break; case DATA_TYPE_UINT64_ARRAY: if (nvpair_value_uint64_array(pair, ×, &nelems)) { nvlist_free(nvp); return (EINVAL); } break; case DATA_TYPE_NVLIST: if (nvpair_value_nvlist(pair, &nvp_sid)) { nvlist_free(nvp); return (EINVAL); } break; case DATA_TYPE_UINT8_ARRAY: if (nvpair_value_uint8_array(pair, &scanstamp, &nelems)) { nvlist_free(nvp); return (EINVAL); } break; default: nvlist_free(nvp); return (EINVAL); } switch (attr) { /* * If we have several similar optional attributes to * process then we should do it all together here so that * xoap and the requested bitmap can be set in one place. */ case F_READONLY: XVA_SET_REQ(&xvattr, XAT_READONLY); xoap->xoa_readonly = value; break; case F_HIDDEN: XVA_SET_REQ(&xvattr, XAT_HIDDEN); xoap->xoa_hidden = value; break; case F_SYSTEM: XVA_SET_REQ(&xvattr, XAT_SYSTEM); xoap->xoa_system = value; break; case F_ARCHIVE: XVA_SET_REQ(&xvattr, XAT_ARCHIVE); xoap->xoa_archive = value; break; case F_IMMUTABLE: XVA_SET_REQ(&xvattr, XAT_IMMUTABLE); xoap->xoa_immutable = value; break; case F_NOUNLINK: XVA_SET_REQ(&xvattr, XAT_NOUNLINK); xoap->xoa_nounlink = value; break; case F_APPENDONLY: XVA_SET_REQ(&xvattr, XAT_APPENDONLY); xoap->xoa_appendonly = value; break; case F_NODUMP: XVA_SET_REQ(&xvattr, XAT_NODUMP); xoap->xoa_nodump = value; break; case F_AV_QUARANTINED: XVA_SET_REQ(&xvattr, XAT_AV_QUARANTINED); xoap->xoa_av_quarantined = value; break; case F_AV_MODIFIED: XVA_SET_REQ(&xvattr, XAT_AV_MODIFIED); xoap->xoa_av_modified = value; break; case F_CRTIME: XVA_SET_REQ(&xvattr, XAT_CREATETIME); time = (uint64_t *)&(xoap->xoa_createtime); for (elem = 0; elem < nelems; elem++) *time++ = times[elem]; break; case F_OWNERSID: case F_GROUPSID: if (nvlist_lookup_string(nvp_sid, SID_DOMAIN, &domain) || nvlist_lookup_uint32(nvp_sid, SID_RID, &rid)) { nvlist_free(nvp); return (EINVAL); } /* * Now map domain+rid to ephemeral id's * * If mapping fails, then the uid/gid will * be set to UID_NOBODY by Winchester. */ if (attr == F_OWNERSID) { (void) kidmap_getuidbysid(crgetzone(cr), domain, rid, &xvattr.xva_vattr.va_uid); xvattr.xva_vattr.va_mask |= AT_UID; } else { (void) kidmap_getgidbysid(crgetzone(cr), domain, rid, &xvattr.xva_vattr.va_gid); xvattr.xva_vattr.va_mask |= AT_GID; } break; case F_AV_SCANSTAMP: if (ppvp->v_type == VREG) { XVA_SET_REQ(&xvattr, XAT_AV_SCANSTAMP); (void) memcpy(xoap->xoa_av_scanstamp, scanstamp, nelems); } else { nvlist_free(nvp); return (EINVAL); } break; case F_REPARSE: XVA_SET_REQ(&xvattr, XAT_REPARSE); xoap->xoa_reparse = value; break; case F_OFFLINE: XVA_SET_REQ(&xvattr, XAT_OFFLINE); xoap->xoa_offline = value; break; case F_SPARSE: XVA_SET_REQ(&xvattr, XAT_SPARSE); xoap->xoa_sparse = value; break; default: break; } } ppvp = gfs_file_parent(gfs_file_parent(vp)); error = VOP_SETATTR(ppvp, &xvattr.xva_vattr, 0, cr, ct); if (error) uiop->uio_resid = size; nvlist_free(nvp); return (error); }
/* * Given a cache file, return the contents as a list of importable pools. * poolname or guid (but not both) are provided by the caller when trying * to import a specific pool. */ nvlist_t * zpool_find_import_cached(libzfs_handle_t *hdl, const char *cachefile, char *poolname, uint64_t guid) { char *buf; int fd; struct stat64 statbuf; nvlist_t *raw, *src, *dst; nvlist_t *pools; nvpair_t *elem; char *name; uint64_t this_guid; boolean_t active; verify(poolname == NULL || guid == 0); if ((fd = open(cachefile, O_RDONLY)) < 0) { zfs_error_aux(hdl, "%s", strerror(errno)); (void) zfs_error(hdl, EZFS_BADCACHE, dgettext(TEXT_DOMAIN, "failed to open cache file")); return (NULL); } if (fstat64(fd, &statbuf) != 0) { zfs_error_aux(hdl, "%s", strerror(errno)); (void) close(fd); (void) zfs_error(hdl, EZFS_BADCACHE, dgettext(TEXT_DOMAIN, "failed to get size of cache file")); return (NULL); } if ((buf = zfs_alloc(hdl, statbuf.st_size)) == NULL) { (void) close(fd); return (NULL); } if (read(fd, buf, statbuf.st_size) != statbuf.st_size) { (void) close(fd); free(buf); (void) zfs_error(hdl, EZFS_BADCACHE, dgettext(TEXT_DOMAIN, "failed to read cache file contents")); return (NULL); } (void) close(fd); if (nvlist_unpack(buf, statbuf.st_size, &raw, 0) != 0) { free(buf); (void) zfs_error(hdl, EZFS_BADCACHE, dgettext(TEXT_DOMAIN, "invalid or corrupt cache file contents")); return (NULL); } free(buf); /* * Go through and get the current state of the pools and refresh their * state. */ if (nvlist_alloc(&pools, 0, 0) != 0) { (void) no_memory(hdl); nvlist_free(raw); return (NULL); } elem = NULL; while ((elem = nvlist_next_nvpair(raw, elem)) != NULL) { verify(nvpair_value_nvlist(elem, &src) == 0); verify(nvlist_lookup_string(src, ZPOOL_CONFIG_POOL_NAME, &name) == 0); if (poolname != NULL && strcmp(poolname, name) != 0) continue; verify(nvlist_lookup_uint64(src, ZPOOL_CONFIG_POOL_GUID, &this_guid) == 0); if (guid != 0) { verify(nvlist_lookup_uint64(src, ZPOOL_CONFIG_POOL_GUID, &this_guid) == 0); if (guid != this_guid) continue; } if (pool_active(hdl, name, this_guid, &active) != 0) { nvlist_free(raw); nvlist_free(pools); return (NULL); } if (active) continue; if ((dst = refresh_config(hdl, src)) == NULL) { nvlist_free(raw); nvlist_free(pools); return (NULL); } if (nvlist_add_nvlist(pools, nvpair_name(elem), dst) != 0) { (void) no_memory(hdl); nvlist_free(dst); nvlist_free(raw); nvlist_free(pools); return (NULL); } nvlist_free(dst); } nvlist_free(raw); return (pools); }
/* * Target is the dataset whose pool we want to open. */ static void import_pool(const char *target, boolean_t readonly) { nvlist_t *config; nvlist_t *pools; int error; char *sepp; spa_t *spa; nvpair_t *elem; nvlist_t *props; char *name; kernel_init(readonly ? FREAD : (FREAD | FWRITE)); g_zfs = libzfs_init(); ASSERT(g_zfs != NULL); dmu_objset_register_type(DMU_OST_ZFS, space_delta_cb); g_readonly = readonly; /* * If we only want readonly access, it's OK if we find * a potentially-active (ie, imported into the kernel) pool from the * default cachefile. */ if (readonly && spa_open(target, &spa, FTAG) == 0) { spa_close(spa, FTAG); return; } g_importargs.unique = B_TRUE; g_importargs.can_be_active = readonly; g_pool = strdup(target); if ((sepp = strpbrk(g_pool, "/@")) != NULL) *sepp = '\0'; g_importargs.poolname = g_pool; pools = zpool_search_import(g_zfs, &g_importargs); if (nvlist_empty(pools)) { if (!g_importargs.can_be_active) { g_importargs.can_be_active = B_TRUE; if (zpool_search_import(g_zfs, &g_importargs) != NULL || spa_open(target, &spa, FTAG) == 0) { fatal(spa, FTAG, "cannot import '%s': pool is " "active; run " "\"zpool export %s\" " "first\n", g_pool, g_pool); } } fatal(NULL, FTAG, "cannot import '%s': no such pool " "available\n", g_pool); } elem = nvlist_next_nvpair(pools, NULL); name = nvpair_name(elem); VERIFY(nvpair_value_nvlist(elem, &config) == 0); props = NULL; if (readonly) { VERIFY(nvlist_alloc(&props, NV_UNIQUE_NAME, 0) == 0); VERIFY(nvlist_add_uint64(props, zpool_prop_to_name(ZPOOL_PROP_READONLY), 1) == 0); } zfeature_checks_disable = B_TRUE; error = spa_import(name, config, props, ZFS_IMPORT_NORMAL); zfeature_checks_disable = B_FALSE; if (error == EEXIST) error = 0; if (error) fatal(NULL, FTAG, "can't import '%s': %s", name, strerror(error)); }
/* * Loads the pool namespace, or re-loads it if the cache has changed. */ static int namespace_reload(libzfs_handle_t *hdl) { nvlist_t *config; config_node_t *cn; nvpair_t *elem; zfs_cmd_t zc = { "\0", "\0", "\0", "\0", 0 }; void *cookie; if (hdl->libzfs_ns_gen == 0) { /* * This is the first time we've accessed the configuration * cache. Initialize the AVL tree and then fall through to the * common code. */ if ((hdl->libzfs_ns_avlpool = uu_avl_pool_create("config_pool", sizeof (config_node_t), offsetof(config_node_t, cn_avl), config_node_compare, UU_DEFAULT)) == NULL) return (no_memory(hdl)); if ((hdl->libzfs_ns_avl = uu_avl_create(hdl->libzfs_ns_avlpool, NULL, UU_DEFAULT)) == NULL) return (no_memory(hdl)); } if (zcmd_alloc_dst_nvlist(hdl, &zc, 0) != 0) return (-1); for (;;) { zc.zc_cookie = hdl->libzfs_ns_gen; //if (ioctl(hdl->libzfs_fd, ZFS_IOC_POOL_CONFIGS, &zc) != 0) { if (zfs_ioctl(hdl, ZFS_IOC_POOL_CONFIGS, &zc) != 0) { switch (errno) { case EEXIST: /* * The namespace hasn't changed. */ zcmd_free_nvlists(&zc); return (0); case ENOMEM: if (zcmd_expand_dst_nvlist(hdl, &zc) != 0) { zcmd_free_nvlists(&zc); return (-1); } break; default: zcmd_free_nvlists(&zc); return (zfs_standard_error(hdl, errno, dgettext(TEXT_DOMAIN, "failed to read " "pool configuration"))); } } else { hdl->libzfs_ns_gen = zc.zc_cookie; break; } } if (zcmd_read_dst_nvlist(hdl, &zc, &config) != 0) { zcmd_free_nvlists(&zc); return (-1); } zcmd_free_nvlists(&zc); /* * Clear out any existing configuration information. */ cookie = NULL; while ((cn = uu_avl_teardown(hdl->libzfs_ns_avl, &cookie)) != NULL) { nvlist_free(cn->cn_config); free(cn->cn_name); free(cn); } elem = NULL; while ((elem = nvlist_next_nvpair(config, elem)) != NULL) { nvlist_t *child; uu_avl_index_t where; if ((cn = zfs_alloc(hdl, sizeof (config_node_t))) == NULL) { nvlist_free(config); return (-1); } if ((cn->cn_name = zfs_strdup(hdl, nvpair_name(elem))) == NULL) { free(cn); nvlist_free(config); return (-1); } verify(nvpair_value_nvlist(elem, &child) == 0); if (nvlist_dup(child, &cn->cn_config, 0) != 0) { free(cn->cn_name); free(cn); nvlist_free(config); return (no_memory(hdl)); } verify(uu_avl_find(hdl->libzfs_ns_avl, cn, NULL, &where) == NULL); uu_avl_insert(hdl->libzfs_ns_avl, cn, where); } nvlist_free(config); return (0); }
/* * Read a file in the nvlist format * EIO - i/o error during read * ENOENT - file not found * EINVAL - file contents corrupted */ static int fread_nvp_list(nvfd_t *nvfd) { nvlist_t *nvl; nvpair_t *nvp; char *name; nvlist_t *sublist; int rval; nvp_list_t *np; nvp_list_t *nvp_list = NULL; nvp_list_t *nvp_tail = NULL; nvfd->nvf_list = NULL; nvfd->nvf_tail = NULL; rval = fread_nvlist(nvfd->nvf_name, &nvl); if (rval != 0) return (rval); ASSERT(nvl != NULL); nvp = NULL; while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) { name = nvpair_name(nvp); ASSERT(strlen(name) > 0); switch (nvpair_type(nvp)) { case DATA_TYPE_NVLIST: rval = nvpair_value_nvlist(nvp, &sublist); if (rval != 0) { KFIOERR((CE_CONT, "nvpair_value_nvlist error %s %d\n", name, rval)); goto error; } /* * convert nvlist for this device to * an nvp_list_t struct */ np = (nvfd->nvf_nvl2nvp)(sublist, name); if (np) { np->nvp_next = NULL; np->nvp_prev = nvp_tail; if (nvp_list == NULL) { nvp_list = np; } else { nvp_tail->nvp_next = np; } nvp_tail = np; } break; default: KFIOERR((CE_CONT, "%s: %s unsupported data type %d\n", nvfd->nvf_name, name, nvpair_type(nvp))); rval = EINVAL; goto error; } } nvlist_free(nvl); nvfd->nvf_list = nvp_list; nvfd->nvf_tail = nvp_tail; return (0); error: nvlist_free(nvl); if (nvp_list) nvp_list_free(nvfd, nvp_list); return (rval); }
static int zpool_import_by_guid(uint64_t searchguid) { int err = 0; nvlist_t *pools = NULL; nvpair_t *elem; nvlist_t *config; nvlist_t *found_config = NULL; nvlist_t *policy = NULL; boolean_t first; int flags = ZFS_IMPORT_NORMAL; uint32_t rewind_policy = ZPOOL_NO_REWIND; uint64_t pool_state, txg = -1ULL; importargs_t idata = { 0 }; #ifdef ZFS_AUTOIMPORT_ZPOOL_STATUS_OK_ONLY char *msgid; zpool_status_t reason; zpool_errata_t errata; #endif if ((g_zfs = libzfs_init()) == NULL) return (1); idata.unique = B_TRUE; /* In the future, we can capture further policy and include it here */ if (nvlist_alloc(&policy, NV_UNIQUE_NAME, 0) != 0 || nvlist_add_uint64(policy, ZPOOL_REWIND_REQUEST_TXG, txg) != 0 || nvlist_add_uint32(policy, ZPOOL_REWIND_REQUEST, rewind_policy) != 0) goto error; if (!priv_ineffect(PRIV_SYS_CONFIG)) { printf("cannot discover pools: permission denied\n"); nvlist_free(policy); return (1); } idata.guid = searchguid; pools = zpool_search_import(g_zfs, &idata); if (pools == NULL && idata.exists) { printf("cannot import '%llu': a pool with that guid is already " "created/imported\n", searchguid); err = 1; } else if (pools == NULL) { printf("cannot import '%llu': no such pool available\n", searchguid); err = 1; } if (err == 1) { nvlist_free(policy); return (1); } /* * At this point we have a list of import candidate configs. Even though * we were searching by guid, we still need to post-process the list to * deal with pool state. */ err = 0; elem = NULL; first = B_TRUE; while ((elem = nvlist_next_nvpair(pools, elem)) != NULL) { verify(nvpair_value_nvlist(elem, &config) == 0); verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_STATE, &pool_state) == 0); if (pool_state == POOL_STATE_DESTROYED) continue; verify(nvlist_add_nvlist(config, ZPOOL_REWIND_POLICY, policy) == 0); uint64_t guid; /* * Search for a pool by guid. */ verify(nvlist_lookup_uint64(config, ZPOOL_CONFIG_POOL_GUID, &guid) == 0); if (guid == searchguid) found_config = config; } /* * If we were searching for a specific pool, verify that we found a * pool, and then do the import. */ if (err == 0) { if (found_config == NULL) { printf("cannot import '%llu': no such pool available\n", searchguid); err = B_TRUE; } else { #ifdef ZFS_AUTOIMPORT_ZPOOL_STATUS_OK_ONLY reason = zpool_import_status(config, &msgid, &errata); if (reason == ZPOOL_STATUS_OK) err |= do_import(found_config, NULL, NULL, NULL, flags); else err = 1; #else err |= do_import(found_config, NULL, NULL, NULL, flags); #endif } } error: nvlist_free(pools); nvlist_free(policy); libzfs_fini(g_zfs); return (err ? 1 : 0); }