Print this page
9286 want refreservation=auto


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2013, Joyent, Inc. All rights reserved.
  25  * Copyright (c) 2011, 2016 by Delphix. All rights reserved.
  26  * Copyright (c) 2012 DEY Storage Systems, Inc.  All rights reserved.
  27  * Copyright (c) 2011-2012 Pawel Jakub Dawidek. All rights reserved.
  28  * Copyright (c) 2013 Martin Matuska. All rights reserved.
  29  * Copyright (c) 2013 Steven Hartland. All rights reserved.
  30  * Copyright (c) 2014 Integros [integros.com]
  31  * Copyright 2017 Nexenta Systems, Inc.
  32  * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
  33  * Copyright 2017 RackTop Systems.
  34  */
  35 
  36 #include <ctype.h>
  37 #include <errno.h>
  38 #include <libintl.h>
  39 #include <math.h>
  40 #include <stdio.h>
  41 #include <stdlib.h>
  42 #include <strings.h>
  43 #include <unistd.h>
  44 #include <stddef.h>


1371                         break;
1372 
1373                 default:
1374                         break;
1375                 }
1376 
1377                 /*
1378                  * For changes to existing volumes, we have some additional
1379                  * checks to enforce.
1380                  */
1381                 if (type == ZFS_TYPE_VOLUME && zhp != NULL) {
1382                         uint64_t volsize = zfs_prop_get_int(zhp,
1383                             ZFS_PROP_VOLSIZE);
1384                         uint64_t blocksize = zfs_prop_get_int(zhp,
1385                             ZFS_PROP_VOLBLOCKSIZE);
1386                         char buf[64];
1387 
1388                         switch (prop) {
1389                         case ZFS_PROP_RESERVATION:
1390                         case ZFS_PROP_REFRESERVATION:
1391                                 if (intval > volsize) {
1392                                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1393                                             "'%s' is greater than current "
1394                                             "volume size"), propname);
1395                                         (void) zfs_error(hdl, EZFS_BADPROP,
1396                                             errbuf);
1397                                         goto error;
1398                                 }
1399                                 break;
1400 
1401                         case ZFS_PROP_VOLSIZE:
1402                                 if (intval % blocksize != 0) {
1403                                         zfs_nicenum(blocksize, buf,
1404                                             sizeof (buf));
1405                                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1406                                             "'%s' must be a multiple of "
1407                                             "volume block size (%s)"),
1408                                             propname, buf);
1409                                         (void) zfs_error(hdl, EZFS_BADPROP,
1410                                             errbuf);
1411                                         goto error;


1482             zfs_prop_to_name(resv_prop))) {
1483                 fnvlist_free(props);
1484                 return (0);
1485         }
1486         if (nvlist_lookup_uint64(nvl, zfs_prop_to_name(ZFS_PROP_VOLSIZE),
1487             &new_volsize) != 0) {
1488                 fnvlist_free(props);
1489                 return (-1);
1490         }
1491         new_reservation = zvol_volsize_to_reservation(new_volsize, props);
1492         fnvlist_free(props);
1493 
1494         if (nvlist_add_uint64(nvl, zfs_prop_to_name(resv_prop),
1495             new_reservation) != 0) {
1496                 (void) no_memory(zhp->zfs_hdl);
1497                 return (-1);
1498         }
1499         return (1);
1500 }
1501 

















































1502 void
1503 zfs_setprop_error(libzfs_handle_t *hdl, zfs_prop_t prop, int err,
1504     char *errbuf)
1505 {
1506         switch (err) {
1507 
1508         case ENOSPC:
1509                 /*
1510                  * For quotas and reservations, ENOSPC indicates
1511                  * something different; setting a quota or reservation
1512                  * doesn't use any disk space.
1513                  */
1514                 switch (prop) {
1515                 case ZFS_PROP_QUOTA:
1516                 case ZFS_PROP_REFQUOTA:
1517                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1518                             "size is less than current used or "
1519                             "reserved space"));
1520                         (void) zfs_error(hdl, EZFS_PROPSPACE, errbuf);
1521                         break;


1647             dgettext(TEXT_DOMAIN, "cannot set property for '%s'"),
1648             zhp->zfs_name);
1649 
1650         if ((nvl = zfs_valid_proplist(hdl, zhp->zfs_type, props,
1651             zfs_prop_get_int(zhp, ZFS_PROP_ZONED), zhp, zhp->zpool_hdl,
1652             errbuf)) == NULL)
1653                 goto error;
1654 
1655         /*
1656          * We have to check for any extra properties which need to be added
1657          * before computing the length of the nvlist.
1658          */
1659         for (nvpair_t *elem = nvlist_next_nvpair(nvl, NULL);
1660             elem != NULL;
1661             elem = nvlist_next_nvpair(nvl, elem)) {
1662                 if (zfs_name_to_prop(nvpair_name(elem)) == ZFS_PROP_VOLSIZE &&
1663                     (added_resv = zfs_add_synthetic_resv(zhp, nvl)) == -1) {
1664                         goto error;
1665                 }
1666         }






1667         /*
1668          * Check how many properties we're setting and allocate an array to
1669          * store changelist pointers for postfix().
1670          */
1671         nvl_len = 0;
1672         for (nvpair_t *elem = nvlist_next_nvpair(nvl, NULL);
1673             elem != NULL;
1674             elem = nvlist_next_nvpair(nvl, elem))
1675                 nvl_len++;
1676         if ((cls = calloc(nvl_len, sizeof (prop_changelist_t *))) == NULL)
1677                 goto error;
1678 
1679         cl_idx = 0;
1680         for (nvpair_t *elem = nvlist_next_nvpair(nvl, NULL);
1681             elem != NULL;
1682             elem = nvlist_next_nvpair(nvl, elem)) {
1683 
1684                 zfs_prop_t prop = zfs_name_to_prop(nvpair_name(elem));
1685 
1686                 assert(cl_idx < nvl_len);


3649 
3650         assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
3651 
3652         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3653             "cannot create '%s'"), target);
3654 
3655         /* validate the target/clone name */
3656         if (!zfs_validate_name(hdl, target, ZFS_TYPE_FILESYSTEM, B_TRUE))
3657                 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3658 
3659         /* validate parents exist */
3660         if (check_parents(hdl, target, &zoned, B_FALSE, NULL) != 0)
3661                 return (-1);
3662 
3663         (void) parent_name(target, parent, sizeof (parent));
3664 
3665         /* do the clone */
3666 
3667         if (props) {
3668                 zfs_type_t type;

3669                 if (ZFS_IS_VOLUME(zhp)) {
3670                         type = ZFS_TYPE_VOLUME;
3671                 } else {
3672                         type = ZFS_TYPE_FILESYSTEM;
3673                 }
3674                 if ((props = zfs_valid_proplist(hdl, type, props, zoned,
3675                     zhp, zhp->zpool_hdl, errbuf)) == NULL)
3676                         return (-1);



3677         }

3678 
3679         ret = lzc_clone(target, zhp->zfs_name, props);
3680         nvlist_free(props);
3681 
3682         if (ret != 0) {
3683                 switch (errno) {
3684 
3685                 case ENOENT:
3686                         /*
3687                          * The parent doesn't exist.  We should have caught this
3688                          * above, but there may a race condition that has since
3689                          * destroyed the parent.
3690                          *
3691                          * At this point, we don't know whether it's the source
3692                          * that doesn't exist anymore, or whether the target
3693                          * dataset doesn't exist.
3694                          */
3695                         zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
3696                             "no such parent '%s'"), parent);
3697                         return (zfs_error(zhp->zfs_hdl, EZFS_NOENT, errbuf));




   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2018, Joyent, Inc. All rights reserved.
  25  * Copyright (c) 2011, 2016 by Delphix. All rights reserved.
  26  * Copyright (c) 2012 DEY Storage Systems, Inc.  All rights reserved.
  27  * Copyright (c) 2011-2012 Pawel Jakub Dawidek. All rights reserved.
  28  * Copyright (c) 2013 Martin Matuska. All rights reserved.
  29  * Copyright (c) 2013 Steven Hartland. All rights reserved.
  30  * Copyright (c) 2014 Integros [integros.com]
  31  * Copyright 2017 Nexenta Systems, Inc.
  32  * Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
  33  * Copyright 2017 RackTop Systems.
  34  */
  35 
  36 #include <ctype.h>
  37 #include <errno.h>
  38 #include <libintl.h>
  39 #include <math.h>
  40 #include <stdio.h>
  41 #include <stdlib.h>
  42 #include <strings.h>
  43 #include <unistd.h>
  44 #include <stddef.h>


1371                         break;
1372 
1373                 default:
1374                         break;
1375                 }
1376 
1377                 /*
1378                  * For changes to existing volumes, we have some additional
1379                  * checks to enforce.
1380                  */
1381                 if (type == ZFS_TYPE_VOLUME && zhp != NULL) {
1382                         uint64_t volsize = zfs_prop_get_int(zhp,
1383                             ZFS_PROP_VOLSIZE);
1384                         uint64_t blocksize = zfs_prop_get_int(zhp,
1385                             ZFS_PROP_VOLBLOCKSIZE);
1386                         char buf[64];
1387 
1388                         switch (prop) {
1389                         case ZFS_PROP_RESERVATION:
1390                         case ZFS_PROP_REFRESERVATION:
1391                                 if (intval > volsize && intval != UINT64_MAX) {
1392                                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1393                                             "'%s' is greater than current "
1394                                             "volume size"), propname);
1395                                         (void) zfs_error(hdl, EZFS_BADPROP,
1396                                             errbuf);
1397                                         goto error;
1398                                 }
1399                                 break;
1400 
1401                         case ZFS_PROP_VOLSIZE:
1402                                 if (intval % blocksize != 0) {
1403                                         zfs_nicenum(blocksize, buf,
1404                                             sizeof (buf));
1405                                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1406                                             "'%s' must be a multiple of "
1407                                             "volume block size (%s)"),
1408                                             propname, buf);
1409                                         (void) zfs_error(hdl, EZFS_BADPROP,
1410                                             errbuf);
1411                                         goto error;


1482             zfs_prop_to_name(resv_prop))) {
1483                 fnvlist_free(props);
1484                 return (0);
1485         }
1486         if (nvlist_lookup_uint64(nvl, zfs_prop_to_name(ZFS_PROP_VOLSIZE),
1487             &new_volsize) != 0) {
1488                 fnvlist_free(props);
1489                 return (-1);
1490         }
1491         new_reservation = zvol_volsize_to_reservation(new_volsize, props);
1492         fnvlist_free(props);
1493 
1494         if (nvlist_add_uint64(nvl, zfs_prop_to_name(resv_prop),
1495             new_reservation) != 0) {
1496                 (void) no_memory(zhp->zfs_hdl);
1497                 return (-1);
1498         }
1499         return (1);
1500 }
1501 
1502 /*
1503  * Helper for 'zfs {set|clone} [ref]reservation=auto'.  Must be called after
1504  * zfs_valid_proplist(), as it is what sets the UINT64_MAX sentinal value.
1505  * Return codes must match zfs_add_synthetic_resv().
1506  */
1507 static int
1508 zfs_fix_auto_resv(zfs_handle_t *zhp, nvlist_t *nvl)
1509 {
1510         uint64_t volsize;
1511         uint64_t resvsize;
1512         zfs_prop_t prop;
1513         nvlist_t *props;
1514 
1515         if (!ZFS_IS_VOLUME(zhp)) {
1516                 return (0);
1517         }
1518 
1519         if (zfs_which_resv_prop(zhp, &prop) != 0) {
1520                 return (-1);
1521         }
1522         if (nvlist_lookup_uint64(nvl, zfs_prop_to_name(prop), &resvsize) != 0) {
1523                 /* No value being set, so it can't be "auto" */
1524                 return (0);
1525         }
1526         if (resvsize != UINT64_MAX) {
1527                 /* Being set to a value other than "auto" */
1528                 return (0);
1529         }
1530 
1531         props = fnvlist_alloc();
1532 
1533         fnvlist_add_uint64(props, zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
1534             zfs_prop_get_int(zhp, ZFS_PROP_VOLBLOCKSIZE));
1535 
1536         if (nvlist_lookup_uint64(nvl, zfs_prop_to_name(ZFS_PROP_VOLSIZE),
1537             &volsize) != 0) {
1538                 volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE);
1539         }
1540 
1541         resvsize = zvol_volsize_to_reservation(volsize, props);
1542         fnvlist_free(props);
1543 
1544         if (nvlist_add_uint64(nvl, zfs_prop_to_name(prop), resvsize) != 0) {
1545                 (void) no_memory(zhp->zfs_hdl);
1546                 return (-1);
1547         }
1548         return (1);
1549 }
1550 
1551 void
1552 zfs_setprop_error(libzfs_handle_t *hdl, zfs_prop_t prop, int err,
1553     char *errbuf)
1554 {
1555         switch (err) {
1556 
1557         case ENOSPC:
1558                 /*
1559                  * For quotas and reservations, ENOSPC indicates
1560                  * something different; setting a quota or reservation
1561                  * doesn't use any disk space.
1562                  */
1563                 switch (prop) {
1564                 case ZFS_PROP_QUOTA:
1565                 case ZFS_PROP_REFQUOTA:
1566                         zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
1567                             "size is less than current used or "
1568                             "reserved space"));
1569                         (void) zfs_error(hdl, EZFS_PROPSPACE, errbuf);
1570                         break;


1696             dgettext(TEXT_DOMAIN, "cannot set property for '%s'"),
1697             zhp->zfs_name);
1698 
1699         if ((nvl = zfs_valid_proplist(hdl, zhp->zfs_type, props,
1700             zfs_prop_get_int(zhp, ZFS_PROP_ZONED), zhp, zhp->zpool_hdl,
1701             errbuf)) == NULL)
1702                 goto error;
1703 
1704         /*
1705          * We have to check for any extra properties which need to be added
1706          * before computing the length of the nvlist.
1707          */
1708         for (nvpair_t *elem = nvlist_next_nvpair(nvl, NULL);
1709             elem != NULL;
1710             elem = nvlist_next_nvpair(nvl, elem)) {
1711                 if (zfs_name_to_prop(nvpair_name(elem)) == ZFS_PROP_VOLSIZE &&
1712                     (added_resv = zfs_add_synthetic_resv(zhp, nvl)) == -1) {
1713                         goto error;
1714                 }
1715         }
1716 
1717         if (added_resv != 1 &&
1718             (added_resv = zfs_fix_auto_resv(zhp, nvl)) == -1) {
1719                 goto error;
1720         }
1721 
1722         /*
1723          * Check how many properties we're setting and allocate an array to
1724          * store changelist pointers for postfix().
1725          */
1726         nvl_len = 0;
1727         for (nvpair_t *elem = nvlist_next_nvpair(nvl, NULL);
1728             elem != NULL;
1729             elem = nvlist_next_nvpair(nvl, elem))
1730                 nvl_len++;
1731         if ((cls = calloc(nvl_len, sizeof (prop_changelist_t *))) == NULL)
1732                 goto error;
1733 
1734         cl_idx = 0;
1735         for (nvpair_t *elem = nvlist_next_nvpair(nvl, NULL);
1736             elem != NULL;
1737             elem = nvlist_next_nvpair(nvl, elem)) {
1738 
1739                 zfs_prop_t prop = zfs_name_to_prop(nvpair_name(elem));
1740 
1741                 assert(cl_idx < nvl_len);


3704 
3705         assert(zhp->zfs_type == ZFS_TYPE_SNAPSHOT);
3706 
3707         (void) snprintf(errbuf, sizeof (errbuf), dgettext(TEXT_DOMAIN,
3708             "cannot create '%s'"), target);
3709 
3710         /* validate the target/clone name */
3711         if (!zfs_validate_name(hdl, target, ZFS_TYPE_FILESYSTEM, B_TRUE))
3712                 return (zfs_error(hdl, EZFS_INVALIDNAME, errbuf));
3713 
3714         /* validate parents exist */
3715         if (check_parents(hdl, target, &zoned, B_FALSE, NULL) != 0)
3716                 return (-1);
3717 
3718         (void) parent_name(target, parent, sizeof (parent));
3719 
3720         /* do the clone */
3721 
3722         if (props) {
3723                 zfs_type_t type;
3724 
3725                 if (ZFS_IS_VOLUME(zhp)) {
3726                         type = ZFS_TYPE_VOLUME;
3727                 } else {
3728                         type = ZFS_TYPE_FILESYSTEM;
3729                 }
3730                 if ((props = zfs_valid_proplist(hdl, type, props, zoned,
3731                     zhp, zhp->zpool_hdl, errbuf)) == NULL)
3732                         return (-1);
3733                 if (zfs_fix_auto_resv(zhp, props) == -1) {
3734                         nvlist_free(props);
3735                         return (-1);
3736                 }
3737         }
3738 
3739         ret = lzc_clone(target, zhp->zfs_name, props);
3740         nvlist_free(props);
3741 
3742         if (ret != 0) {
3743                 switch (errno) {
3744 
3745                 case ENOENT:
3746                         /*
3747                          * The parent doesn't exist.  We should have caught this
3748                          * above, but there may a race condition that has since
3749                          * destroyed the parent.
3750                          *
3751                          * At this point, we don't know whether it's the source
3752                          * that doesn't exist anymore, or whether the target
3753                          * dataset doesn't exist.
3754                          */
3755                         zfs_error_aux(zhp->zfs_hdl, dgettext(TEXT_DOMAIN,
3756                             "no such parent '%s'"), parent);
3757                         return (zfs_error(zhp->zfs_hdl, EZFS_NOENT, errbuf));