static int sysev_evc_handler(sysevent_t *ev, void *cookie) { char *name, *zonename, *oldstate, *newstate; nvlist_t *nvlist; nvpair_t *curr, *next; cookie = cookie; // SILENCE! if (sysevent_get_attr_list(ev, &nvlist) != 0) { // XXX Error return (1); } // loop through event nvpairs to get our interesting values curr = nvlist_next_nvpair(nvlist, NULL); while (curr != NULL) { // all fields we're interested in are strings if (nvpair_type(curr) == DATA_TYPE_STRING) { name = nvpair_name(curr); if (strcmp(name, ZONE_CB_NAME) == 0) { nvpair_value_string(curr, &zonename); } else if (strcmp(name, ZONE_CB_NEWSTATE) == 0) { nvpair_value_string(curr, &newstate); } else if (strcmp(name, ZONE_CB_OLDSTATE) == 0) { nvpair_value_string(curr, &oldstate); } } next = nvlist_next_nvpair(nvlist, curr); curr = next; } // if it is a boot into running we need to enable the gate if (strcmp(oldstate, ZONE_EVENT_READY) == 0 && strcmp(newstate, ZONE_EVENT_RUNNING) == 0) { gate_attach(zonename); } // ignore multiple shutting_down -> shutting_down transitions if (strcmp(oldstate, newstate) != 0) { char zonebrand[MAXNAMELEN]; // get brand for zone if (zone_get_brand(zonename, zonebrand, sizeof (zonebrand)) == Z_OK) { request_send_state_event(zonename, zonebrand, oldstate, newstate); } else { request_send_state_event(zonename, NULL, oldstate, newstate); } } return (0); }
static void get_slice_use(dm_descriptor_t slice, char *name, char **used_name, char **used_by, int *error) { /* Get slice use statistics */ nvlist_t *stats = dm_get_stats(slice, DM_SLICE_STAT_USE, error); if (*error != 0) { handle_error("could not get stats of slice %s", name); } else { *used_name = NULL; *used_by = NULL; if (stats != NULL) { char *tmp; nvpair_t *match; /* Get the type of usage for this slice */ match = zjni_nvlist_walk_nvpair( stats, DM_USED_BY, DATA_TYPE_STRING, NULL); if (match != NULL && nvpair_value_string(match, &tmp) == 0) { *used_name = strdup(tmp); if (*used_name == NULL) { *error = -1; handle_error("out of memory"); } else { /* Get the object using this slice */ match = zjni_nvlist_walk_nvpair(stats, DM_USED_NAME, DATA_TYPE_STRING, NULL); if (match != NULL && nvpair_value_string(match, &tmp) == 0) { *used_by = strdup(tmp); if (*used_by == NULL) { *error = -1; handle_error( "out of memory"); } } } } nvlist_free(stats); } } }
static void prof_make_maps(struct sdev_node *dir) { nvpair_t *nvp = NULL; nvlist_t *nvl = dir->sdev_prof.dev_map; int rv; ASSERT(RW_WRITE_HELD(&dir->sdev_contents)); if (nvl == NULL) return; while (nvp = nvlist_next_nvpair(nvl, nvp)) { char *name; char *rename = nvpair_name(nvp); rv = nvpair_value_string(nvp, &name); if (rv != 0) { cmn_err(CE_WARN, sdev_nvp_val_err, rv, nvpair_name(nvp)); break; } sdcmn_err10(("map %s -> %s\n", name, rename)); (void) prof_lookup_globaldev(dir, sdev_origins->sdev_root, name, rename); } }
static void apply_glob_pattern(struct sdev_node *pdir, struct sdev_node *cdir) { char *name; nvpair_t *nvp = NULL; nvlist_t *nvl; struct vnode *vp = SDEVTOV(cdir); int rv = 0; if (vp->v_type != VDIR) return; name = cdir->sdev_name; nvl = pdir->sdev_prof.dev_glob_incdir; while (nvp = nvlist_next_nvpair(nvl, nvp)) { char *pathleft; char *expr = nvpair_name(nvp); if (!gmatch(name, expr)) continue; rv = nvpair_value_string(nvp, &pathleft); if (rv != 0) { cmn_err(CE_WARN, sdev_nvp_val_err, rv, nvpair_name(nvp)); break; } process_rule(cdir, cdir->sdev_origin, pathleft, NULL, PROFILE_TYPE_INCLUDE); } }
char * fnvpair_value_string(nvpair_t *nvp) { char *rv; VERIFY0(nvpair_value_string(nvp, &rv)); return (rv); }
/* * Use the supplied nvpair_t to set the name, type and value of the * supplied pool_value_t. * * Return: PO_SUCCESS/PO_FAIL */ int pool_value_from_nvpair(pool_value_t *pv, nvpair_t *pn) { uchar_t bval; uint64_t uval; int64_t ival; double dval; uint_t nelem; uchar_t *dval_b; char *sval; if (pool_value_set_name(pv, nvpair_name(pn)) != PO_SUCCESS) return (PO_FAIL); switch (nvpair_type(pn)) { case DATA_TYPE_BYTE: if (nvpair_value_byte(pn, &bval) != 0) { pool_seterror(POE_SYSTEM); return (PO_FAIL); } pool_value_set_bool(pv, bval); break; case DATA_TYPE_BYTE_ARRAY: if (nvpair_value_byte_array(pn, &dval_b, &nelem) != 0) { pool_seterror(POE_SYSTEM); return (PO_FAIL); } (void) memcpy(&dval, dval_b, sizeof (double)); pool_value_set_double(pv, dval); break; case DATA_TYPE_INT64: if (nvpair_value_int64(pn, &ival) != 0) { pool_seterror(POE_SYSTEM); return (PO_FAIL); } pool_value_set_int64(pv, ival); break; case DATA_TYPE_UINT64: if (nvpair_value_uint64(pn, &uval) != 0) { pool_seterror(POE_SYSTEM); return (PO_FAIL); } pool_value_set_uint64(pv, uval); break; case DATA_TYPE_STRING: if (nvpair_value_string(pn, &sval) != 0) { pool_seterror(POE_SYSTEM); return (PO_FAIL); } if (pool_value_set_string(pv, sval) != PO_SUCCESS) return (PO_FAIL); break; default: pool_seterror(POE_SYSTEM); return (PO_FAIL); } return (PO_SUCCESS); }
/* * Goes through the ini property list and validates * each entry. If errs is non-NULL, will return explicit errors * for each property that fails validation. */ static int it_validate_iniprops(nvlist_t *nvl, nvlist_t *errs) { int errcnt = 0; nvpair_t *nvp = NULL; data_type_t nvtype; char *name; char *val; if (!nvl) { return (0); } while ((nvp = nvlist_next_nvpair(nvl, nvp)) != NULL) { name = nvpair_name(nvp); nvtype = nvpair_type(nvp); if (!name) { continue; } if (strcmp(name, PROP_CHAP_USER) == 0) { if (nvtype != DATA_TYPE_STRING) { PROPERR(errs, name, gettext("must be a string value")); errcnt++; continue; } } else if (strcmp(name, PROP_CHAP_SECRET) == 0) { /* * must be between 12 and 255 chars in cleartext. * will be base64 encoded when it's set. */ if (nvtype == DATA_TYPE_STRING) { val = NULL; (void) nvpair_value_string(nvp, &val); } if (!val) { PROPERR(errs, name, gettext("must be a string value")); errcnt++; continue; } } else { /* unrecognized property */ PROPERR(errs, name, gettext("unrecognized property")); errcnt++; } } if (errcnt) { return (EINVAL); } return (0); }
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); }
/* Check if name passes matching rules */ int prof_name_matched(char *name, struct sdev_node *dir) { int type, match = 0; char *expr; nvlist_t *nvl; nvpair_t *nvp = NULL; int rv; /* check against nvlist for leaf include/exclude */ nvl = dir->sdev_prof.dev_name; while (nvp = nvlist_next_nvpair(nvl, nvp)) { expr = nvpair_name(nvp); rv = nvpair_value_int32(nvp, &type); if (rv != 0) { cmn_err(CE_WARN, sdev_nvp_val_err, rv, nvpair_name(nvp)); break; } if (type == PROFILE_TYPE_EXCLUDE) { if (gmatch(name, expr)) return (0); /* excluded */ } else if (!match) { match = gmatch(name, expr); } } if (match) { sdcmn_err10(("prof_name_matched: %s\n", name)); return (match); } /* check for match against directory globbing pattern */ nvl = dir->sdev_prof.dev_glob_incdir; while (nvp = nvlist_next_nvpair(nvl, nvp)) { char *pathleft; expr = nvpair_name(nvp); if (gmatch(name, expr) == 0) continue; rv = nvpair_value_string(nvp, &pathleft); if (rv != 0) { cmn_err(CE_WARN, sdev_nvp_val_err, rv, nvpair_name(nvp)); break; } if (is_nonempty_dir(name, pathleft, dir)) { sdcmn_err10(("prof_name_matched: dir %s\n", name)); return (1); } } return (0); }
static int dsl_dataset_user_hold_check(void *arg, dmu_tx_t *tx) { dsl_dataset_user_hold_arg_t *dduha = arg; dsl_pool_t *dp = dmu_tx_pool(tx); nvpair_t *pair; if (spa_version(dp->dp_spa) < SPA_VERSION_USERREFS) return (SET_ERROR(ENOTSUP)); if (!dmu_tx_is_syncing(tx)) return (0); for (pair = nvlist_next_nvpair(dduha->dduha_holds, NULL); pair != NULL; pair = nvlist_next_nvpair(dduha->dduha_holds, pair)) { dsl_dataset_t *ds; int error = 0; char *htag, *name; /* must be a snapshot */ name = nvpair_name(pair); if (strchr(name, '@') == NULL) error = SET_ERROR(EINVAL); if (error == 0) error = nvpair_value_string(pair, &htag); if (error == 0) error = dsl_dataset_hold(dp, name, FTAG, &ds); if (error == 0) { error = dsl_dataset_user_hold_check_one(ds, htag, dduha->dduha_minor != 0, tx); dsl_dataset_rele(ds, FTAG); } if (error == 0) { fnvlist_add_string(dduha->dduha_chkholds, name, htag); } else { /* * We register ENOENT errors so they can be correctly * reported if needed, such as when all holds fail. */ fnvlist_add_int32(dduha->dduha_errlist, name, error); if (error != ENOENT) return (error); } } return (0); }
/* * This is invoked after a new filesystem is mounted to define the * name space. It is also invoked during normal system operation * to update the name space. * * Applications call di_prof_commit() in libdevinfo, which invokes * modctl(). modctl calls this function. The input is a packed nvlist. */ int devname_profile_update(char *packed, size_t packed_sz) { char *mntpt; nvlist_t *nvl; nvpair_t *nvp; struct sdev_data *mntinfo; int err; int rv; nvl = NULL; if ((err = copyin_nvlist(packed, packed_sz, &nvl)) != 0) return (err); ASSERT(nvl); /* The first nvpair must be the mount point */ nvp = nvlist_next_nvpair(nvl, NULL); if (strcmp(nvpair_name(nvp), SDEV_NVNAME_MOUNTPT) != 0) { cmn_err(CE_NOTE, "devname_profile_update: mount point not specified"); nvlist_free(nvl); return (EINVAL); } /* find the matching filesystem instance */ rv = nvpair_value_string(nvp, &mntpt); if (rv != 0) { cmn_err(CE_WARN, sdev_nvp_val_err, rv, nvpair_name(nvp)); } else { mntinfo = sdev_find_mntinfo(mntpt); if (mntinfo == NULL) { cmn_err(CE_NOTE, "devname_profile_update: " " mount point %s not found", mntpt); nvlist_free(nvl); return (EINVAL); } /* now do the hardwork to process the profile */ sdev_process_profile(mntinfo, nvl); sdev_mntinfo_rele(mntinfo); } nvlist_free(nvl); return (0); }
/* * Put new CPU property. * Handle special case of "cpu.status". */ int pool_cpu_propput(processorid_t cpuid, nvpair_t *pair) { int ret = 0; cpu_t *cpu; ASSERT(pool_lock_held()); ASSERT(INGLOBALZONE(curproc)); if (nvpair_type(pair) == DATA_TYPE_STRING && strcmp(nvpair_name(pair), "cpu.status") == 0) { char *val; int status; int old_status; (void) nvpair_value_string(pair, &val); if (strcmp(val, PS_OFFLINE) == 0) status = P_OFFLINE; else if (strcmp(val, PS_ONLINE) == 0) status = P_ONLINE; else if (strcmp(val, PS_NOINTR) == 0) status = P_NOINTR; else if (strcmp(val, PS_FAULTED) == 0) status = P_FAULTED; else if (strcmp(val, PS_SPARE) == 0) status = P_SPARE; else return (EINVAL); ret = p_online_internal(cpuid, status, &old_status); } else { mutex_enter(&cpu_lock); if ((cpu = cpu_get(cpuid)) == NULL) ret = EINVAL; if (cpu->cpu_props == NULL) { (void) nvlist_alloc(&cpu->cpu_props, NV_UNIQUE_NAME, KM_SLEEP); (void) nvlist_add_string(cpu->cpu_props, "cpu.comment", ""); } ret = pool_propput_common(cpu->cpu_props, pair, pool_cpu_props); if (ret == 0) pool_cpu_mod = gethrtime(); mutex_exit(&cpu_lock); } return (ret); }
/* Ensure that "None" is an option in the digest list, and select it */ static kv_status_t iser_handle_digest(nvpair_t *choices, const idm_kv_xlate_t *ikvx, nvlist_t *request_nvl, nvlist_t *response_nvl, nvlist_t *negotiated_nvl) { kv_status_t kvrc = KV_VALUE_ERROR; int nvrc = 0; nvpair_t *digest_choice; char *digest_choice_string; /* * Loop through all digest choices. We need to enforce no * "None" for both header and data digest. If we find our * required value, add the value to our negotiated values list * and respond with that value in the login response. If not, * indicate a value error for the iSCSI layer to work with. */ digest_choice = idm_get_next_listvalue(choices, NULL); while (digest_choice != NULL) { nvrc = nvpair_value_string(digest_choice, &digest_choice_string); ASSERT(nvrc == 0); if (strcasecmp(digest_choice_string, "none") == 0) { /* Add to negotiated values list */ nvrc = nvlist_add_string(negotiated_nvl, ikvx->ik_key_name, digest_choice_string); kvrc = idm_nvstat_to_kvstat(nvrc); if (nvrc == 0) { /* Add to login response list */ nvrc = nvlist_add_string(response_nvl, ikvx->ik_key_name, digest_choice_string); kvrc = idm_nvstat_to_kvstat(nvrc); /* Remove from the request (we've handled it) */ (void) nvlist_remove_all(request_nvl, ikvx->ik_key_name); } break; } digest_choice = idm_get_next_listvalue(choices, digest_choice); } return (kvrc); }
/* * Get the named string from the given nvlist_t. * * @param attrs * the nvlist_t to search * * @param which * the string key for this element in the list * * @param str * RETURN: the requested string * * @return 0 * if successful * * @return ENOENT * if no matching name-value pair is found */ int get_string( nvlist_t *attrs, char *which, char **str) { int error; nvpair_t *match = nvlist_walk_nvpair(attrs, which, DATA_TYPE_STRING, NULL); if (match == NULL) { error = ENOENT; } else { error = nvpair_value_string(match, str); } return (error); }
static int dsl_dataset_user_hold_check(void *arg, dmu_tx_t *tx) { dsl_dataset_user_hold_arg_t *dduha = arg; dsl_pool_t *dp = dmu_tx_pool(tx); nvpair_t *pair; int rv = 0; if (spa_version(dp->dp_spa) < SPA_VERSION_USERREFS) return (ENOTSUP); for (pair = nvlist_next_nvpair(dduha->dduha_holds, NULL); pair != NULL; pair = nvlist_next_nvpair(dduha->dduha_holds, pair)) { int error = 0; dsl_dataset_t *ds; char *htag; /* must be a snapshot */ if (strchr(nvpair_name(pair), '@') == NULL) error = EINVAL; if (error == 0) error = nvpair_value_string(pair, &htag); if (error == 0) { error = dsl_dataset_hold(dp, nvpair_name(pair), FTAG, &ds); } if (error == 0) { error = dsl_dataset_user_hold_check_one(ds, htag, dduha->dduha_minor != 0, tx); dsl_dataset_rele(ds, FTAG); } if (error != 0) { rv = error; fnvlist_add_int32(dduha->dduha_errlist, nvpair_name(pair), error); } } return (rv); }
static void cvt_string(nvlist_t *nvl, nvpair_t *pair, data_type_t tgt) { const char *name = nvpair_name(pair); uint64_t intval; char *str; int ret; ASSERT3U(nvpair_type(pair), ==, DATA_TYPE_STRING); ret = nvpair_value_string(pair, &str); if (ret) return; switch (tgt) { case DATA_TYPE_UINT64: ret = str2u64(str, &intval); if (!ret) nvl_set_int(nvl, name, intval); break; default: panic("unexpected target type"); } }
/* * This method builds values for "sharesmb" property from the * nvlist argument. The values are returned in sharesmb_val variable. */ static int sa_zfs_sprintf_new_prop(nvlist_t *nvl, char *sharesmb_val) { char cur_val[MAXPATHLEN]; char *name, *val; nvpair_t *cur; int err = 0; cur = nvlist_next_nvpair(nvl, NULL); while (cur != NULL) { name = nvpair_name(cur); err = nvpair_value_string(cur, &val); if ((err != 0) || (name == NULL) || (val == NULL)) return (-1); (void) snprintf(cur_val, MAXPATHLEN, "%s=%s,", name, val); (void) strlcat(sharesmb_val, cur_val, MAXPATHLEN); cur = nvlist_next_nvpair(nvl, cur); } return (0); }
/* * Create symlinks in the current directory based on profile */ static void prof_make_symlinks(struct sdev_node *dir) { char *tgt, *lnm; nvpair_t *nvp = NULL; nvlist_t *nvl = dir->sdev_prof.dev_symlink; int rv; ASSERT(RW_WRITE_HELD(&dir->sdev_contents)); if (nvl == NULL) return; while (nvp = nvlist_next_nvpair(nvl, nvp)) { lnm = nvpair_name(nvp); rv = nvpair_value_string(nvp, &tgt); if (rv != 0) { cmn_err(CE_WARN, sdev_nvp_val_err, rv, nvpair_name(nvp)); break; } prof_make_sym(dir, lnm, tgt); } }
/* * Determine if string 'value' matches 'nvp' value. The 'value' string is * converted, depending on the type of 'nvp', prior to match. For numeric * types, a radix independent sscanf conversion of 'value' is used. If 'nvp' * is an array type, 'ai' is the index into the array against which we are * checking for match. If nvp is of DATA_TYPE_STRING*, the caller can pass * in a regex_t compilation of value in 'value_regex' to trigger regular * expression string match instead of simple strcmp(). * * Return 1 on match, 0 on no-match, and -1 on error. If the error is * related to value syntax error and 'ep' is non-NULL, *ep will point into * the 'value' string at the location where the error exists. * * NOTE: It may be possible to move the non-regex_t version of this into * common code used by library/kernel/boot. */ int nvpair_value_match_regex(nvpair_t *nvp, int ai, char *value, regex_t *value_regex, char **ep) { char *evalue; uint_t a_len; int sr; if (ep) *ep = NULL; if ((nvp == NULL) || (value == NULL)) return (-1); /* error fail match - invalid args */ /* make sure array and index combination make sense */ if ((nvpair_type_is_array(nvp) && (ai < 0)) || (!nvpair_type_is_array(nvp) && (ai >= 0))) return (-1); /* error fail match - bad index */ /* non-string values should be single 'chunk' */ if ((nvpair_type(nvp) != DATA_TYPE_STRING) && (nvpair_type(nvp) != DATA_TYPE_STRING_ARRAY)) { value += strspn(value, " \t"); evalue = value + strcspn(value, " \t"); if (*evalue) { if (ep) *ep = evalue; return (-1); /* error fail match - syntax */ } } sr = EOF; switch (nvpair_type(nvp)) { case DATA_TYPE_STRING: { char *val; /* check string value for match */ if (nvpair_value_string(nvp, &val) == 0) { if (value_regex) { if (regexec(value_regex, val, (size_t)0, NULL, 0) == 0) return (1); /* match */ } else { if (strcmp(value, val) == 0) return (1); /* match */ } } break; } case DATA_TYPE_STRING_ARRAY: { char **val_array; /* check indexed string value of array for match */ if ((nvpair_value_string_array(nvp, &val_array, &a_len) == 0) && (ai < a_len)) { if (value_regex) { if (regexec(value_regex, val_array[ai], (size_t)0, NULL, 0) == 0) return (1); } else { if (strcmp(value, val_array[ai]) == 0) return (1); } } break; } case DATA_TYPE_BYTE: { uchar_t val, val_arg; /* scanf uchar_t from value and check for match */ sr = sscanf(value, "%c", &val_arg); if ((sr == 1) && (nvpair_value_byte(nvp, &val) == 0) && (val == val_arg)) return (1); break; } case DATA_TYPE_BYTE_ARRAY: { uchar_t *val_array, val_arg; /* check indexed value of array for match */ sr = sscanf(value, "%c", &val_arg); if ((sr == 1) && (nvpair_value_byte_array(nvp, &val_array, &a_len) == 0) && (ai < a_len) && (val_array[ai] == val_arg)) return (1); break; } case DATA_TYPE_INT8: { int8_t val, val_arg; /* scanf int8_t from value and check for match */ sr = sscanf(value, "%"SCNi8, &val_arg); if ((sr == 1) && (nvpair_value_int8(nvp, &val) == 0) && (val == val_arg)) return (1); break; } case DATA_TYPE_INT8_ARRAY: { int8_t *val_array, val_arg; /* check indexed value of array for match */ sr = sscanf(value, "%"SCNi8, &val_arg); if ((sr == 1) && (nvpair_value_int8_array(nvp, &val_array, &a_len) == 0) && (ai < a_len) && (val_array[ai] == val_arg)) return (1); break; } case DATA_TYPE_UINT8: { uint8_t val, val_arg; /* scanf uint8_t from value and check for match */ sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg); if ((sr == 1) && (nvpair_value_uint8(nvp, &val) == 0) && (val == val_arg)) return (1); break; } case DATA_TYPE_UINT8_ARRAY: { uint8_t *val_array, val_arg; /* check indexed value of array for match */ sr = sscanf(value, "%"SCNi8, (int8_t *)&val_arg); if ((sr == 1) && (nvpair_value_uint8_array(nvp, &val_array, &a_len) == 0) && (ai < a_len) && (val_array[ai] == val_arg)) return (1); break; } case DATA_TYPE_INT16: { int16_t val, val_arg; /* scanf int16_t from value and check for match */ sr = sscanf(value, "%"SCNi16, &val_arg); if ((sr == 1) && (nvpair_value_int16(nvp, &val) == 0) && (val == val_arg)) return (1); break; } case DATA_TYPE_INT16_ARRAY: { int16_t *val_array, val_arg; /* check indexed value of array for match */ sr = sscanf(value, "%"SCNi16, &val_arg); if ((sr == 1) && (nvpair_value_int16_array(nvp, &val_array, &a_len) == 0) && (ai < a_len) && (val_array[ai] == val_arg)) return (1); break; } case DATA_TYPE_UINT16: { uint16_t val, val_arg; /* scanf uint16_t from value and check for match */ sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg); if ((sr == 1) && (nvpair_value_uint16(nvp, &val) == 0) && (val == val_arg)) return (1); break; } case DATA_TYPE_UINT16_ARRAY: { uint16_t *val_array, val_arg; /* check indexed value of array for match */ sr = sscanf(value, "%"SCNi16, (int16_t *)&val_arg); if ((sr == 1) && (nvpair_value_uint16_array(nvp, &val_array, &a_len) == 0) && (ai < a_len) && (val_array[ai] == val_arg)) return (1); break; } case DATA_TYPE_INT32: { int32_t val, val_arg; /* scanf int32_t from value and check for match */ sr = sscanf(value, "%"SCNi32, &val_arg); if ((sr == 1) && (nvpair_value_int32(nvp, &val) == 0) && (val == val_arg)) return (1); break; } case DATA_TYPE_INT32_ARRAY: { int32_t *val_array, val_arg; /* check indexed value of array for match */ sr = sscanf(value, "%"SCNi32, &val_arg); if ((sr == 1) && (nvpair_value_int32_array(nvp, &val_array, &a_len) == 0) && (ai < a_len) && (val_array[ai] == val_arg)) return (1); break; } case DATA_TYPE_UINT32: { uint32_t val, val_arg; /* scanf uint32_t from value and check for match */ sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg); if ((sr == 1) && (nvpair_value_uint32(nvp, &val) == 0) && (val == val_arg)) return (1); break; } case DATA_TYPE_UINT32_ARRAY: { uint32_t *val_array, val_arg; /* check indexed value of array for match */ sr = sscanf(value, "%"SCNi32, (int32_t *)&val_arg); if ((sr == 1) && (nvpair_value_uint32_array(nvp, &val_array, &a_len) == 0) && (ai < a_len) && (val_array[ai] == val_arg)) return (1); break; } case DATA_TYPE_INT64: { int64_t val, val_arg; /* scanf int64_t from value and check for match */ sr = sscanf(value, "%"SCNi64, &val_arg); if ((sr == 1) && (nvpair_value_int64(nvp, &val) == 0) && (val == val_arg)) return (1); break; } case DATA_TYPE_INT64_ARRAY: { int64_t *val_array, val_arg; /* check indexed value of array for match */ sr = sscanf(value, "%"SCNi64, &val_arg); if ((sr == 1) && (nvpair_value_int64_array(nvp, &val_array, &a_len) == 0) && (ai < a_len) && (val_array[ai] == val_arg)) return (1); break; } case DATA_TYPE_UINT64: { uint64_t val_arg, val; /* scanf uint64_t from value and check for match */ sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg); if ((sr == 1) && (nvpair_value_uint64(nvp, &val) == 0) && (val == val_arg)) return (1); break; } case DATA_TYPE_UINT64_ARRAY: { uint64_t *val_array, val_arg; /* check indexed value of array for match */ sr = sscanf(value, "%"SCNi64, (int64_t *)&val_arg); if ((sr == 1) && (nvpair_value_uint64_array(nvp, &val_array, &a_len) == 0) && (ai < a_len) && (val_array[ai] == val_arg)) return (1); break; } case DATA_TYPE_BOOLEAN_VALUE: { boolean_t val, val_arg; /* scanf boolean_t from value and check for match */ sr = sscanf(value, "%"SCNi32, &val_arg); if ((sr == 1) && (nvpair_value_boolean_value(nvp, &val) == 0) && (val == val_arg)) return (1); break; } case DATA_TYPE_BOOLEAN_ARRAY: { boolean_t *val_array, val_arg; /* check indexed value of array for match */ sr = sscanf(value, "%"SCNi32, &val_arg); if ((sr == 1) && (nvpair_value_boolean_array(nvp, &val_array, &a_len) == 0) && (ai < a_len) && (val_array[ai] == val_arg)) return (1); break; } case DATA_TYPE_HRTIME: case DATA_TYPE_NVLIST: case DATA_TYPE_NVLIST_ARRAY: case DATA_TYPE_BOOLEAN: case DATA_TYPE_DOUBLE: case DATA_TYPE_UNKNOWN: default: /* * unknown/unsupported data type */ return (-1); /* error fail match */ } /* * check to see if sscanf failed conversion, return approximate * pointer to problem */ if (sr != 1) { if (ep) *ep = value; return (-1); /* error fail match - syntax */ } return (0); /* fail match */ }
static void rcm_print_nvlist(nvlist_t *nvl) { uchar_t data_byte; int16_t data_int16; uint16_t data_uint16; int32_t data_int32; uint32_t data_uint32; int64_t data_int64; uint64_t data_uint64; char *data_string; char **data_strings; uint_t data_nstrings; nvpair_t *nvp = NULL; int i; char *name; data_type_t type; rcm_log_message(RCM_TRACE3, "event attributes:\n"); while (nvp = nvlist_next_nvpair(nvl, nvp)) { type = nvpair_type(nvp); name = nvpair_name(nvp); rcm_log_message(RCM_TRACE3, "\t%s(%d)=", name, type); switch (type) { case DATA_TYPE_BOOLEAN: rcm_log_message(RCM_TRACE3, "True (boolean)\n"); break; case DATA_TYPE_BYTE: (void) nvpair_value_byte(nvp, &data_byte); rcm_log_message(RCM_TRACE3, "0x%x (byte)\n", data_byte); break; case DATA_TYPE_INT16: (void) nvpair_value_int16(nvp, &data_int16); rcm_log_message(RCM_TRACE3, "0x%x (int16)\n", data_int16); break; case DATA_TYPE_UINT16: (void) nvpair_value_uint16(nvp, &data_uint16); rcm_log_message(RCM_TRACE3, "0x%x (uint16)\n", data_uint16); break; case DATA_TYPE_INT32: (void) nvpair_value_int32(nvp, &data_int32); rcm_log_message(RCM_TRACE3, "0x%x (int32)\n", data_int32); break; case DATA_TYPE_UINT32: (void) nvpair_value_uint32(nvp, &data_uint32); rcm_log_message(RCM_TRACE3, "0x%x (uint32)\n", data_uint32); break; case DATA_TYPE_INT64: (void) nvpair_value_int64(nvp, &data_int64); rcm_log_message(RCM_TRACE3, "0x%lx (int64)\n", data_int64); break; case DATA_TYPE_UINT64: (void) nvpair_value_uint64(nvp, &data_uint64); rcm_log_message(RCM_TRACE3, "0x%lx (uint64)\n", data_uint64); break; case DATA_TYPE_STRING: (void) nvpair_value_string(nvp, &data_string); rcm_log_message(RCM_TRACE3, "\"%s\" (string)\n", data_string); break; case DATA_TYPE_STRING_ARRAY: (void) nvpair_value_string_array(nvp, &data_strings, &data_nstrings); for (i = 0; i < data_nstrings; i++) { rcm_log_message(RCM_TRACE3, "\t\"%s\" (string)\n", data_strings[i]); if (i < (data_nstrings - 1)) rcm_log_message(RCM_TRACE3, "\t\t\t"); } break; default: rcm_log_message(RCM_TRACE3, "<not dumped>\n"); break; } } }
static int build_jailcmd(char ***argvp, bool interactive, int argc, char *argv[]) { char *cmd, **jargv, *name, *val; nvpair_t *nvp; size_t i, iarg, nargv; cmd = NULL; nvp = NULL; iarg = i = 0; if (nvlist_size(jailparams, &nargv, NV_ENCODE_NATIVE) != 0) return (1); /* * Number of args + "/usr/sbin/jail", "-c", and ending NULL. * If interactive also include command. */ nargv += 3; if (interactive) { if (argc == 0) nargv++; else nargv += argc; } jargv = *argvp = calloc(nargv, sizeof(jargv)); if (jargv == NULL) err(2, "calloc"); jargv[iarg++] = strdup("/usr/sbin/jail"); jargv[iarg++] = strdup("-c"); while ((nvp = nvlist_next_nvpair(jailparams, nvp)) != NULL) { name = nvpair_name(nvp); if (nvpair_value_string(nvp, &val) != 0) continue; if (asprintf(&jargv[iarg++], "%s=%s", name, val) < 0) goto error; } if (interactive) { if (argc < 1) cmd = strdup("/bin/sh"); else { cmd = argv[0]; argc--; argv++; } if (asprintf(&jargv[iarg++], "command=%s", cmd) < 0) { goto error; } if (argc < 1) { free(cmd); cmd = NULL; } for (; argc > 0; argc--) { if (asprintf(&jargv[iarg++], "%s", argv[0]) < 0) goto error; argv++; } } return (0); error: if (interactive && argc < 1) free(cmd); for (; i < iarg - 1; i++) { free(jargv[i]); } free(jargv); return (1); }
/* * 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); }
/* * It's up to the caller to do any sorting or pretty-printing of the device * mappings we report. Since we're storing the device links as just the cXtYdZ * part, we'll add /dev/rdsk/ back on when we print the listing so we maintain * compatibility with previous versions of this tool. There's a little bit * of footwork involved to make sure that we show all the paths to a device * rather than just the first one we stashed away. */ static void list_devs(int listguids, int ctrl) { nvlist_t *thisdevnvl; nvpair_t *pair; char *diskpath, *livepath, *key, *querydev; char *matchctrl = NULL; char checkctrl[MAXPATHLEN]; int rv; if (!mpxenabled) { if (mpxprop) { logmsg(MSG_ERROR, gettext("MPXIO disabled\n")); } else { logmsg(MSG_ERROR, gettext("No STMS devices have " "been found\n")); } return; } if (listguids) { (void) printf(gettext("non-STMS device name\t\t\tGUID\n" "------------------------------------------" "------------------------\n")); } else { (void) printf(gettext("non-STMS device name\t\t\t" "STMS device name\n" "------------------------------------------" "------------------------\n")); } bzero(checkctrl, MAXPATHLEN); pair = NULL; while ((pair = nvlist_next_nvpair(mapnvl, pair)) != NULL) { boolean_t livescsivhcip = B_FALSE; if ((((rv = nvpair_value_string(pair, &querydev)) < 0) || ((key = nvpair_name(pair)) == NULL)) || ((strstr(key, "/pci") != NULL) || (strstr(key, "/sbus") != NULL) || (strstr(key, "/scsi_vhci") != NULL) || (strncmp(key, "id1", 3) == 0))) { logmsg(MSG_INFO, "list_devs: rv = %d; (%s) is not a devlink, " "continuing.\n", rv, (key != NULL) ? key : "null"); querydev = NULL; continue; } (void) nvlist_lookup_nvlist(mapnvl, querydev, &thisdevnvl); (void) nvlist_lookup_boolean_value(thisdevnvl, NVL_MPXEN, &livescsivhcip); (void) nvlist_lookup_string(thisdevnvl, NVL_MPXPATH, &livepath); if ((!livescsivhcip) || (livescsivhcip && (strncmp(key, livepath, strlen(key)) == 0))) continue; (void) nvlist_lookup_string(thisdevnvl, NVL_PATH, &diskpath); logmsg(MSG_INFO, "list_devs: %s :: %s ::%s :: MPXEN (%s)\n", key, diskpath, livepath, ((livescsivhcip) ? "TRUE" : "FALSE")); if (ctrl > -1) { (void) sprintf(checkctrl, "c%dt", ctrl); matchctrl = strstr(key, checkctrl); if (matchctrl == NULL) continue; } if (listguids != 0) { char *tempguid; ddi_devid_t curdevid; int rv; rv = devid_str_decode(querydev, &curdevid, NULL); if (rv == -1) { logmsg(MSG_INFO, "Unable to decode devid %s\n", key); continue; } tempguid = devid_to_guid(curdevid); if (tempguid != NULL) (void) printf("/dev/rdsk/%s\t%s\n", diskpath, tempguid); devid_free_guid(tempguid); devid_free(curdevid); continue; } (void) printf("/dev/rdsk/%s\t/dev/rdsk/%s\n", (strstr(key, diskpath) == NULL) ? key : diskpath, livepath); } }
static void print_prop_nameval(topo_hdl_t *thp, tnode_t *node, nvlist_t *nvl) { int err; topo_type_t type; char *tstr, *propn, buf[48], *factype; nvpair_t *pv_nvp; int i; uint_t nelem; if ((pv_nvp = nvlist_next_nvpair(nvl, NULL)) == NULL) return; /* Print property name */ if ((pv_nvp = nvlist_next_nvpair(nvl, NULL)) == NULL || nvpair_name(pv_nvp) == NULL || strcmp(TOPO_PROP_VAL_NAME, nvpair_name(pv_nvp)) != 0) { (void) fprintf(stderr, "%s: malformed property name\n", g_pname); return; } else { (void) nvpair_value_string(pv_nvp, &propn); } if ((pv_nvp = nvlist_next_nvpair(nvl, pv_nvp)) == NULL || nvpair_name(pv_nvp) == NULL || strcmp(nvpair_name(pv_nvp), TOPO_PROP_VAL_TYPE) != 0 || nvpair_type(pv_nvp) != DATA_TYPE_UINT32) { (void) fprintf(stderr, "%s: malformed property type for %s\n", g_pname, propn); return; } else { (void) nvpair_value_uint32(pv_nvp, (uint32_t *)&type); } switch (type) { case TOPO_TYPE_BOOLEAN: tstr = "boolean"; break; case TOPO_TYPE_INT32: tstr = "int32"; break; case TOPO_TYPE_UINT32: tstr = "uint32"; break; case TOPO_TYPE_INT64: tstr = "int64"; break; case TOPO_TYPE_UINT64: tstr = "uint64"; break; case TOPO_TYPE_DOUBLE: tstr = "double"; break; case TOPO_TYPE_STRING: tstr = "string"; break; case TOPO_TYPE_FMRI: tstr = "fmri"; break; case TOPO_TYPE_INT32_ARRAY: tstr = "int32[]"; break; case TOPO_TYPE_UINT32_ARRAY: tstr = "uint32[]"; break; case TOPO_TYPE_INT64_ARRAY: tstr = "int64[]"; break; case TOPO_TYPE_UINT64_ARRAY: tstr = "uint64[]"; break; case TOPO_TYPE_STRING_ARRAY: tstr = "string[]"; break; case TOPO_TYPE_FMRI_ARRAY: tstr = "fmri[]"; break; default: tstr = "unknown type"; } (void) printf(" %-17s %-8s ", propn, tstr); /* * Get property value */ if (nvpair_name(pv_nvp) == NULL || (pv_nvp = nvlist_next_nvpair(nvl, pv_nvp)) == NULL) { (void) fprintf(stderr, "%s: malformed property value\n", g_pname); return; } switch (nvpair_type(pv_nvp)) { case DATA_TYPE_INT32: { int32_t val; (void) nvpair_value_int32(pv_nvp, &val); (void) printf(" %d", val); break; } case DATA_TYPE_UINT32: { uint32_t val, type; char val_str[49]; nvlist_t *fac, *rsrc = NULL; (void) nvpair_value_uint32(pv_nvp, &val); if (node == NULL || topo_node_flags(node) != TOPO_NODE_FACILITY) goto uint32_def; if (topo_node_resource(node, &rsrc, &err) != 0) goto uint32_def; if (nvlist_lookup_nvlist(rsrc, "facility", &fac) != 0) goto uint32_def; if (nvlist_lookup_string(fac, FM_FMRI_FACILITY_TYPE, &factype) != 0) goto uint32_def; nvlist_free(rsrc); rsrc = NULL; /* * Special case code to do friendlier printing of * facility node properties */ if ((strcmp(propn, TOPO_FACILITY_TYPE) == 0) && (strcmp(factype, TOPO_FAC_TYPE_SENSOR) == 0)) { topo_sensor_type_name(val, val_str, 48); (void) printf(" 0x%x (%s)", val, val_str); break; } else if ((strcmp(propn, TOPO_FACILITY_TYPE) == 0) && (strcmp(factype, TOPO_FAC_TYPE_INDICATOR) == 0)) { topo_led_type_name(val, val_str, 48); (void) printf(" 0x%x (%s)", val, val_str); break; } else if (strcmp(propn, TOPO_SENSOR_UNITS) == 0) { topo_sensor_units_name(val, val_str, 48); (void) printf(" 0x%x (%s)", val, val_str); break; } else if (strcmp(propn, TOPO_LED_MODE) == 0) { topo_led_state_name(val, val_str, 48); (void) printf(" 0x%x (%s)", val, val_str); break; } else if ((strcmp(propn, TOPO_SENSOR_STATE) == 0) && (strcmp(factype, TOPO_FAC_TYPE_SENSOR) == 0)) { if (topo_prop_get_uint32(node, TOPO_PGROUP_FACILITY, TOPO_FACILITY_TYPE, &type, &err) != 0) { goto uint32_def; } topo_sensor_state_name(type, val, val_str, 48); (void) printf(" 0x%x (%s)", val, val_str); break; } uint32_def: (void) printf(" 0x%x", val); if (rsrc != NULL) nvlist_free(rsrc); break; } case DATA_TYPE_INT64: { int64_t val; (void) nvpair_value_int64(pv_nvp, &val); (void) printf(" %lld", (longlong_t)val); break; } case DATA_TYPE_UINT64: { uint64_t val; (void) nvpair_value_uint64(pv_nvp, &val); (void) printf(" 0x%llx", (u_longlong_t)val); break; } case DATA_TYPE_DOUBLE: { double val; (void) nvpair_value_double(pv_nvp, &val); (void) printf(" %lf", (double)val); break; } case DATA_TYPE_STRING: { char *val; (void) nvpair_value_string(pv_nvp, &val); if (!opt_V && strlen(val) > 48) { (void) snprintf(buf, 48, "%s...", val); (void) printf(" %s", buf); } else { (void) printf(" %s", val); } break; } case DATA_TYPE_NVLIST: { nvlist_t *val; char *fmri; (void) nvpair_value_nvlist(pv_nvp, &val); if (topo_fmri_nvl2str(thp, val, &fmri, &err) != 0) { if (opt_V) nvlist_print(stdout, nvl); break; } if (!opt_V && strlen(fmri) > 48) { (void) snprintf(buf, 48, "%s", fmri); (void) snprintf(&buf[45], 4, "%s", DOTS); (void) printf(" %s", buf); } else { (void) printf(" %s", fmri); } topo_hdl_strfree(thp, fmri); break; } case DATA_TYPE_INT32_ARRAY: { int32_t *val; (void) nvpair_value_int32_array(pv_nvp, &val, &nelem); (void) printf(" [ "); for (i = 0; i < nelem; i++) (void) printf("%d ", val[i]); (void) printf("]"); break; } case DATA_TYPE_UINT32_ARRAY: { uint32_t *val; (void) nvpair_value_uint32_array(pv_nvp, &val, &nelem); (void) printf(" [ "); for (i = 0; i < nelem; i++) (void) printf("%u ", val[i]); (void) printf("]"); break; } case DATA_TYPE_INT64_ARRAY: { int64_t *val; (void) nvpair_value_int64_array(pv_nvp, &val, &nelem); (void) printf(" [ "); for (i = 0; i < nelem; i++) (void) printf("%lld ", val[i]); (void) printf("]"); break; } case DATA_TYPE_UINT64_ARRAY: { uint64_t *val; (void) nvpair_value_uint64_array(pv_nvp, &val, &nelem); (void) printf(" [ "); for (i = 0; i < nelem; i++) (void) printf("%llu ", val[i]); (void) printf("]"); break; } case DATA_TYPE_STRING_ARRAY: { char **val; (void) nvpair_value_string_array(pv_nvp, &val, &nelem); (void) printf(" [ "); for (i = 0; i < nelem; i++) (void) printf("\"%s\" ", val[i]); (void) printf("]"); break; } default: (void) fprintf(stderr, " unknown data type (%d)", nvpair_type(pv_nvp)); break; } (void) printf("\n"); }
/*ARGSUSED*/ static int sw_fmri_nvl2str(topo_mod_t *mod, tnode_t *node, topo_version_t version, nvlist_t *nvl, nvlist_t **out) { nvlist_t *object, *site = NULL, *anvl = NULL; char *file, *func, *token; uint8_t scheme_version; char *path, *root; nvlist_t *fmristr; size_t buflen = 0; int linevalid = 0; char *buf = NULL; ssize_t size = 0; char linebuf[32]; int64_t line; int pass; int err; if (version > TOPO_METH_NVL2STR_VERSION) return (topo_mod_seterrno(mod, EMOD_VER_NEW)); if (nvlist_lookup_uint8(nvl, FM_VERSION, &scheme_version) != 0 || scheme_version > FM_SW_SCHEME_VERSION) return (topo_mod_seterrno(mod, EMOD_FMRI_NVL)); /* Get authority, if present */ err = nvlist_lookup_nvlist(nvl, FM_FMRI_AUTHORITY, &anvl); if (err != 0 && err != ENOENT) return (topo_mod_seterrno(mod, EMOD_FMRI_NVL)); /* * The 'object' nvlist is required. It must include the path, * but the root is optional. */ if (nvlist_lookup_nvlist(nvl, FM_FMRI_SW_OBJ, &object) != 0 || !lookup_string(object, FM_FMRI_SW_OBJ_PATH, &path, B_TRUE) || !lookup_string(object, FM_FMRI_SW_OBJ_ROOT, &root, B_FALSE)) return (topo_mod_seterrno(mod, EMOD_FMRI_NVL)); /* The 'site' nvlist is optional */ file = func = token = NULL; linevalid = 0; if ((err = nvlist_lookup_nvlist(nvl, FM_FMRI_SW_SITE, &site)) == 0) { /* * Prefer 'token' to file/func/line */ if (lookup_string(site, FM_FMRI_SW_SITE_TOKEN, &token, B_FALSE) <= 0) { /* * If no token then try file, func, line - but * func and line are meaningless without file. */ if (lookup_string(site, FM_FMRI_SW_SITE_FILE, &file, B_FALSE) == 1) { (void) lookup_string(site, FM_FMRI_SW_SITE_FUNC, &func, B_FALSE); if (nvlist_lookup_int64(site, FM_FMRI_SW_SITE_LINE, &line) == 0) linevalid = 1; } } } else if (err != ENOENT) { return (topo_mod_seterrno(mod, EMOD_FMRI_NVL)); } /* On the first pass buf is NULL and size and buflen are 0 */ pass = 1; again: /* * sw://[<authority>]/ * [:root=<object.root] * :path=<object.path> * [#<fragment-identifier>] * * <fragment-identifier> is one of * * :token=<site.token> * or * :file=<site.file>[:func=<site.func>][:line=<site.line>] */ /* sw:// */ topo_fmristr_build(&size, buf, buflen, FM_FMRI_SCHEME_SW, NULL, "://"); /* authority, if any */ if (anvl != NULL) { nvpair_t *apair; char *aname, *aval; for (apair = nvlist_next_nvpair(anvl, NULL); apair != NULL; apair = nvlist_next_nvpair(anvl, apair)) { if (nvpair_type(apair) != DATA_TYPE_STRING || nvpair_value_string(apair, &aval) != 0) continue; aname = nvpair_name(apair); topo_fmristr_build(&size, buf, buflen, ":", NULL, NULL); topo_fmristr_build(&size, buf, buflen, "=", aname, aval); } } /* separating slash */ topo_fmristr_build(&size, buf, buflen, "/", NULL, NULL); /* :root=... */ if (root) { topo_fmristr_build(&size, buf, buflen, root, ":" FM_FMRI_SW_OBJ_ROOT "=", NULL); } /* :path=... */ topo_fmristr_build(&size, buf, buflen, path, ":" FM_FMRI_SW_OBJ_PATH "=", NULL); if (token) { /* #:token=... */ topo_fmristr_build(&size, buf, buflen, token, "#:" FM_FMRI_SW_SITE_TOKEN "=", NULL); } else if (file) { /* #:file=... */ topo_fmristr_build(&size, buf, buflen, file, "#:" FM_FMRI_SW_SITE_FILE "=", NULL); /* :func=... */ if (func) { topo_fmristr_build(&size, buf, buflen, func, ":" FM_FMRI_SW_SITE_FUNC "=", NULL); } /* :line=... */ if (linevalid) { if (pass == 1) (void) snprintf(linebuf, sizeof (linebuf), "%lld", line); topo_fmristr_build(&size, buf, buflen, linebuf, ":" FM_FMRI_SW_SITE_LINE "=", NULL); } } if (buf == NULL) { if ((buf = topo_mod_alloc(mod, size + 1)) == NULL) return (topo_mod_seterrno(mod, EMOD_NOMEM)); buflen = size + 1; size = 0; pass = 2; goto again; } /* * Construct the nvlist to return as the result. */ if (topo_mod_nvalloc(mod, &fmristr, NV_UNIQUE_NAME) != 0) { topo_mod_strfree(mod, buf); return (topo_mod_seterrno(mod, EMOD_NOMEM)); } if (nvlist_add_string(fmristr, "fmri-string", buf) != 0) { topo_mod_strfree(mod, buf); nvlist_free(fmristr); return (topo_mod_seterrno(mod, EMOD_NOMEM)); } topo_mod_strfree(mod, buf); *out = fmristr; return (0); }
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; } }
/* * Process profile passed down from libdevinfo. There are four types * of matching rules: * include: export a name or names matching a pattern * exclude: exclude a name or names matching a pattern * symlink: create a local symlink * map: export a device with a name different from the global zone * Note: We may consider supporting VOP_SYMLINK in non-global instances, * because it does not present any security risk. For now, the fs * instance is read only. */ static void sdev_process_profile(struct sdev_data *sdev_data, nvlist_t *profile) { nvpair_t *nvpair; char *nvname, *dname; struct sdev_node *dir, *gdir; char **pair; /* for symlinks and maps */ uint_t nelem; int rv; gdir = sdev_origins->sdev_root; /* root of global /dev */ dir = sdev_data->sdev_root; /* root of current instance */ ASSERT(profile); /* process nvpairs in the list */ nvpair = NULL; while (nvpair = nvlist_next_nvpair(profile, nvpair)) { nvname = nvpair_name(nvpair); ASSERT(nvname != NULL); if (strcmp(nvname, SDEV_NVNAME_INCLUDE) == 0) { rv = nvpair_value_string(nvpair, &dname); if (rv != 0) { cmn_err(CE_WARN, sdev_nvp_val_err, rv, nvpair_name(nvpair)); break; } process_rule(dir, gdir, dname, NULL, PROFILE_TYPE_INCLUDE); } else if (strcmp(nvname, SDEV_NVNAME_EXCLUDE) == 0) { rv = nvpair_value_string(nvpair, &dname); if (rv != 0) { cmn_err(CE_WARN, sdev_nvp_val_err, rv, nvpair_name(nvpair)); break; } process_rule(dir, gdir, dname, NULL, PROFILE_TYPE_EXCLUDE); } else if (strcmp(nvname, SDEV_NVNAME_SYMLINK) == 0) { rv = nvpair_value_string_array(nvpair, &pair, &nelem); if (rv != 0) { cmn_err(CE_WARN, sdev_nvp_val_err, rv, nvpair_name(nvpair)); break; } ASSERT(nelem == 2); process_rule(dir, gdir, pair[0], pair[1], PROFILE_TYPE_SYMLINK); } else if (strcmp(nvname, SDEV_NVNAME_MAP) == 0) { rv = nvpair_value_string_array(nvpair, &pair, &nelem); if (rv != 0) { cmn_err(CE_WARN, sdev_nvp_val_err, rv, nvpair_name(nvpair)); break; } process_rule(dir, gdir, pair[1], pair[0], PROFILE_TYPE_MAP); } else if (strcmp(nvname, SDEV_NVNAME_MOUNTPT) != 0) { cmn_err(CE_WARN, "sdev_process_profile: invalid " "nvpair %s\n", nvname); } } }
/* * Convert the nvpair [nvp] to a string which is added to the environment * of the child process. * Return 0 on success, -1 on error. * * FIXME: Refactor with cmd/zpool/zpool_main.c:zpool_do_events_nvprint()? */ static void _zed_event_add_nvpair(uint64_t eid, zed_strings_t *zsp, nvpair_t *nvp) { const char *name; data_type_t type; const char *prefix = ZEVENT_VAR_PREFIX; boolean_t b; double d; uint8_t i8; uint16_t i16; uint32_t i32; uint64_t i64; char *str; assert(zsp != NULL); assert(nvp != NULL); name = nvpair_name(nvp); type = nvpair_type(nvp); switch (type) { case DATA_TYPE_BOOLEAN: _zed_event_add_var(eid, zsp, prefix, name, "%s", "1"); break; case DATA_TYPE_BOOLEAN_VALUE: (void) nvpair_value_boolean_value(nvp, &b); _zed_event_add_var(eid, zsp, prefix, name, "%s", b ? "1" : "0"); break; case DATA_TYPE_BYTE: (void) nvpair_value_byte(nvp, &i8); _zed_event_add_var(eid, zsp, prefix, name, "%d", i8); break; case DATA_TYPE_INT8: (void) nvpair_value_int8(nvp, (int8_t *) &i8); _zed_event_add_var(eid, zsp, prefix, name, "%d", i8); break; case DATA_TYPE_UINT8: (void) nvpair_value_uint8(nvp, &i8); _zed_event_add_var(eid, zsp, prefix, name, "%u", i8); break; case DATA_TYPE_INT16: (void) nvpair_value_int16(nvp, (int16_t *) &i16); _zed_event_add_var(eid, zsp, prefix, name, "%d", i16); break; case DATA_TYPE_UINT16: (void) nvpair_value_uint16(nvp, &i16); _zed_event_add_var(eid, zsp, prefix, name, "%u", i16); break; case DATA_TYPE_INT32: (void) nvpair_value_int32(nvp, (int32_t *) &i32); _zed_event_add_var(eid, zsp, prefix, name, "%d", i32); break; case DATA_TYPE_UINT32: (void) nvpair_value_uint32(nvp, &i32); _zed_event_add_var(eid, zsp, prefix, name, "%u", i32); break; case DATA_TYPE_INT64: (void) nvpair_value_int64(nvp, (int64_t *) &i64); _zed_event_add_var(eid, zsp, prefix, name, "%lld", (longlong_t) i64); break; case DATA_TYPE_UINT64: (void) nvpair_value_uint64(nvp, &i64); _zed_event_add_var(eid, zsp, prefix, name, (_zed_event_value_is_hex(name) ? "0x%.16llX" : "%llu"), (u_longlong_t) i64); /* * shadow readable strings for vdev state pairs */ if (strcmp(name, FM_EREPORT_PAYLOAD_ZFS_VDEV_STATE) == 0 || strcmp(name, FM_EREPORT_PAYLOAD_ZFS_VDEV_LASTSTATE) == 0) { char alt[32]; (void) snprintf(alt, sizeof (alt), "%s_str", name); _zed_event_add_var(eid, zsp, prefix, alt, "%s", zpool_state_to_name(i64, VDEV_AUX_NONE)); } break; case DATA_TYPE_DOUBLE: (void) nvpair_value_double(nvp, &d); _zed_event_add_var(eid, zsp, prefix, name, "%g", d); break; case DATA_TYPE_HRTIME: (void) nvpair_value_hrtime(nvp, (hrtime_t *) &i64); _zed_event_add_var(eid, zsp, prefix, name, "%llu", (u_longlong_t) i64); break; case DATA_TYPE_NVLIST: _zed_event_add_var(eid, zsp, prefix, name, "%s", "_NOT_IMPLEMENTED_"); /* FIXME */ break; case DATA_TYPE_STRING: (void) nvpair_value_string(nvp, &str); _zed_event_add_var(eid, zsp, prefix, name, "%s", (str ? str : "<NULL>")); break; case DATA_TYPE_BOOLEAN_ARRAY: _zed_event_add_var(eid, zsp, prefix, name, "%s", "_NOT_IMPLEMENTED_"); /* FIXME */ break; case DATA_TYPE_BYTE_ARRAY: _zed_event_add_var(eid, zsp, prefix, name, "%s", "_NOT_IMPLEMENTED_"); /* FIXME */ break; case DATA_TYPE_INT8_ARRAY: _zed_event_add_int8_array(eid, zsp, prefix, nvp); break; case DATA_TYPE_UINT8_ARRAY: _zed_event_add_uint8_array(eid, zsp, prefix, nvp); break; case DATA_TYPE_INT16_ARRAY: _zed_event_add_int16_array(eid, zsp, prefix, nvp); break; case DATA_TYPE_UINT16_ARRAY: _zed_event_add_uint16_array(eid, zsp, prefix, nvp); break; case DATA_TYPE_INT32_ARRAY: _zed_event_add_int32_array(eid, zsp, prefix, nvp); break; case DATA_TYPE_UINT32_ARRAY: _zed_event_add_uint32_array(eid, zsp, prefix, nvp); break; case DATA_TYPE_INT64_ARRAY: _zed_event_add_int64_array(eid, zsp, prefix, nvp); break; case DATA_TYPE_UINT64_ARRAY: _zed_event_add_uint64_array(eid, zsp, prefix, nvp); break; case DATA_TYPE_STRING_ARRAY: _zed_event_add_string_array(eid, zsp, prefix, nvp); break; case DATA_TYPE_NVLIST_ARRAY: _zed_event_add_var(eid, zsp, prefix, name, "%s", "_NOT_IMPLEMENTED_"); /* FIXME */ break; default: errno = EINVAL; zed_log_msg(LOG_WARNING, "Failed to convert nvpair \"%s\" for eid=%llu: " "Unrecognized type=%u", name, eid, (unsigned int) type); break; } }
/* * 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); } }
/* * Returns 'in use' details, if found, about a specific dev_name, * based on the caller(who). It is important to note that it is possible * for there to be more than one 'in use' statistic regarding a dev_name. * The **msg parameter returns a list of 'in use' details. This message * is formatted via gettext(). */ int dm_inuse(char *dev_name, char **msg, dm_who_type_t who, int *errp) { nvlist_t *dev_stats = NULL; char *by, *data; nvpair_t *nvwhat = NULL; nvpair_t *nvdesc = NULL; int found = 0; int err; char *dname = NULL; *errp = 0; *msg = NULL; /* * If the user doesn't want to do in use checking, return. */ if (NOINUSE_SET) return (0); dname = getfullblkname(dev_name); /* * If we cannot find the block name, we cannot check the device * for in use statistics. So, return found, which is == 0. */ if (dname == NULL || *dname == '\0') { return (found); } /* * Slice stats for swap devices are only returned if mounted * (e.g. /tmp). Other devices or files being used for swap * are ignored, so we add a special check here to use swapctl(2) * to perform in-use checking. */ if (ANY_ZPOOL_USE(who) && (err = dm_inuse_swap(dname, errp))) { /* on error, dm_inuse_swap sets errp */ if (err < 0) { free(dname); return (err); } /* simulate a mounted swap device */ (void) build_usage_string(dname, DM_USE_MOUNT, "swap", msg, &found, errp); /* if this fails, dm_get_usage_string changed */ ASSERT(found == 1); free(dname); return (found); } dm_get_slice_stats(dname, &dev_stats, errp); if (dev_stats == NULL) { /* * If there is an error, but it isn't a no device found error * return the error as recorded. Otherwise, with a full * block name, we might not be able to get the slice * associated, and will get an ENODEV error. For example, * an SVM metadevice will return a value from getfullblkname() * but libdiskmgt won't be able to find this device for * statistics gathering. This is expected and we should not * report errnoneous errors. */ if (*errp) { if (*errp == ENODEV) { *errp = 0; } } free(dname); return (found); } for (;;) { nvwhat = nvlist_next_nvpair(dev_stats, nvdesc); nvdesc = nvlist_next_nvpair(dev_stats, nvwhat); /* * End of the list found. */ if (nvwhat == NULL || nvdesc == NULL) { break; } /* * Otherwise, we check to see if this client(who) cares * about this in use scenario */ ASSERT(strcmp(nvpair_name(nvwhat), DM_USED_BY) == 0); ASSERT(strcmp(nvpair_name(nvdesc), DM_USED_NAME) == 0); /* * If we error getting the string value continue on * to the next pair(if there is one) */ if (nvpair_value_string(nvwhat, &by)) { continue; } if (nvpair_value_string(nvdesc, &data)) { continue; } switch (who) { case DM_WHO_MKFS: /* * mkfs is not in use for these cases. * All others are in use. */ if (strcmp(by, DM_USE_LU) == 0 || strcmp(by, DM_USE_FS) == 0 || strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0) { break; } if (build_usage_string(dname, by, data, msg, &found, errp) != 0) { if (*errp) { goto out; } } break; case DM_WHO_SWAP: /* * Not in use for this. */ if (strcmp(by, DM_USE_DUMP) == 0 || strcmp(by, DM_USE_FS) == 0 || strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0) { break; } if (strcmp(by, DM_USE_LU) == 0 && strcmp(data, "-") == 0) { break; } if (strcmp(by, DM_USE_VFSTAB) == 0 && strcmp(data, "") == 0) { break; } if (build_usage_string(dname, by, data, msg, &found, errp) != 0) { if (*errp) { goto out; } } break; case DM_WHO_DUMP: /* * Not in use for this. */ if ((strcmp(by, DM_USE_MOUNT) == 0 && strcmp(data, "swap") == 0) || strcmp(by, DM_USE_DUMP) == 0 || strcmp(by, DM_USE_FS) == 0 || strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0) { break; } if (build_usage_string(dname, by, data, msg, &found, errp)) { if (*errp) { goto out; } } break; case DM_WHO_FORMAT: if (strcmp(by, DM_USE_FS) == 0 || strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0) break; if (build_usage_string(dname, by, data, msg, &found, errp) != 0) { if (*errp) { goto out; } } break; case DM_WHO_ZPOOL_FORCE: if (strcmp(by, DM_USE_FS) == 0 || strcmp(by, DM_USE_EXPORTED_ZPOOL) == 0) break; /* FALLTHROUGH */ case DM_WHO_ZPOOL: if (build_usage_string(dname, by, data, msg, &found, errp) != 0) { if (*errp) goto out; } break; case DM_WHO_ZPOOL_SPARE: if (strcmp(by, DM_USE_SPARE_ZPOOL) != 0) { if (build_usage_string(dname, by, data, msg, &found, errp) != 0) { if (*errp) goto out; } } break; default: /* * nothing found in use for this client * of libdiskmgt. Default is 'not in use'. */ break; } } out: if (dname != NULL) free(dname); if (dev_stats != NULL) nvlist_free(dev_stats); return (found); }