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);
 }