libzfs_dataset.c revision 30925561c223021e91d15899cbe75f80e54d8889
fa9e4066f08beec538e775443c5be79dd423fcabahrens * CDDL HEADER START
fa9e4066f08beec538e775443c5be79dd423fcabahrens * The contents of this file are subject to the terms of the
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * Common Development and Distribution License (the "License").
ea8dc4b6d2251b437950c0056bc626b311c73c27eschrock * You may not use this file except in compliance with the License.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
fa9e4066f08beec538e775443c5be79dd423fcabahrens * See the License for the specific language governing permissions
fa9e4066f08beec538e775443c5be79dd423fcabahrens * and limitations under the License.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * When distributing Covered Code, include this CDDL HEADER in each
fa9e4066f08beec538e775443c5be79dd423fcabahrens * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * If applicable, add the following below this CDDL HEADER, with the
fa9e4066f08beec538e775443c5be79dd423fcabahrens * fields enclosed by brackets "[]" replaced with your own identifying
fa9e4066f08beec538e775443c5be79dd423fcabahrens * information: Portions Copyright [yyyy] [name of copyright owner]
fa9e4066f08beec538e775443c5be79dd423fcabahrens * CDDL HEADER END
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Copyright (c) 2013, Joyent, Inc. All rights reserved.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Copyright (c) 2011, 2014 by Delphix. All rights reserved.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Copyright (c) 2012 DEY Storage Systems, Inc. All rights reserved.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Copyright (c) 2013 Martin Matuska. All rights reserved.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Copyright (c) 2013 Steven Hartland. All rights reserved.
fa9e4066f08beec538e775443c5be79dd423fcabahrens * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
99653d4ee642c6528e88224f12409a5f23060994eschrockstatic int userquota_propname_decode(const char *propname, boolean_t zoned,
99653d4ee642c6528e88224f12409a5f23060994eschrock zfs_userquota_prop_t *typep, char *domain, int domainlen, uint64_t *ridp);
99653d4ee642c6528e88224f12409a5f23060994eschrock * Given a single type (not a mask of types), return the type in a human
99653d4ee642c6528e88224f12409a5f23060994eschrock * readable form.
99653d4ee642c6528e88224f12409a5f23060994eschrockconst char *
99653d4ee642c6528e88224f12409a5f23060994eschrock * Given a path and mask of ZFS types, return a string describing this dataset.
99653d4ee642c6528e88224f12409a5f23060994eschrock * This is used when we fail to open a dataset and we cannot get an exact type.
99653d4ee642c6528e88224f12409a5f23060994eschrock * We guess what the type would have been based on the path and the mask of
99653d4ee642c6528e88224f12409a5f23060994eschrock * acceptable types.
99653d4ee642c6528e88224f12409a5f23060994eschrockstatic const char *
99653d4ee642c6528e88224f12409a5f23060994eschrock * When given a single type, always report the exact type.
99653d4ee642c6528e88224f12409a5f23060994eschrock * The user is requesting more than one type of dataset. If this is the
99653d4ee642c6528e88224f12409a5f23060994eschrock * case, consult the path itself. If we're looking for a snapshot, and
99653d4ee642c6528e88224f12409a5f23060994eschrock * a '@' is found, then report it as "snapshot". Otherwise, remove the
99653d4ee642c6528e88224f12409a5f23060994eschrock * snapshot attribute and try again.
99653d4ee642c6528e88224f12409a5f23060994eschrock return (path_to_str(path, types & ~ZFS_TYPE_SNAPSHOT));
99653d4ee642c6528e88224f12409a5f23060994eschrock * The user has requested either filesystems or volumes.
99653d4ee642c6528e88224f12409a5f23060994eschrock * We have no way of knowing a priori what type this would be, so always
99653d4ee642c6528e88224f12409a5f23060994eschrock * report it as "filesystem" or "volume", our two primitive types.
99653d4ee642c6528e88224f12409a5f23060994eschrock * Validate a ZFS path. This is used even before trying to open the dataset, to
f3861e1a2ceec23a5b699c24d814b7775a9e0b52ahl * provide a more meaningful error message. We call zfs_error_aux() to
99653d4ee642c6528e88224f12409a5f23060994eschrock * explain exactly why the name was not valid.
da6c28aaf62fa55f0fdb8004aa40f88f23bf53f0amwzfs_validate_name(libzfs_handle_t *hdl, const char *path, int type,
6e27f86863a47869e7b2514d7445d3ea6fc6cf4aSam Falkner "name is too long"));
99653d4ee642c6528e88224f12409a5f23060994eschrock "leading slash in name"));
99653d4ee642c6528e88224f12409a5f23060994eschrock "empty component in name"));
f3861e1a2ceec23a5b699c24d814b7775a9e0b52ahl "trailing slash in name"));
b1b8ab34de515a5e83206da22c3d7e563241b021lling "multiple '@' delimiters in name"));
b7661ccca92e6bf5160f4d5d2601efaeaa1f5161mmusante "pool doesn't begin with a letter"));
8488aeb5df27784d479c16cde06a9e25cd9a1152taylor "name is reserved"));
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks "reserved disk name"));
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks return (0);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks if (!(type & ZFS_TYPE_SNAPSHOT) && strchr(path, '@') != NULL) {
2f8aaab38e6371ad39ed90a1211ba8921acbb4d5eschrock "snapshot delimiter '@' in filesystem name"));
fa94a07fd0519b8abfd871ad8fe60e6bebe1e2bbbrendan return (0);
e7cbe64f7a72dae5cb44f100db60ca88f3313c65gw if (type == ZFS_TYPE_SNAPSHOT && strchr(path, '@') == NULL) {
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw "missing '@' delimiter in snapshot name"));
15e6edf145a9c2bb0e0272cf8debe823bb97529bgw return (0);
842727c2f41f01b380de4f5e787d905702870f23Chris Kirby return (-1);
1195e687f1c03c8d57417b5999578922e20a3554Mark J Musante return (zfs_validate_name(NULL, name, type, B_FALSE));
99653d4ee642c6528e88224f12409a5f23060994eschrock * This function takes the raw DSL properties, and filters out the user-defined
99653d4ee642c6528e88224f12409a5f23060994eschrock * properties into a separate nvlist.
99653d4ee642c6528e88224f12409a5f23060994eschrockprocess_user_props(zfs_handle_t *zhp, nvlist_t *props)
99653d4ee642c6528e88224f12409a5f23060994eschrock while ((elem = nvlist_next_nvpair(props, elem)) != NULL) {
99653d4ee642c6528e88224f12409a5f23060994eschrock if (nvlist_add_nvlist(nvl, nvpair_name(elem), propval) != 0) {
99653d4ee642c6528e88224f12409a5f23060994eschrockzpool_add_handle(zfs_handle_t *zhp, const char *pool_name)
99653d4ee642c6528e88224f12409a5f23060994eschrock if ((zph = zpool_open_canfail(hdl, pool_name)) != NULL) {
99653d4ee642c6528e88224f12409a5f23060994eschrockzpool_find_handle(zfs_handle_t *zhp, const char *pool_name, int len)
99653d4ee642c6528e88224f12409a5f23060994eschrock * Returns a handle to the pool that contains the provided dataset.
99653d4ee642c6528e88224f12409a5f23060994eschrock * If a handle to that pool already exists then that handle is returned.
99653d4ee642c6528e88224f12409a5f23060994eschrock * Otherwise, a new handle is created and added to the list of handles.
99653d4ee642c6528e88224f12409a5f23060994eschrock zpool_handle_t *next, *zph = hdl->libzfs_pool_handles;
99653d4ee642c6528e88224f12409a5f23060994eschrock * Utility function to gather stats (objset and zpl) for the given object.
ece3d9b3bacef51a5f34d993935eedbb7bb87059lling (void) strlcpy(zc->zc_name, zhp->zfs_name, sizeof (zc->zc_name));
99653d4ee642c6528e88224f12409a5f23060994eschrock while (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_STATS, zc) != 0) {
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (-1);
99653d4ee642c6528e88224f12409a5f23060994eschrock return (0);
99653d4ee642c6528e88224f12409a5f23060994eschrock * Utility function to get the received properties of the given object.
99653d4ee642c6528e88224f12409a5f23060994eschrock return (-1);
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
99653d4ee642c6528e88224f12409a5f23060994eschrock while (ioctl(hdl->libzfs_fd, ZFS_IOC_OBJSET_RECVD_PROPS, &zc) != 0) {
99653d4ee642c6528e88224f12409a5f23060994eschrock return (-1);
99653d4ee642c6528e88224f12409a5f23060994eschrock return (-1);
99653d4ee642c6528e88224f12409a5f23060994eschrock err = zcmd_read_dst_nvlist(zhp->zfs_hdl, &zc, &recvdprops);
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks return (-1);
b7661ccca92e6bf5160f4d5d2601efaeaa1f5161mmusante return (0);
54d692b75b7a6f90ce7787309da5451f7458e66aGeorge Wilson zhp->zfs_dmustats = zc->zc_objset_stats; /* structure assignment */
99653d4ee642c6528e88224f12409a5f23060994eschrock if (zcmd_read_dst_nvlist(zhp->zfs_hdl, zc, &allprops) != 0) {
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson return (-1);
99653d4ee642c6528e88224f12409a5f23060994eschrock * XXX Why do we store the user props separately, in addition to
99653d4ee642c6528e88224f12409a5f23060994eschrock * storing them in zfs_props?
fa9e4066f08beec538e775443c5be79dd423fcabahrens if ((userprops = process_user_props(zhp, allprops)) == NULL) {
ece3d9b3bacef51a5f34d993935eedbb7bb87059lling return (-1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens return (0);
99653d4ee642c6528e88224f12409a5f23060994eschrock if (zcmd_alloc_dst_nvlist(zhp->zfs_hdl, &zc, 0) != 0)
99653d4ee642c6528e88224f12409a5f23060994eschrock return (-1);
99653d4ee642c6528e88224f12409a5f23060994eschrock * Refresh the properties currently stored in the handle.
43afaaa8b73f73af765f4fa90f39a0f86cb8a364Eric Schrock * Makes a handle from the given dataset name. Used by zfs_open() and
99653d4ee642c6528e88224f12409a5f23060994eschrock * zfs_iter_* to create child handles on the fly.
99653d4ee642c6528e88224f12409a5f23060994eschrockmake_dataset_handle_common(zfs_handle_t *zhp, zfs_cmd_t *zc)
99653d4ee642c6528e88224f12409a5f23060994eschrock return (-1);
99653d4ee642c6528e88224f12409a5f23060994eschrock * We've managed to open the dataset and gather statistics. Determine
99653d4ee642c6528e88224f12409a5f23060994eschrock * the high-level type.
54d692b75b7a6f90ce7787309da5451f7458e66aGeorge Wilson abort(); /* we should never see any other types */
54d692b75b7a6f90ce7787309da5451f7458e66aGeorge Wilson if ((zhp->zpool_hdl = zpool_handle(zhp)) == NULL)
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks return (-1);
99653d4ee642c6528e88224f12409a5f23060994eschrock return (0);
99653d4ee642c6528e88224f12409a5f23060994eschrockmake_dataset_handle(libzfs_handle_t *hdl, const char *path)
fa9e4066f08beec538e775443c5be79dd423fcabahrens zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1);
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) strlcpy(zhp->zfs_name, path, sizeof (zhp->zfs_name));
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrockmake_dataset_handle_zc(libzfs_handle_t *hdl, zfs_cmd_t *zc)
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1);
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock (void) strlcpy(zhp->zfs_name, zc->zc_name, sizeof (zhp->zfs_name));
99653d4ee642c6528e88224f12409a5f23060994eschrock zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1);
fa9e4066f08beec538e775443c5be79dd423fcabahrens if (nvlist_dup(zhp_orig->zfs_props, &zhp->zfs_props, 0) != 0) {
99653d4ee642c6528e88224f12409a5f23060994eschrock if (err != 0) {
99653d4ee642c6528e88224f12409a5f23060994eschrockmake_bookmark_handle(zfs_handle_t *parent, const char *path,
99653d4ee642c6528e88224f12409a5f23060994eschrock zfs_handle_t *zhp = calloc(sizeof (zfs_handle_t), 1);
91ebeef555ce7f899b6270a3c2df47b51f7ad59aahrens /* Fill in the name. */
99653d4ee642c6528e88224f12409a5f23060994eschrock (void) strlcpy(zhp->zfs_name, path, sizeof (zhp->zfs_name));
99653d4ee642c6528e88224f12409a5f23060994eschrock /* Set the property lists. */
99653d4ee642c6528e88224f12409a5f23060994eschrock if (nvlist_dup(bmark_props, &zhp->zfs_props, 0) != 0) {
99653d4ee642c6528e88224f12409a5f23060994eschrock /* Set the types. */
99653d4ee642c6528e88224f12409a5f23060994eschrock * Opens the given snapshot, filesystem, or volume. The 'types'
99653d4ee642c6528e88224f12409a5f23060994eschrock * argument is a mask of acceptable types. The function will print an
99653d4ee642c6528e88224f12409a5f23060994eschrock * appropriate error message and return NULL if it can't be opened.
99653d4ee642c6528e88224f12409a5f23060994eschrockzfs_open(libzfs_handle_t *hdl, const char *path, int types)
d5b5bb256c576fe5ef26e0795bd40abe77f93246Rich Morris dgettext(TEXT_DOMAIN, "cannot open '%s'"), path);
d5b5bb256c576fe5ef26e0795bd40abe77f93246Rich Morris * Validate the name before we even try to open it.
5aba80db367b061758a29154d304977d00d8e4f4ck if (!zfs_validate_name(hdl, path, ZFS_TYPE_DATASET, B_FALSE)) {
5aba80db367b061758a29154d304977d00d8e4f4ck "invalid dataset name"));
5aba80db367b061758a29154d304977d00d8e4f4ck * Try to get stats for the dataset, which will tell us if it exists.
5aba80db367b061758a29154d304977d00d8e4f4ck * Release a ZFS handle. Nothing to do but free the associated memory.
5aba80db367b061758a29154d304977d00d8e4f4cktypedef struct mnttab_node {
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrocklibzfs_mnttab_cache_compare(const void *arg1, const void *arg2)
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock rv = strcmp(mtn1->mtn_mt.mnt_special, mtn2->mtn_mt.mnt_special);
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock return (0);
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock assert(avl_numnodes(&hdl->libzfs_mnttab_cache) == 0);
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock avl_create(&hdl->libzfs_mnttab_cache, libzfs_mnttab_cache_compare,
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock sizeof (mnttab_node_t), offsetof(mnttab_node_t, mtn_node));
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock while (getmntent(hdl->libzfs_mnttab, &entry) == 0) {
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock mtn->mtn_mt.mnt_special = zfs_strdup(hdl, entry.mnt_special);
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock mtn->mtn_mt.mnt_mountp = zfs_strdup(hdl, entry.mnt_mountp);
a2eea2e101e6a163a537dcc6d4e3c4da2a0ea5b2ahrens mtn->mtn_mt.mnt_fstype = zfs_strdup(hdl, entry.mnt_fstype);
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock mtn->mtn_mt.mnt_mntopts = zfs_strdup(hdl, entry.mnt_mntopts);
990b4856d0eaada6f8140335733a1b1771ed2746lling while (mtn = avl_destroy_nodes(&hdl->libzfs_mnttab_cache, &cookie)) {
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrocklibzfs_mnttab_cache(libzfs_handle_t *hdl, boolean_t enable)
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrocklibzfs_mnttab_find(libzfs_handle_t *hdl, const char *fsname,
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock return (0);
e9dbad6f263d5570ed7ff5443ec5b958af8c24d7eschrock mtn = avl_find(&hdl->libzfs_mnttab_cache, &find, NULL);
b1b8ab34de515a5e83206da22c3d7e563241b021lling return (0);
990b4856d0eaada6f8140335733a1b1771ed2746llinglibzfs_mnttab_add(libzfs_handle_t *hdl, const char *special,
990b4856d0eaada6f8140335733a1b1771ed2746lling mtn->mtn_mt.mnt_fstype = zfs_strdup(hdl, MNTTYPE_ZFS);
990b4856d0eaada6f8140335733a1b1771ed2746llinglibzfs_mnttab_remove(libzfs_handle_t *hdl, const char *fsname)
b1b8ab34de515a5e83206da22c3d7e563241b021lling if (ret = avl_find(&hdl->libzfs_mnttab_cache, (void *)&find, NULL)) {
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson return (-1);
b1b8ab34de515a5e83206da22c3d7e563241b021lling * The choice of reservation property depends on the SPA version.
b1b8ab34de515a5e83206da22c3d7e563241b021llingzfs_which_resv_prop(zfs_handle_t *zhp, zfs_prop_t *resv_prop)
b1b8ab34de515a5e83206da22c3d7e563241b021lling return (-1);
990b4856d0eaada6f8140335733a1b1771ed2746lling return (0);
b1b8ab34de515a5e83206da22c3d7e563241b021lling * Given an nvlist of properties to set, validates that they are correct, and
b1b8ab34de515a5e83206da22c3d7e563241b021lling * parses any numeric properties (index, boolean, etc) if they are specified as
b1b8ab34de515a5e83206da22c3d7e563241b021llingzfs_valid_proplist(libzfs_handle_t *hdl, zfs_type_t type, nvlist_t *nvl,
b1b8ab34de515a5e83206da22c3d7e563241b021lling uint64_t zoned, zfs_handle_t *zhp, const char *errbuf)
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson * Make sure this property is valid and applies to this type.
990b4856d0eaada6f8140335733a1b1771ed2746lling while ((elem = nvlist_next_nvpair(nvl, elem)) != NULL) {
b1b8ab34de515a5e83206da22c3d7e563241b021lling * This is a user property: make sure it's a
b1b8ab34de515a5e83206da22c3d7e563241b021lling * string, and that it's less than ZAP_MAXNAMELEN.
b1b8ab34de515a5e83206da22c3d7e563241b021lling "property name '%s' is too long"),
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson if (nvlist_add_string(ret, propname, strval) != 0) {
b1b8ab34de515a5e83206da22c3d7e563241b021lling * Currently, only user properties can be modified on
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson * snapshots.
b1b8ab34de515a5e83206da22c3d7e563241b021lling "this property can not be modified for snapshots"));
b1b8ab34de515a5e83206da22c3d7e563241b021lling if (prop == ZPROP_INVAL && zfs_prop_userquota(propname)) {
b1b8ab34de515a5e83206da22c3d7e563241b021lling "'%s' has an invalid user/group name"),
b1b8ab34de515a5e83206da22c3d7e563241b021lling if (intval == 0) {
b1b8ab34de515a5e83206da22c3d7e563241b021lling "use 'none' to disable "
b1b8ab34de515a5e83206da22c3d7e563241b021lling * Encode the prop name as
b1b8ab34de515a5e83206da22c3d7e563241b021lling * userquota@<hex-rid>-domain, to make it easy
b1b8ab34de515a5e83206da22c3d7e563241b021lling * for the kernel to decode.
92241e0b80813d0b83c08e730a29b9d1831794fcTom Erickson } else if (prop == ZPROP_INVAL && zfs_prop_written(propname)) {
b1b8ab34de515a5e83206da22c3d7e563241b021lling "'%s' is readonly"),
990b4856d0eaada6f8140335733a1b1771ed2746lling * Perform some additional checks for specific properties.
990b4856d0eaada6f8140335733a1b1771ed2746lling "Can not downgrade; already at version %u"),
990b4856d0eaada6f8140335733a1b1771ed2746lling * Volumes are limited to a volblocksize of 128KB,
990b4856d0eaada6f8140335733a1b1771ed2746lling * because they typically service workloads with
990b4856d0eaada6f8140335733a1b1771ed2746lling * small random writes, which incur a large performance
990b4856d0eaada6f8140335733a1b1771ed2746lling * penalty with large blocks.
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks * The value must be a power of two between
069f55e237020c4a4907b235fc38fafc6442ce94Eric Schrock * SPA_MINBLOCKSIZE and maxbs.
990b4856d0eaada6f8140335733a1b1771ed2746lling "'%s' must be power of 2 from 512B "
990b4856d0eaada6f8140335733a1b1771ed2746lling * Verify the mlslabel string and convert to
990b4856d0eaada6f8140335733a1b1771ed2746lling * internal hex label string.
990b4856d0eaada6f8140335733a1b1771ed2746lling /* Default value is already OK. */
990b4856d0eaada6f8140335733a1b1771ed2746lling /* Verify the label can be converted to binary form */
990b4856d0eaada6f8140335733a1b1771ed2746lling /* Now translate to hex internal label string */
990b4856d0eaada6f8140335733a1b1771ed2746lling /* If string is already in internal form, we're done. */
990b4856d0eaada6f8140335733a1b1771ed2746lling /* Replace the label string with the internal form. */
990b4856d0eaada6f8140335733a1b1771ed2746lling switch (why) {
990b4856d0eaada6f8140335733a1b1771ed2746lling "'%s' must be an absolute path, "
990b4856d0eaada6f8140335733a1b1771ed2746lling "component of '%s' is too long"),
990b4856d0eaada6f8140335733a1b1771ed2746lling /*FALLTHRU*/
990b4856d0eaada6f8140335733a1b1771ed2746lling * For the mountpoint and sharenfs or sharesmb
990b4856d0eaada6f8140335733a1b1771ed2746lling * properties, check if it can be set in a
990b4856d0eaada6f8140335733a1b1771ed2746lling * global/non-global zone based on
990b4856d0eaada6f8140335733a1b1771ed2746lling * the zoned property value:
990b4856d0eaada6f8140335733a1b1771ed2746lling * global zone non-global zone
990b4856d0eaada6f8140335733a1b1771ed2746lling * --------------------------------------------------
990b4856d0eaada6f8140335733a1b1771ed2746lling * zoned=on mountpoint (no) mountpoint (yes)
990b4856d0eaada6f8140335733a1b1771ed2746lling * sharenfs (no) sharenfs (no)
990b4856d0eaada6f8140335733a1b1771ed2746lling * sharesmb (no) sharesmb (no)
990b4856d0eaada6f8140335733a1b1771ed2746lling * zoned=off mountpoint (yes) N/A
990b4856d0eaada6f8140335733a1b1771ed2746lling * sharenfs (yes)
990b4856d0eaada6f8140335733a1b1771ed2746lling * sharesmb (yes)
990b4856d0eaada6f8140335733a1b1771ed2746lling "'%s' cannot be set on "
990b4856d0eaada6f8140335733a1b1771ed2746lling "dataset in a non-global zone"),
990b4856d0eaada6f8140335733a1b1771ed2746lling "'%s' cannot be set in "
990b4856d0eaada6f8140335733a1b1771ed2746lling * If zoned property is 'off', this must be in
990b4856d0eaada6f8140335733a1b1771ed2746lling * a global zone. If not, something is wrong.
990b4856d0eaada6f8140335733a1b1771ed2746lling "'%s' cannot be set while dataset "
990b4856d0eaada6f8140335733a1b1771ed2746lling * At this point, it is legitimate to set the
990b4856d0eaada6f8140335733a1b1771ed2746lling * property. Now we want to make sure that the
990b4856d0eaada6f8140335733a1b1771ed2746lling * property value is valid if it is sharenfs.
990b4856d0eaada6f8140335733a1b1771ed2746lling * Must be an valid sharing protocol
990b4856d0eaada6f8140335733a1b1771ed2746lling * option string so init the libshare
990b4856d0eaada6f8140335733a1b1771ed2746lling * in order to enable the parser and
990b4856d0eaada6f8140335733a1b1771ed2746lling * then parse the options. We use the
990b4856d0eaada6f8140335733a1b1771ed2746lling * control API since we don't care about
990b4856d0eaada6f8140335733a1b1771ed2746lling * the current configuration and don't
990b4856d0eaada6f8140335733a1b1771ed2746lling * want the overhead of loading it
990b4856d0eaada6f8140335733a1b1771ed2746lling * until we actually do something.
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * An error occurred so we can't do
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens "'%s' cannot be set: problem "
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens "in share initialization"),
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens if (zfs_parse_options(strval, proto) != SA_OK) {
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * There was an error in parsing so
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * deal with it by issuing an error
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * message and leaving after
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * uninitializing the the libshare
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens "'%s' cannot be set to invalid "
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * For changes to existing volumes, we have some additional
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens * checks to enforce.
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens if (type == ZFS_TYPE_VOLUME && zhp != NULL) {
990b4856d0eaada6f8140335733a1b1771ed2746lling "'%s' is greater than current "
990b4856d0eaada6f8140335733a1b1771ed2746lling sizeof (buf));
990b4856d0eaada6f8140335733a1b1771ed2746lling "'%s' must be a multiple of "
990b4856d0eaada6f8140335733a1b1771ed2746lling "volume block size (%s)"),
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens "'%s' cannot be zero"),
990b4856d0eaada6f8140335733a1b1771ed2746lling * If normalization was chosen, but no UTF8 choice was made,
990b4856d0eaada6f8140335733a1b1771ed2746lling * enforce rejection of non-UTF8 names.
990b4856d0eaada6f8140335733a1b1771ed2746lling * If normalization was chosen, but rejecting non-UTF8 names
990b4856d0eaada6f8140335733a1b1771ed2746lling * was explicitly not chosen, it is an error.
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens } else if (chosen_normal > 0 && chosen_utf == 0) {
74e7dc986c89efca1f2e4451c7a572e05e4a6e4fMatthew Ahrens "'%s' must be set 'on' if normalization chosen"),
990b4856d0eaada6f8140335733a1b1771ed2746llingzfs_add_synthetic_resv(zfs_handle_t *zhp, nvlist_t *nvl)
990b4856d0eaada6f8140335733a1b1771ed2746lling * If this is an existing volume, and someone is setting the volsize,
990b4856d0eaada6f8140335733a1b1771ed2746lling * make sure that it matches the reservation, or add it if necessary.
990b4856d0eaada6f8140335733a1b1771ed2746lling old_volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE);
990b4856d0eaada6f8140335733a1b1771ed2746lling return (-1);
990b4856d0eaada6f8140335733a1b1771ed2746lling fnvlist_add_uint64(props, zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
990b4856d0eaada6f8140335733a1b1771ed2746lling if ((zvol_volsize_to_reservation(old_volsize, props) !=
990b4856d0eaada6f8140335733a1b1771ed2746lling return (0);
990b4856d0eaada6f8140335733a1b1771ed2746lling if (nvlist_lookup_uint64(nvl, zfs_prop_to_name(ZFS_PROP_VOLSIZE),
990b4856d0eaada6f8140335733a1b1771ed2746lling return (-1);
990b4856d0eaada6f8140335733a1b1771ed2746lling new_reservation = zvol_volsize_to_reservation(new_volsize, props);
990b4856d0eaada6f8140335733a1b1771ed2746lling if (nvlist_add_uint64(nvl, zfs_prop_to_name(resv_prop),
990b4856d0eaada6f8140335733a1b1771ed2746lling return (-1);
990b4856d0eaada6f8140335733a1b1771ed2746lling return (1);
990b4856d0eaada6f8140335733a1b1771ed2746llingzfs_setprop_error(libzfs_handle_t *hdl, zfs_prop_t prop, int err,
990b4856d0eaada6f8140335733a1b1771ed2746lling switch (err) {
990b4856d0eaada6f8140335733a1b1771ed2746lling * For quotas and reservations, ENOSPC indicates
990b4856d0eaada6f8140335733a1b1771ed2746lling * something different; setting a quota or reservation
990b4856d0eaada6f8140335733a1b1771ed2746lling * doesn't use any disk space.
990b4856d0eaada6f8140335733a1b1771ed2746lling "size is less than current used or "
990b4856d0eaada6f8140335733a1b1771ed2746lling "reserved space"));
990b4856d0eaada6f8140335733a1b1771ed2746lling "size is greater than available space"));
990b4856d0eaada6f8140335733a1b1771ed2746lling "pool and or dataset must be upgraded to set this "
990b4856d0eaada6f8140335733a1b1771ed2746lling "property or value"));
990b4856d0eaada6f8140335733a1b1771ed2746lling "property setting is not allowed on "
ecd6cf800b63704be73fb264c3f5b6e0dafc068dmarks "bootable datasets"));
case EINVAL:
case EOVERFLOW:
#ifdef _ILP32
goto error;
return (ret);
int cl_idx;
int nvl_len;
int added_resv;
goto error;
goto error;
nvl_len = 0;
nvl_len++;
goto error;
cl_idx = 0;
goto error;
goto error;
goto error;
cl_idx++;
goto error;
if (ret != 0) {
goto error;
goto error;
old_volsize) != 0)
goto error;
goto error;
if (clp_err != 0)
if (ret == 0)
return (ret);
int ret;
goto error;
goto error;
goto error;
return (ret);
static uint64_t
return (value);
char *value;
return (value);
static boolean_t
*cookie = 0;
switch (prop) {
case ZFS_PROP_ATIME:
case ZFS_PROP_DEVICES:
case ZFS_PROP_EXEC:
case ZFS_PROP_READONLY:
case ZFS_PROP_SETUID:
case ZFS_PROP_XATTR:
case ZFS_PROP_NBMAND:
switch (prop) {
case ZFS_PROP_ATIME:
case ZFS_PROP_DEVICES:
case ZFS_PROP_EXEC:
case ZFS_PROP_READONLY:
case ZFS_PROP_SETUID:
case ZFS_PROP_XATTR:
case ZFS_PROP_NBMAND:
if (received)
if (src)
if (src)
case ZFS_PROP_CANMOUNT:
case ZFS_PROP_VOLSIZE:
case ZFS_PROP_QUOTA:
case ZFS_PROP_REFQUOTA:
case ZFS_PROP_RESERVATION:
case ZFS_PROP_REFRESERVATION:
case ZFS_PROP_SNAPSHOT_LIMIT:
case ZFS_PROP_SNAPSHOT_COUNT:
case ZFS_PROP_MOUNTED:
case ZFS_PROP_NUMCLONES:
case ZFS_PROP_VERSION:
case ZFS_PROP_NORMALIZE:
case ZFS_PROP_UTF8ONLY:
case ZFS_PROP_CASE:
val) != 0) {
if (zplprops)
case ZFS_PROP_INCONSISTENT:
case PROP_TYPE_NUMBER:
case PROP_TYPE_INDEX:
case PROP_TYPE_STRING:
int err = 0;
char *recvdval;
&recvdval) == 0);
struct get_clones_arg {
const char *origin;
goto out;
out:
nvlist_t *
return (NULL);
return (NULL);
return (NULL);
return (NULL);
return (value);
char *str;
const char *strval;
if (src)
switch (prop) {
case ZFS_PROP_CREATION:
struct tm t;
if (literal ||
case ZFS_PROP_MOUNTPOINT:
const char *relpath;
relpath++;
root++;
str++;
relpath);
case ZFS_PROP_ORIGIN:
proplen);
case ZFS_PROP_CLONES:
case ZFS_PROP_QUOTA:
case ZFS_PROP_REFQUOTA:
case ZFS_PROP_RESERVATION:
case ZFS_PROP_REFRESERVATION:
if (val == 0) {
if (literal)
if (literal)
case ZFS_PROP_SNAPSHOT_LIMIT:
case ZFS_PROP_SNAPSHOT_COUNT:
if (literal) {
case ZFS_PROP_REFRATIO:
case ZFS_PROP_COMPRESSRATIO:
case ZFS_PROP_TYPE:
case ZFS_TYPE_FILESYSTEM:
case ZFS_TYPE_VOLUME:
case ZFS_TYPE_SNAPSHOT:
case ZFS_TYPE_BOOKMARK:
abort();
case ZFS_PROP_MOUNTED:
if (val)
case ZFS_PROP_NAME:
case ZFS_PROP_MLSLABEL:
ZFS_MLSLABEL_DEFAULT) == 0))
DEF_NAMES) != 0) {
if (ascii)
case ZFS_PROP_GUID:
case PROP_TYPE_NUMBER:
if (literal)
case PROP_TYPE_STRING:
case PROP_TYPE_INDEX:
abort();
char *source;
return (val);
char *source;
if (src)
goto out;
if (isuser) {
err = 0;
out:
if (get_hdl)
return (err);
*ridp = 0;
return (EINVAL);
int flag = 0;
return (ENOMEM);
return (ENOENT);
if (isuser) {
if (stat < 0)
return (ENOENT);
if (stat < 0)
return (ENOENT);
if (stat < 0) {
return (ENOENT);
if (stat < 0) {
return (ENOENT);
return (ENOENT);
errno = 0;
if (*ridp == 0) {
cp++;
if (numericsid) {
return (EINVAL);
return (ENOENT);
if (isuser) {
return (ENOENT);
return (ENOENT);
char *mapdomain;
return (EINVAL);
return (ENOENT);
int err;
if (err)
return (err);
if (err)
return (err);
&type));
int err;
&type);
if (err)
return (err);
if (literal) {
} else if (propvalue == 0 &&
int err;
const char *snapname;
char *cp;
if (err)
return (err);
int err;
if (err)
return (err);
if (literal) {
static boolean_t
return (B_FALSE);
char *slashp;
char *slash;
return (B_FALSE);
return (B_TRUE);
return (B_FALSE);
zfs_handle_t *h;
char *cp;
const char *opname;
if (h == NULL)
zfs_close(h);
zfs_close(h);
NULL) != 0) {
goto ancestorerr;
if (h == NULL) {
goto ancestorerr;
goto ancestorerr;
if (zfs_share(h) != 0) {
goto ancestorerr;
zfs_close(h);
int prefix;
char *path_copy;
int rc;
int ret;
&blocksize)) != 0) {
if (size == 0) {
if (ret != 0) {
switch (errno) {
case ENOENT:
case EINVAL:
case EDOM:
case ENOTSUP:
#ifdef _ILP32
case EOVERFLOW:
errbuf));
if (error != 0) {
struct destroydata {
const char *snapname;
int rv = 0;
return (rv);
int ret;
return (ret);
int ret;
if (ret == 0)
case EEXIST:
return (ret);
int ret;
if (props) {
if (ret != 0) {
switch (errno) {
case ENOENT:
case EXDEV:
errbuf));
errbuf));
return (ret);
int ret;
if (ret != 0) {
switch (save_errno) {
case EEXIST:
return (ret);
typedef struct snapdata {
const char *sd_snapname;
} snapdata_t;
int rv = 0;
return (rv);
int ret;
B_TRUE)) {
if (ret != 0) {
if (!printed) {
switch (ret) {
case EXDEV:
return (ret);
int ret;
char *cp;
if (recursive) {
return (ret);
typedef struct rollback_data {
int err;
if (err != 0) {
return (err);
if (restore_resv) {
return (err);
int ret;
char *delim;
sizeof (parent));
errbuf));
if (recursive) {
if (recursive) {
goto error;
goto error;
goto error;
goto error;
return (ret);
nvlist_t *
nvlist_t *
return (NULL);
char *strval;
&propval) == 0) {
int error;
if (resource)
return (error);
while (curr) {
int error;
switch (cmd) {
case ZFS_SMB_ACL_ADD:
case ZFS_SMB_ACL_REMOVE:
case ZFS_SMB_ACL_RENAME:
resource1) != 0) {
resource2) != 0) {
case ZFS_SMB_ACL_PURGE:
if (nvlist)
return (error);
int ret;
return (ret);
zua++;
struct holdarg {
const char *snapname;
const char *tag;
int error;
int rv = 0;
return (rv);
int ret;
return (ret);
return (ret);
int ret;
if (ret == 0) {
switch (ret) {
case ENOTSUP:
case EINVAL:
case E2BIG:
case EINVAL:
case EEXIST:
return (ret);
int rv = 0;
return (rv);
int ret;
return (ret);
if (ret == 0) {
switch (errno) {
case ENOTSUP:
case ESRCH:
case EINVAL:
return (ret);
void *nvbuf;
int err = 0;
goto out;
switch (errno) {
case ENOMEM:
goto tryagain;
case ENOTSUP:
case EINVAL:
case ENOENT:
if (rc) {
out:
return (err);
char *nvbuf;
int err;
switch (errno) {
case ENOTSUP:
case EINVAL:
case ENOENT:
return (err);
int err;
if (err != 0) {
switch (err) {
case ENOTSUP:
case EINVAL:
case ENOENT:
return (err);
int ncopies;
char *strval;
&volblocksize) != 0)
return (volsize);