int zpool_get_prop(zpool_handle_t *zhp, zpool_prop_t prop, char *propbuf, size_t proplen, zfs_source_t *srctype) { uint64_t value; char msg[1024], *strvalue; nvlist_t *nvp; zfs_source_t src = ZFS_SRC_NONE; (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, "cannot get property '%s'"), zpool_prop_to_name(prop)); if (zpool_get_version(zhp) < ZFS_VERSION_BOOTFS) { zfs_error_aux(zhp->zpool_hdl, dgettext(TEXT_DOMAIN, "pool must be " "upgraded to support pool properties")); return (zfs_error(zhp->zpool_hdl, EZFS_BADVERSION, msg)); } if (zhp->zpool_props == NULL && zpool_get_all_props(zhp)) return (zfs_error(zhp->zpool_hdl, EZFS_POOLPROPS, msg)); /* * the "name" property is special cased */ if (!zfs_prop_valid_for_type(prop, ZFS_TYPE_POOL) && prop != ZFS_PROP_NAME) return (-1); switch (prop) { case ZFS_PROP_NAME: (void) strlcpy(propbuf, zhp->zpool_name, proplen); break; case ZFS_PROP_BOOTFS: if (nvlist_lookup_nvlist(zhp->zpool_props, zpool_prop_to_name(prop), &nvp) != 0) { strvalue = (char *)zfs_prop_default_string(prop); if (strvalue == NULL) strvalue = "-"; src = ZFS_SRC_DEFAULT; } else { VERIFY(nvlist_lookup_uint64(nvp, ZFS_PROP_SOURCE, &value) == 0); src = value; VERIFY(nvlist_lookup_string(nvp, ZFS_PROP_VALUE, &strvalue) == 0); if (strlen(strvalue) >= proplen) return (-1); } (void) strcpy(propbuf, strvalue); break; default: return (-1); } if (srctype) *srctype = src; return (0); }
int zpool_set_prop(zpool_handle_t *zhp, const char *propname, const char *propval) { zfs_cmd_t zc = { 0 }; int ret = -1; char errbuf[1024]; nvlist_t *nvl = NULL; nvlist_t *realprops; (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN, "cannot set property for '%s'"), zhp->zpool_name); if (zpool_get_version(zhp) < ZFS_VERSION_BOOTFS) { zfs_error_aux(zhp->zpool_hdl, dgettext(TEXT_DOMAIN, "pool must be " "upgraded to support pool properties")); return (zfs_error(zhp->zpool_hdl, EZFS_BADVERSION, errbuf)); } if (zhp->zpool_props == NULL && zpool_get_all_props(zhp)) return (zfs_error(zhp->zpool_hdl, EZFS_POOLPROPS, errbuf)); if (nvlist_alloc(&nvl, NV_UNIQUE_NAME, 0) != 0 || nvlist_add_string(nvl, propname, propval) != 0) { return (no_memory(zhp->zpool_hdl)); } if ((realprops = zfs_validate_properties(zhp->zpool_hdl, ZFS_TYPE_POOL, zhp->zpool_name, nvl, 0, NULL, errbuf)) == NULL) { nvlist_free(nvl); return (-1); } nvlist_free(nvl); nvl = realprops; /* * Execute the corresponding ioctl() to set this property. */ (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); if (zcmd_write_src_nvlist(zhp->zpool_hdl, &zc, nvl, NULL) != 0) return (-1); ret = ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_POOL_SET_PROPS, &zc); zcmd_free_nvlists(&zc); if (ret) (void) zpool_standard_error(zhp->zpool_hdl, errno, errbuf); return (ret); }
/* * Add the given vdevs to the pool. The caller must have already performed the * necessary verification to ensure that the vdev specification is well-formed. */ int zpool_add(zpool_handle_t *zhp, nvlist_t *nvroot) { char *packed; size_t len; zfs_cmd_t zc; int ret; libzfs_handle_t *hdl = zhp->zpool_hdl; char msg[1024]; nvlist_t **spares; uint_t nspares; (void) snprintf(msg, sizeof (msg), dgettext(TEXT_DOMAIN, "cannot add to '%s'"), zhp->zpool_name); if (zpool_get_version(zhp) < ZFS_VERSION_SPARES && nvlist_lookup_nvlist_array(nvroot, ZPOOL_CONFIG_SPARES, &spares, &nspares) == 0) { zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be " "upgraded to add hot spares")); return (zfs_error(hdl, EZFS_BADVERSION, msg)); } verify(nvlist_size(nvroot, &len, NV_ENCODE_NATIVE) == 0); if ((packed = zfs_alloc(zhp->zpool_hdl, len)) == NULL) return (-1); verify(nvlist_pack(nvroot, &packed, &len, NV_ENCODE_NATIVE, 0) == 0); (void) strlcpy(zc.zc_name, zhp->zpool_name, sizeof (zc.zc_name)); zc.zc_config_src = (uint64_t)(uintptr_t)packed; zc.zc_config_src_size = len; if (ioctl(zhp->zpool_hdl->libzfs_fd, ZFS_IOC_VDEV_ADD, &zc) != 0) { switch (errno) { case EBUSY: /* * This can happen if the user has specified the same * device multiple times. We can't reliably detect this * until we try to add it and see we already have a * label. */ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "one or more vdevs refer to the same device")); (void) zfs_error(hdl, EZFS_BADDEV, msg); break; case EOVERFLOW: /* * This occurrs when one of the devices is below * SPA_MINDEVSIZE. Unfortunately, we can't detect which * device was the problem device since there's no * reliable way to determine device size from userland. */ { char buf[64]; zfs_nicenum(SPA_MINDEVSIZE, buf, sizeof (buf)); zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "device is less than the minimum " "size (%s)"), buf); } (void) zfs_error(hdl, EZFS_BADDEV, msg); break; case ENOTSUP: zfs_error_aux(hdl, dgettext(TEXT_DOMAIN, "pool must be upgraded to add raidz2 vdevs")); (void) zfs_error(hdl, EZFS_BADVERSION, msg); break; default: (void) zpool_standard_error(hdl, errno, msg); } ret = -1; } else { ret = 0; } free(packed); return (ret); }