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