Print this page
9286 want refreservation=auto

@@ -19,11 +19,11 @@
  * 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) 2018, 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.

@@ -1386,11 +1386,11 @@
                         char buf[64];
 
                         switch (prop) {
                         case ZFS_PROP_RESERVATION:
                         case ZFS_PROP_REFRESERVATION:
-                                if (intval > volsize) {
+                                if (intval > volsize && intval != UINT64_MAX) {
                                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
                                             "'%s' is greater than current "
                                             "volume size"), propname);
                                         (void) zfs_error(hdl, EZFS_BADPROP,
                                             errbuf);

@@ -1497,10 +1497,59 @@
                 return (-1);
         }
         return (1);
 }
 
+/*
+ * Helper for 'zfs {set|clone} [ref]reservation=auto'.  Must be called after
+ * zfs_valid_proplist(), as it is what sets the UINT64_MAX sentinal value.
+ * Return codes must match zfs_add_synthetic_resv().
+ */
+static int
+zfs_fix_auto_resv(zfs_handle_t *zhp, nvlist_t *nvl)
+{
+        uint64_t volsize;
+        uint64_t resvsize;
+        zfs_prop_t prop;
+        nvlist_t *props;
+
+        if (!ZFS_IS_VOLUME(zhp)) {
+                return (0);
+        }
+
+        if (zfs_which_resv_prop(zhp, &prop) != 0) {
+                return (-1);
+        }
+        if (nvlist_lookup_uint64(nvl, zfs_prop_to_name(prop), &resvsize) != 0) {
+                /* No value being set, so it can't be "auto" */
+                return (0);
+        }
+        if (resvsize != UINT64_MAX) {
+                /* Being set to a value other than "auto" */
+                return (0);
+        }
+
+        props = fnvlist_alloc();
+
+        fnvlist_add_uint64(props, zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
+            zfs_prop_get_int(zhp, ZFS_PROP_VOLBLOCKSIZE));
+
+        if (nvlist_lookup_uint64(nvl, zfs_prop_to_name(ZFS_PROP_VOLSIZE),
+            &volsize) != 0) {
+                volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE);
+        }
+
+        resvsize = zvol_volsize_to_reservation(volsize, props);
+        fnvlist_free(props);
+
+        if (nvlist_add_uint64(nvl, zfs_prop_to_name(prop), resvsize) != 0) {
+                (void) no_memory(zhp->zfs_hdl);
+                return (-1);
+        }
+        return (1);
+}
+
 void
 zfs_setprop_error(libzfs_handle_t *hdl, zfs_prop_t prop, int err,
     char *errbuf)
 {
         switch (err) {

@@ -1662,10 +1711,16 @@
                 if (zfs_name_to_prop(nvpair_name(elem)) == ZFS_PROP_VOLSIZE &&
                     (added_resv = zfs_add_synthetic_resv(zhp, nvl)) == -1) {
                         goto error;
                 }
         }
+
+        if (added_resv != 1 &&
+            (added_resv = zfs_fix_auto_resv(zhp, nvl)) == -1) {
+                goto error;
+        }
+
         /*
          * Check how many properties we're setting and allocate an array to
          * store changelist pointers for postfix().
          */
         nvl_len = 0;

@@ -3664,19 +3719,24 @@
 
         /* do the clone */
 
         if (props) {
                 zfs_type_t type;
+
                 if (ZFS_IS_VOLUME(zhp)) {
                         type = ZFS_TYPE_VOLUME;
                 } else {
                         type = ZFS_TYPE_FILESYSTEM;
                 }
                 if ((props = zfs_valid_proplist(hdl, type, props, zoned,
                     zhp, zhp->zpool_hdl, errbuf)) == NULL)
                         return (-1);
+                if (zfs_fix_auto_resv(zhp, props) == -1) {
+                        nvlist_free(props);
+                        return (-1);
         }
+        }
 
         ret = lzc_clone(target, zhp->zfs_name, props);
         nvlist_free(props);
 
         if (ret != 0) {