Print this page
4012 Upper limit of zfs set bounds check for refreservation on volumes is too low
*** 20,30 ****
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
! * Copyright (c) 2012 DEY Storage Systems, Inc. All rights reserved.
* Copyright 2012 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2013 Martin Matuska. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
*/
--- 20,30 ----
*/
/*
* Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013 by Delphix. All rights reserved.
! * Copyright 2013 DEY Storage Systems, Inc.
* Copyright 2012 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2013 Martin Matuska. All rights reserved.
* Copyright (c) 2013 Steven Hartland. All rights reserved.
*/
*** 1207,1222 ****
if (type == ZFS_TYPE_VOLUME && zhp != NULL) {
uint64_t volsize = zfs_prop_get_int(zhp,
ZFS_PROP_VOLSIZE);
uint64_t blocksize = zfs_prop_get_int(zhp,
ZFS_PROP_VOLBLOCKSIZE);
char buf[64];
switch (prop) {
case ZFS_PROP_RESERVATION:
case ZFS_PROP_REFRESERVATION:
! if (intval > volsize) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"'%s' is greater than current "
"volume size"), propname);
(void) zfs_error(hdl, EZFS_BADPROP,
errbuf);
--- 1207,1225 ----
if (type == ZFS_TYPE_VOLUME && zhp != NULL) {
uint64_t volsize = zfs_prop_get_int(zhp,
ZFS_PROP_VOLSIZE);
uint64_t blocksize = zfs_prop_get_int(zhp,
ZFS_PROP_VOLBLOCKSIZE);
+ int ncopies = zfs_prop_get_int(zhp, ZFS_PROP_COPIES);
char buf[64];
switch (prop) {
case ZFS_PROP_RESERVATION:
case ZFS_PROP_REFRESERVATION:
! if (intval >
! zvol_volsize_to_reservation_impl(volsize,
! blocksize, ncopies)) {
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
"'%s' is greater than current "
"volume size"), propname);
(void) zfs_error(hdl, EZFS_BADPROP,
errbuf);
*** 1283,1320 ****
uint64_t old_volsize;
uint64_t new_volsize;
uint64_t old_reservation;
uint64_t new_reservation;
zfs_prop_t resv_prop;
! nvlist_t *props;
/*
* If this is an existing volume, and someone is setting the volsize,
* make sure that it matches the reservation, or add it if necessary.
*/
old_volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE);
if (zfs_which_resv_prop(zhp, &resv_prop) < 0)
return (-1);
old_reservation = zfs_prop_get_int(zhp, resv_prop);
! props = fnvlist_alloc();
! fnvlist_add_uint64(props, zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
! zfs_prop_get_int(zhp, ZFS_PROP_VOLBLOCKSIZE));
!
! if ((zvol_volsize_to_reservation(old_volsize, props) !=
! old_reservation) || nvlist_exists(nvl,
! zfs_prop_to_name(resv_prop))) {
! fnvlist_free(props);
return (0);
- }
if (nvlist_lookup_uint64(nvl, zfs_prop_to_name(ZFS_PROP_VOLSIZE),
! &new_volsize) != 0) {
! fnvlist_free(props);
return (-1);
! }
! new_reservation = zvol_volsize_to_reservation(new_volsize, props);
! fnvlist_free(props);
if (nvlist_add_uint64(nvl, zfs_prop_to_name(resv_prop),
new_reservation) != 0) {
(void) no_memory(zhp->zfs_hdl);
return (-1);
--- 1286,1318 ----
uint64_t old_volsize;
uint64_t new_volsize;
uint64_t old_reservation;
uint64_t new_reservation;
zfs_prop_t resv_prop;
! uint64_t volblocksize;
! int ncopies;
/*
* If this is an existing volume, and someone is setting the volsize,
* make sure that it matches the reservation, or add it if necessary.
*/
old_volsize = zfs_prop_get_int(zhp, ZFS_PROP_VOLSIZE);
if (zfs_which_resv_prop(zhp, &resv_prop) < 0)
return (-1);
old_reservation = zfs_prop_get_int(zhp, resv_prop);
+ volblocksize = zfs_prop_get_int(zhp, ZFS_PROP_VOLBLOCKSIZE);
+ ncopies = zfs_prop_get_int(zhp, ZFS_PROP_COPIES);
! if ((zvol_volsize_to_reservation_impl(old_volsize, volblocksize,
! ncopies) != old_reservation) || nvlist_exists(nvl,
! zfs_prop_to_name(resv_prop)))
return (0);
if (nvlist_lookup_uint64(nvl, zfs_prop_to_name(ZFS_PROP_VOLSIZE),
! &new_volsize) != 0)
return (-1);
! new_reservation = zvol_volsize_to_reservation_impl(new_volsize,
! volblocksize, ncopies);
if (nvlist_add_uint64(nvl, zfs_prop_to_name(resv_prop),
new_reservation) != 0) {
(void) no_memory(zhp->zfs_hdl);
return (-1);
*** 4458,4476 ****
return (err);
}
/*
! * Convert the zvol's volume size to an appropriate reservation.
* Note: If this routine is updated, it is necessary to update the ZFS test
* suite's shell version in reservation.kshlib.
*/
uint64_t
zvol_volsize_to_reservation(uint64_t volsize, nvlist_t *props)
{
! uint64_t numdb;
! uint64_t nblocks, volblocksize;
int ncopies;
char *strval;
if (nvlist_lookup_string(props,
zfs_prop_to_name(ZFS_PROP_COPIES), &strval) == 0)
--- 4456,4474 ----
return (err);
}
/*
! * Convert the zvol's volume size to an appropriate reservation. This is a
! * convenience front-end to zvol_volsize_to_reservation_impl.
* Note: If this routine is updated, it is necessary to update the ZFS test
* suite's shell version in reservation.kshlib.
*/
uint64_t
zvol_volsize_to_reservation(uint64_t volsize, nvlist_t *props)
{
! uint64_t volblocksize;
int ncopies;
char *strval;
if (nvlist_lookup_string(props,
zfs_prop_to_name(ZFS_PROP_COPIES), &strval) == 0)
*** 4479,4488 ****
--- 4477,4502 ----
ncopies = 1;
if (nvlist_lookup_uint64(props,
zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
&volblocksize) != 0)
volblocksize = ZVOL_DEFAULT_BLOCKSIZE;
+
+ return (zvol_volsize_to_reservation_impl(volsize, volblocksize,
+ ncopies));
+ }
+
+ /*
+ * Computes the required reservation to completely contain all blocks of a
+ * zvol at a given volsize.
+ */
+ uint64_t
+ zvol_volsize_to_reservation_impl(uint64_t volsize, uint64_t volblocksize,
+ int ncopies)
+ {
+ uint64_t numdb;
+ uint64_t nblocks;
+
nblocks = volsize/volblocksize;
/* start with metadnode L0-L6 */
numdb = 7;
/* calculate number of indirects */
while (nblocks > 1) {