Print this page
MFV: illumos-gate@f62db44dbcda5dd786bb821f1e6fd3ca2e6d4391
9616 Bogus error when attempting to set property on read-only pool
Reviewed by: Paul Dagnelie <pcd@delphix.com>
Reviewed by: Matt Ahrens <matt@delphix.com>
Approved by: Robert Mustacchi <rm@joyent.com>
8520 lzc_rollback_to should support rolling back to origin
7198 libzfs should gracefully handle EINVAL from lzc_rollback
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Approved by: Dan McDonald <danmcd@joyent.com>
NEX-16502 libshare needs to support SMB in a zone
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
NEX-15279 support NFS server in zone
NEX-15520 online NFS shares cause zoneadm halt to hang in nfs_export_zone_fini
Portions contributed by: Dan Kruchinin dan.kruchinin@nexenta.com
Portions contributed by: Stepan Zastupov stepan.zastupov@gmail.com
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
NEX-9406 Add a property to show that a dataset has been modified since a snapshot
Reviewed by: Alexey Komarov <alexey.komarov@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-9436 Rate limiting controls (was QoS) per ZFS dataset, updates from demo
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
NEX-8852 Quality-of-Service (QoS) controls per NFS share
Reviewed by: Rob Gittins <rob.gittins@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
NEX-5795 Rename 'wrc' as 'wbc' in the source and in the tech docs
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
NEX-5060 WBC: Writecache and deduplication should not be used together
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
NEX-4830 writecache=off leaks data on special vdev (the data will never migrate)
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
6298 zfs_create_008_neg and zpool_create_023_neg need to be updated for large block support
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: John Kennedy <john.kennedy@delphix.com>
Approved by: Robert Mustacchi <rm@joyent.com>
2605 want to resume interrupted zfs send
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Paul Dagnelie <pcd@delphix.com>
Reviewed by: Richard Elling <Richard.Elling@RichardElling.com>
Reviewed by: Xin Li <delphij@freebsd.org>
Reviewed by: Arne Jansen <sensille@gmx.net>
Approved by: Dan McDonald <danmcd@omniti.com>
4185 add new cryptographic checksums to ZFS: SHA-512, Skein, Edon-R (fix studio build)
4185 add new cryptographic checksums to ZFS: SHA-512, Skein, Edon-R
Reviewed by: George Wilson <george.wilson@delphix.com>
Reviewed by: Prakash Surya <prakash.surya@delphix.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Richard Lowe <richlowe@richlowe.net>
Approved by: Garrett D'Amore <garrett@damore.org>
5813 zfs_setprop_error(): Handle errno value E2BIG.
Reviewed by: Paul Dagnelie <paul.dagnelie@delphix.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Prakash Surya <prakash.surya@delphix.com>
Reviewed by: Richard Elling <richard.elling@richardelling.com>
Approved by: Garrett D'Amore <garrett@damore.org>
5745 zfs set allows only one dataset property to be set at a time
Reviewed by: Christopher Siden <christopher.siden@delphix.com>
Reviewed by: George Wilson <george@delphix.com>
Reviewed by: Matthew Ahrens <mahrens@delphix.com>
Reviewed by: Bayard Bell <buffer.g.overflow@gmail.com>
Reviewed by: Richard PALO <richard@NetBSD.org>
Reviewed by: Steven Hartland <killing@multiplay.co.uk>
Approved by: Rich Lowe <richlowe@richlowe.net>
NEX-4476 WRC: Allow to use write back cache per tree of datasets
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
Revert "NEX-4476 WRC: Allow to use write back cache per tree of datasets"
This reverts commit fe97b74444278a6f36fec93179133641296312da.
NEX-4476 WRC: Allow to use write back cache per tree of datasets
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Alex Aizman <alex.aizman@nexenta.com>
NEX-4043 Renaming of autosnaps is not handled correctly
Reviewed by: Alek Pinchuk <alek.pinchuk@nexenta.com>
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
NEX-3669 Faults for fans that don't exist
Reviewed by: Jeffry Molanus <jeffry.molanus@nexenta.com>
NEX-3891 Hide the snapshots that belong to in-kernel autosnap-service
Reviewed by: Josef 'Jeff' Sipek <josef.sipek@nexenta.com>
Reviewed by: Alek Pinchuk <alek@nexenta.com>
NEX-3558 KRRP Integration
NEX-2848 memory leak in the zfs_release() library call path
NEX-1456 Part 2, port FreeBSD patch - new zfs recv options support
SUP-642 Regression leading to AD usernames not being displayed by zfs userspace command.
re #8279 rb3915 need a mechanism to notify NMS about ZFS config changes (Opened code)
@@ -19,20 +19,23 @@
* CDDL HEADER END
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ */
+
+/*
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
* Copyright (c) 2011, 2016 by Delphix. All rights reserved.
* Copyright (c) 2012 DEY Storage Systems, Inc. All rights reserved.
* Copyright (c) 2011-2012 Pawel Jakub Dawidek. All rights reserved.
* Copyright (c) 2013 Martin Matuska. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
- * Copyright 2017 Nexenta Systems, Inc.
+ * Copyright 2018 Nexenta Systems, Inc.
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
- * Copyright 2017 RackTop Systems.
+ * Copyright 2017-2018 RackTop Systems.
*/
#include <ctype.h>
#include <errno.h>
#include <libintl.h>
@@ -62,10 +65,11 @@
#include "zfs_namecheck.h"
#include "zfs_prop.h"
#include "libzfs_impl.h"
#include "zfs_deleg.h"
+#include "zfs_errno.h"
static int userquota_propname_decode(const char *propname, boolean_t zoned,
zfs_userquota_prop_t *typep, char *domain, int domainlen, uint64_t *ridp);
/*
@@ -440,11 +444,13 @@
else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS)
zhp->zfs_head_type = ZFS_TYPE_FILESYSTEM;
else
abort();
- if (zhp->zfs_dmustats.dds_is_snapshot)
+ if (zhp->zfs_dmustats.dds_is_autosnapshot)
+ zhp->zfs_type = ZFS_TYPE_AUTOSNAP;
+ else if (zhp->zfs_dmustats.dds_is_snapshot)
zhp->zfs_type = ZFS_TYPE_SNAPSHOT;
else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZVOL)
zhp->zfs_type = ZFS_TYPE_VOLUME;
else if (zhp->zfs_dmustats.dds_type == DMU_OST_ZFS)
zhp->zfs_type = ZFS_TYPE_FILESYSTEM;
@@ -1260,11 +1266,11 @@
* the zoned property value:
*
* global zone non-global zone
* --------------------------------------------------
* zoned=on mountpoint (no) mountpoint (yes)
- * sharenfs (no) sharenfs (no)
+ * sharenfs (no) sharenfs (yes)
* sharesmb (no) sharesmb (no)
*
* zoned=off mountpoint (yes) N/A
* sharenfs (yes)
* sharesmb (yes)
@@ -1276,18 +1282,10 @@
"dataset in a non-global zone"),
propname);
(void) zfs_error(hdl, EZFS_ZONED,
errbuf);
goto error;
- } else if (prop == ZFS_PROP_SHARENFS ||
- prop == ZFS_PROP_SHARESMB) {
- zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
- "'%s' cannot be set in "
- "a non-global zone"), propname);
- (void) zfs_error(hdl, EZFS_ZONED,
- errbuf);
- goto error;
}
} else if (getzoneid() != GLOBAL_ZONEID) {
/*
* If zoned property is 'off', this must be in
* a global zone. If not, something is wrong.
@@ -1555,11 +1553,12 @@
break;
case ERANGE:
if (prop == ZFS_PROP_COMPRESSION ||
prop == ZFS_PROP_RECORDSIZE) {
- (void) zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ (void) zfs_error_aux(hdl,
+ dgettext(TEXT_DOMAIN,
"property setting is not allowed on "
"bootable datasets"));
(void) zfs_error(hdl, EZFS_NOTSUP, errbuf);
} else if (prop == ZFS_PROP_CHECKSUM ||
prop == ZFS_PROP_DEDUP) {
@@ -1578,10 +1577,23 @@
} else {
(void) zfs_standard_error(hdl, err, errbuf);
}
break;
+ case EKZFS_WBCCONFLICT:
+ if (prop == ZFS_PROP_WBC_MODE || prop == ZFS_PROP_DEDUP) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "WBC and deduplication cannot be "
+ "active simultaneously on the "
+ "same dataset"));
+ (void) zfs_error(hdl, EZFS_WBCNOTSUP, errbuf);
+ } else {
+ (void) zfs_standard_error(hdl, err, errbuf);
+ }
+
+ break;
+
case EOVERFLOW:
/*
* This platform can't address a volume this big.
*/
#ifdef _ILP32
@@ -1590,12 +1602,50 @@
break;
}
#endif
/* FALLTHROUGH */
default:
+ if (prop != ZFS_PROP_WBC_MODE) {
(void) zfs_standard_error(hdl, err, errbuf);
+ break;
}
+
+ switch (err) {
+ case EINPROGRESS:
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "WBC cannot be enabled for the dataset since "
+ "the latter is currently in transition to "
+ "wbc_mode = off. Try again later"));
+ (void) zfs_error(hdl, EZFS_WBCINPROGRESS, errbuf);
+ break;
+ case EALREADY:
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "WBC is already in the requested (on/off) "
+ "state, nothing to do"));
+ (void) zfs_error(hdl, EZFS_WBCALREADY, errbuf);
+ break;
+ case EKZFS_WBCNOTSUP:
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "feature@wbc is not enabled or "
+ "special device (special vdev) is not present"));
+ (void) zfs_error(hdl, EZFS_WBCNOTSUP, errbuf);
+ break;
+ case EKZFS_WBCCHILD:
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "a child dataset has this property enabled"));
+ (void) zfs_error(hdl, EZFS_WBCCHILD, errbuf);
+ break;
+ case EKZFS_WBCPARENT:
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "a parent dataset has this property enabled"));
+ (void) zfs_error(hdl, EZFS_WBCPARENT, errbuf);
+ break;
+ default:
+ (void) zfs_standard_error(hdl, err, errbuf);
+ break;
+ }
+ }
}
/*
* Given a property name and value, set the property for the given dataset.
*/
@@ -1724,17 +1774,22 @@
goto error;
ret = zfs_ioctl(hdl, ZFS_IOC_SET_PROP, &zc);
if (ret != 0) {
+ if (zc.zc_nvlist_dst_filled == B_FALSE) {
+ (void) zfs_standard_error(hdl, errno, errbuf);
+ goto error;
+ }
+
/* Get the list of unset properties back and report them. */
nvlist_t *errorprops = NULL;
if (zcmd_read_dst_nvlist(hdl, &zc, &errorprops) != 0)
goto error;
- for (nvpair_t *elem = nvlist_next_nvpair(nvl, NULL);
+ for (nvpair_t *elem = nvlist_next_nvpair(errorprops, NULL);
elem != NULL;
- elem = nvlist_next_nvpair(nvl, elem)) {
+ elem = nvlist_next_nvpair(errorprops, elem)) {
zfs_prop_t prop = zfs_name_to_prop(nvpair_name(elem));
zfs_setprop_error(hdl, prop, errno, errbuf);
}
nvlist_free(errorprops);
@@ -1832,10 +1887,18 @@
if (!zfs_prop_inheritable(prop) && !received)
return (zfs_error(hdl, EZFS_PROPNONINHERIT, errbuf));
/*
+ * This property is inheritable by nature,
+ * but user can do only "set" operation,
+ * because "inherit" does not make sence
+ */
+ if (prop == ZFS_PROP_WBC_MODE)
+ return (zfs_error(hdl, EZFS_PROPNONINHERIT, errbuf));
+
+ /*
* Check to see if the value applies to this type
*/
if (!zfs_prop_valid_for_type(prop, zhp->zfs_type))
return (zfs_error(hdl, EZFS_PROPTYPE, errbuf));
@@ -2073,10 +2136,11 @@
case ZFS_PROP_REFRESERVATION:
case ZFS_PROP_FILESYSTEM_LIMIT:
case ZFS_PROP_SNAPSHOT_LIMIT:
case ZFS_PROP_FILESYSTEM_COUNT:
case ZFS_PROP_SNAPSHOT_COUNT:
+ case ZFS_PROP_RATE_LIMIT:
*val = getprop_uint64(zhp, prop, source);
if (*source == NULL) {
/* not default, must be local */
*source = zhp->zfs_name;
@@ -2551,10 +2615,11 @@
case ZFS_PROP_FILESYSTEM_LIMIT:
case ZFS_PROP_SNAPSHOT_LIMIT:
case ZFS_PROP_FILESYSTEM_COUNT:
case ZFS_PROP_SNAPSHOT_COUNT:
+ case ZFS_PROP_RATE_LIMIT:
if (get_numeric_property(zhp, prop, src, &source, &val) != 0)
return (-1);
/*
@@ -2594,10 +2659,13 @@
str = "volume";
break;
case ZFS_TYPE_SNAPSHOT:
str = "snapshot";
break;
+ case ZFS_TYPE_AUTOSNAP:
+ str = "autosnap";
+ break;
case ZFS_TYPE_BOOKMARK:
str = "bookmark";
break;
default:
abort();
@@ -2680,10 +2748,27 @@
return (-1);
(void) snprintf(propbuf, proplen, "%llu", (u_longlong_t)val);
zcp_check(zhp, prop, val, NULL);
break;
+ case ZFS_PROP_MODIFIED:
+ /*
+ * For a snapshot the "modified" pseudo-property is set to
+ * "yes" if parent filesystem/zvol differs from the snapshot.
+ * Even though it's a boolean value, the typical
+ * values of "on" and "off" don't make sense, so we translate
+ * to "yes" and "no".
+ */
+ if (get_numeric_property(zhp, ZFS_PROP_MODIFIED,
+ src, &source, &val) != 0)
+ return (-1);
+ if (val != 0)
+ (void) strlcpy(propbuf, "yes", proplen);
+ else
+ (void) strlcpy(propbuf, "no", proplen);
+ break;
+
default:
switch (zfs_prop_get_type(prop)) {
case PROP_TYPE_NUMBER:
if (get_numeric_property(zhp, prop, src,
&source, &val) != 0) {
@@ -3140,11 +3225,11 @@
* closest existing ancestor for the given path. In prefixlen return the
* length of already existing prefix of the given path. We also fetch the
* 'zoned' property, which is used to validate property settings when creating
* new datasets.
*/
-static int
+int
check_parents(libzfs_handle_t *hdl, const char *path, uint64_t *zoned,
boolean_t accept_ancestor, int *prefixlen)
{
zfs_cmd_t zc = { 0 };
char parent[ZFS_MAX_DATASET_NAME_LEN];
@@ -3452,10 +3537,12 @@
}
/* create the dataset */
ret = lzc_create(path, ost, props);
nvlist_free(props);
+ if (ret == 0)
+ libzfs_log_event(hdl, path);
/* check for failure */
if (ret != 0) {
char parent[ZFS_MAX_DATASET_NAME_LEN];
(void) parent_name(path, parent, sizeof (parent));
@@ -3496,10 +3583,68 @@
}
return (0);
}
+int
+zfs_check_krrp(libzfs_handle_t *hdl, const char *name)
+{
+ zfs_cmd_t zc = { 0 };
+ int err;
+
+ (void) strncpy(zc.zc_name, name, ZFS_MAX_DATASET_NAME_LEN);
+ zc.zc_name[ZFS_MAX_DATASET_NAME_LEN - 1] = '\0';
+
+ (void) zfs_ioctl(hdl, ZFS_IOC_CHECK_KRRP, &zc);
+ err = errno;
+
+ free((void *)(uintptr_t)zc.zc_nvlist_dst);
+
+ return (err);
+}
+
+int
+zfs_destroy_atomically(zfs_handle_t *zhp, boolean_t defer)
+{
+ zfs_cmd_t zc = { 0 };
+
+ if (zhp->zfs_type == ZFS_TYPE_BOOKMARK) {
+ nvlist_t *nv = fnvlist_alloc();
+ fnvlist_add_boolean(nv, zhp->zfs_name);
+ int error = lzc_destroy_bookmarks(nv, NULL);
+ fnvlist_free(nv);
+ if (error != 0) {
+ return (zfs_standard_error_fmt(zhp->zfs_hdl, errno,
+ dgettext(TEXT_DOMAIN, "cannot destroy '%s'"),
+ zhp->zfs_name));
+ }
+ return (0);
+ }
+
+ (void) strlcpy(zc.zc_name, zhp->zfs_name, sizeof (zc.zc_name));
+
+ if (ZFS_IS_VOLUME(zhp)) {
+ zc.zc_objset_type = DMU_OST_ZVOL;
+ } else {
+ zc.zc_objset_type = DMU_OST_ZFS;
+ }
+
+ zc.zc_defer_destroy = defer;
+ zc.zc_guid = B_TRUE;
+ if (zfs_ioctl(zhp->zfs_hdl, ZFS_IOC_DESTROY, &zc) != 0 &&
+ errno != ENOENT) {
+ return (zfs_standard_error_fmt(zhp->zfs_hdl, errno,
+ dgettext(TEXT_DOMAIN, "cannot destroy '%s'"),
+ zhp->zfs_name));
+ }
+
+ remove_mountpoint(zhp);
+
+ return (0);
+
+}
+
/*
* Destroys the given dataset. The caller must make sure that the filesystem
* isn't mounted, and that there are no active dependents. If the file system
* does not exist this function does nothing.
*/
@@ -3594,13 +3739,19 @@
*/
int
zfs_destroy_snaps_nvl(libzfs_handle_t *hdl, nvlist_t *snaps, boolean_t defer)
{
int ret;
+ nvpair_t *elem;
nvlist_t *errlist = NULL;
ret = lzc_destroy_snaps(snaps, defer, &errlist);
+ if (ret == 0) {
+ for (elem = nvlist_next_nvpair(snaps, NULL); elem != NULL;
+ elem = nvlist_next_nvpair(snaps, elem))
+ libzfs_log_event(hdl, nvpair_name(elem));
+ }
if (ret == 0) {
nvlist_free(errlist);
return (0);
}
@@ -3676,10 +3827,12 @@
return (-1);
}
ret = lzc_clone(target, zhp->zfs_name, props);
nvlist_free(props);
+ if (ret == 0)
+ libzfs_log_event(hdl, target);
if (ret != 0) {
switch (errno) {
case ENOENT:
@@ -3735,13 +3888,10 @@
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"not a cloned filesystem"));
return (zfs_error(hdl, EZFS_BADTYPE, errbuf));
}
- if (!zfs_validate_name(hdl, zhp->zfs_name, zhp->zfs_type, B_TRUE))
- return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
-
ret = lzc_promote(zhp->zfs_name, snapname, sizeof (snapname));
if (ret != 0) {
switch (ret) {
case EEXIST:
@@ -3781,28 +3931,10 @@
zfs_close(zhp);
return (rv);
}
-int
-zfs_remap_indirects(libzfs_handle_t *hdl, const char *fs)
-{
- int err;
- char errbuf[1024];
-
- (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
- "cannot remap filesystem '%s' "), fs);
-
- err = lzc_remap(fs);
-
- if (err != 0) {
- (void) zfs_standard_error(hdl, err, errbuf);
- }
-
- return (err);
-}
-
/*
* Creates snapshots. The keys in the snaps nvlist are the snapshots to be
* created.
*/
int
@@ -3847,10 +3979,15 @@
return (-1);
}
zpool_close(zpool_hdl);
ret = lzc_snapshot(snaps, props, &errors);
+ if (ret == 0) {
+ for (elem = nvlist_next_nvpair(snaps, NULL); elem != NULL;
+ elem = nvlist_next_nvpair(snaps, elem))
+ libzfs_log_event(hdl, nvpair_name(elem));
+ }
if (ret != 0) {
boolean_t printed = B_FALSE;
for (elem = nvlist_next_nvpair(errors, NULL);
elem != NULL;
@@ -4095,13 +4232,15 @@
return (0);
(void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
"cannot rename to '%s'"), target);
- /* make sure source name is valid */
- if (!zfs_validate_name(hdl, zhp->zfs_name, zhp->zfs_type, B_TRUE))
- return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
+ if (zhp->zfs_type == ZFS_TYPE_AUTOSNAP) {
+ zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
+ "autosnapshots cannot be renamed"));
+ return (zfs_error(hdl, EZFS_PERM, errbuf));
+ }
/*
* Make sure the target name is valid
*/
if (zhp->zfs_type == ZFS_TYPE_SNAPSHOT) {
@@ -4707,10 +4846,12 @@
fnvlist_add_boolean(torelease, ha->tag);
fnvlist_add_nvlist(ha->nvl, name, torelease);
fnvlist_free(torelease);
}
+ fnvlist_free(existing_holds);
+
if (ha->recursive)
rv = zfs_iter_filesystems(zhp, zfs_release_one, ha);
zfs_close(zhp);
return (rv);
}