9286 want refreservation=auto
When a ZFS volume is created with zfs create -V (but without -s), the refreservation property is set to a value that is volsize plus the maximum size of metadata. If refreservation is ever set to another value, it is impossible to set it back to the automatically determined value. There are other cases where refreservation may be wrong. These include receiving a volume that was sent without properties and zfs clone. We need: zfs set refreservation=auto <volume> zfs clone -o refreservation=auto <volume> Each one would use the same function used by zfs create -V to determine the proper value for refreservation. illumos/illumos-gate@1c10ae76c0 Reviewed by: Allan Jude <allanjude@freebsd.org> Reviewed by: Matthew Ahrens <mahrens@delphix.com> Reviewed by: John Kennedy <john.kennedy@delphix.com> Reviewed by: Andy Stormont <astormont@racktopsystems.com> Approved by: Richard Lowe <richlowe@richlowe.net> Author: Mike Gerdts <mike.gerdts@joyent.com>
This commit is contained in:
parent
05cdb6cd3b
commit
6f4662e465
@ -21,7 +21,7 @@
|
||||
|
||||
/*
|
||||
* 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.
|
||||
@ -1387,7 +1387,6 @@ zfs_valid_proplist(libzfs_handle_t *hdl, zfs_type_t type, nvlist_t *nvl,
|
||||
|
||||
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 "
|
||||
@ -1398,6 +1397,17 @@ zfs_valid_proplist(libzfs_handle_t *hdl, zfs_type_t type, nvlist_t *nvl,
|
||||
}
|
||||
break;
|
||||
|
||||
case ZFS_PROP_REFRESERVATION:
|
||||
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);
|
||||
goto error;
|
||||
}
|
||||
break;
|
||||
|
||||
case ZFS_PROP_VOLSIZE:
|
||||
if (intval % blocksize != 0) {
|
||||
zfs_nicenum(blocksize, buf,
|
||||
@ -1499,6 +1509,61 @@ zfs_add_synthetic_resv(zfs_handle_t *zhp, nvlist_t *nvl)
|
||||
return (1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Helper for 'zfs {set|clone} refreservation=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 (prop != ZFS_PROP_REFRESERVATION) {
|
||||
return (0);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
(void) nvlist_remove_all(nvl, zfs_prop_to_name(prop));
|
||||
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)
|
||||
@ -1664,6 +1729,12 @@ zfs_prop_set_list(zfs_handle_t *zhp, nvlist_t *props)
|
||||
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().
|
||||
@ -3666,6 +3737,7 @@ zfs_clone(zfs_handle_t *zhp, const char *target, nvlist_t *props)
|
||||
|
||||
if (props) {
|
||||
zfs_type_t type;
|
||||
|
||||
if (ZFS_IS_VOLUME(zhp)) {
|
||||
type = ZFS_TYPE_VOLUME;
|
||||
} else {
|
||||
@ -3674,6 +3746,10 @@ zfs_clone(zfs_handle_t *zhp, const char *target, nvlist_t *props)
|
||||
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);
|
||||
|
@ -21,7 +21,7 @@
|
||||
|
||||
/*
|
||||
* 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.
|
||||
* Copyright (c) 2011, 2017 by Delphix. All rights reserved.
|
||||
* Copyright 2016 Igor Kozhukhov <ikozhukhov@gmail.com>
|
||||
* Copyright (c) 2017 Datto Inc.
|
||||
@ -1184,6 +1184,7 @@ zprop_parse_value(libzfs_handle_t *hdl, nvpair_t *elem, int prop,
|
||||
const char *propname;
|
||||
char *value;
|
||||
boolean_t isnone = B_FALSE;
|
||||
boolean_t isauto = B_FALSE;
|
||||
|
||||
if (type == ZFS_TYPE_POOL) {
|
||||
proptype = zpool_prop_get_type(prop);
|
||||
@ -1219,8 +1220,9 @@ zprop_parse_value(libzfs_handle_t *hdl, nvpair_t *elem, int prop,
|
||||
(void) nvpair_value_string(elem, &value);
|
||||
if (strcmp(value, "none") == 0) {
|
||||
isnone = B_TRUE;
|
||||
} else if (zfs_nicestrtonum(hdl, value, ivalp)
|
||||
!= 0) {
|
||||
} else if (strcmp(value, "auto") == 0) {
|
||||
isauto = B_TRUE;
|
||||
} else if (zfs_nicestrtonum(hdl, value, ivalp) != 0) {
|
||||
goto error;
|
||||
}
|
||||
} else if (datatype == DATA_TYPE_UINT64) {
|
||||
@ -1250,6 +1252,31 @@ zprop_parse_value(libzfs_handle_t *hdl, nvpair_t *elem, int prop,
|
||||
prop == ZFS_PROP_SNAPSHOT_LIMIT)) {
|
||||
*ivalp = UINT64_MAX;
|
||||
}
|
||||
|
||||
/*
|
||||
* Special handling for setting 'refreservation' to 'auto'. Use
|
||||
* UINT64_MAX to tell the caller to use zfs_fix_auto_resv().
|
||||
* 'auto' is only allowed on volumes.
|
||||
*/
|
||||
if (isauto) {
|
||||
switch (prop) {
|
||||
case ZFS_PROP_REFRESERVATION:
|
||||
if ((type & ZFS_TYPE_VOLUME) == 0) {
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"'%s=auto' only allowed on "
|
||||
"volumes"), nvpair_name(elem));
|
||||
goto error;
|
||||
}
|
||||
*ivalp = UINT64_MAX;
|
||||
break;
|
||||
default:
|
||||
zfs_error_aux(hdl, dgettext(TEXT_DOMAIN,
|
||||
"'auto' is invalid value for '%s'"),
|
||||
nvpair_name(elem));
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case PROP_TYPE_INDEX:
|
||||
|
@ -27,6 +27,7 @@
|
||||
.\" Copyright (c) 2014 by Adam Stevko. All rights reserved.
|
||||
.\" Copyright (c) 2014 Integros [integros.com]
|
||||
.\" Copyright 2017 Nexenta Systems, Inc.
|
||||
.\" Copyright 2018 Joyent, Inc.
|
||||
.\"
|
||||
.Dd December 6, 2017
|
||||
.Dt ZFS 1M
|
||||
@ -1345,7 +1346,7 @@ Limits the amount of space a dataset can consume.
|
||||
This property enforces a hard limit on the amount of space used.
|
||||
This hard limit does not include space used by descendents, including file
|
||||
systems and snapshots.
|
||||
.It Sy refreservation Ns = Ns Em size Ns | Ns Sy none
|
||||
.It Sy refreservation Ns = Ns Em size Ns | Ns Sy none Ns | Ns Sy auto
|
||||
The minimum amount of space guaranteed to a dataset, not including its
|
||||
descendents.
|
||||
When the amount of space used is below this value, the dataset is treated as if
|
||||
@ -1363,6 +1364,22 @@ this reservation to accommodate the current number of
|
||||
.Qq referenced
|
||||
bytes in the dataset.
|
||||
.Pp
|
||||
If
|
||||
.Sy refreservation
|
||||
is set to
|
||||
.Sy auto ,
|
||||
a volume is thick provisioned
|
||||
.Po or
|
||||
.Qq not sparse
|
||||
.Pc .
|
||||
.Sy refreservation Ns = Ns Sy auto
|
||||
is only supported on volumes.
|
||||
See
|
||||
.Sy volsize
|
||||
in the
|
||||
.Sx Native Properties
|
||||
section for more information about sparse volumes.
|
||||
.Pp
|
||||
This property can also be referred to by its shortened column name,
|
||||
.Sy refreserv .
|
||||
.It Sy reservation Ns = Ns Em size Ns | Ns Sy none
|
||||
@ -1577,22 +1594,39 @@ Extreme care should be used when adjusting the volume size.
|
||||
Though not recommended, a
|
||||
.Qq sparse volume
|
||||
.Po also known as
|
||||
.Qq thin provisioning
|
||||
.Qq thin provisioned
|
||||
.Pc
|
||||
can be created by specifying the
|
||||
.Fl s
|
||||
option to the
|
||||
.Nm zfs Cm create Fl V
|
||||
command, or by changing the reservation after the volume has been created.
|
||||
command, or by changing the value of the
|
||||
.Sy refreservation
|
||||
property
|
||||
.Po or
|
||||
.Sy reservation
|
||||
property on pool version 8 or earlier
|
||||
.Pc
|
||||
after the volume has been created.
|
||||
A
|
||||
.Qq sparse volume
|
||||
is a volume where the reservation is less then the volume size.
|
||||
is a volume where the value of
|
||||
.Sy refreservation
|
||||
is less than the size of the volume plus the space required to store its
|
||||
metadata.
|
||||
Consequently, writes to a sparse volume can fail with
|
||||
.Er ENOSPC
|
||||
when the pool is low on space.
|
||||
For a sparse volume, changes to
|
||||
.Sy volsize
|
||||
are not reflected in the reservation.
|
||||
are not reflected in the
|
||||
.Sy refreservation.
|
||||
A volume that is not sparse is said to be
|
||||
.Qq thick provisioned .
|
||||
A sparse volume can become thick provisioned by setting
|
||||
.Sy refreservation
|
||||
to
|
||||
.Sy auto .
|
||||
.It Sy vscan Ns = Ns Sy on Ns | Ns Sy off
|
||||
Controls whether regular files should be scanned for viruses when a file is
|
||||
opened and closed.
|
||||
|
Loading…
Reference in New Issue
Block a user