zfs_create: round up volume size to multiple of bs

Round up the volume size requested in `zfs create -V size` to the next
higher multiple of the volblocksize. Updates the man page and adds a
test to verify the new behavior.

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reported-by: puffi <puffi@users.noreply.github.com>
Signed-off-by: Alex John <alex@stty.io>
Closes #8541 
Closes #10196
This commit is contained in:
alex 2020-04-25 10:04:34 +08:00 committed by GitHub
parent aa646323db
commit 47c9299fcc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 46 additions and 4 deletions

View File

@ -1038,6 +1038,31 @@ zfs_do_create(int argc, char **argv)
}
}
/*
* if volsize is not a multiple of volblocksize, round it up to the
* nearest multiple of the volblocksize
*/
if (type == ZFS_TYPE_VOLUME) {
uint64_t volblocksize;
if (nvlist_lookup_uint64(props,
zfs_prop_to_name(ZFS_PROP_VOLBLOCKSIZE),
&volblocksize) != 0)
volblocksize = ZVOL_DEFAULT_BLOCKSIZE;
if (volsize % volblocksize) {
volsize = P2ROUNDUP_TYPED(volsize, volblocksize,
uint64_t);
if (nvlist_add_uint64(props,
zfs_prop_to_name(ZFS_PROP_VOLSIZE), volsize) != 0) {
nvlist_free(props);
nomem();
}
}
}
if (type == ZFS_TYPE_VOLUME && !noreserve) {
uint64_t spa_version;
zfs_prop_t resv_prop;

View File

@ -143,8 +143,7 @@ The size represents the logical size as exported by the device.
By default, a reservation of equal size is created.
.Pp
.Ar size
is automatically rounded up to the nearest 128 Kbytes to ensure that the volume
has an integral number of blocks regardless of
is automatically rounded up to the nearest multiple of the
.Sy blocksize .
.Bl -tag -width "-b"
.It Fl b Ar blocksize

View File

@ -54,6 +54,12 @@ export VOL_LIMIT_KEYWORD1="1TB on 32-bit"
export VOL_LIMIT_KEYWORD2="value is too large"
export VOL_LIMIT_KEYWORD3="volume size exceeds limit"
set -A size "8k" "8K" "1m" "1M" "1mb" "1mB" "1Mb" "1MB" "1g" "1G" \
set -A size "8k" "8K" "35K" "1m" "1M" "1mb" "1mB" "1Mb" "1MB" "1g" "1G" \
"1p" "1P" "1z" "1Z" "1gb" "1gB" "1Gb" "1GB" "1pb" "1pB" "1Pb" \
"1PB" "1zb" "1zB" "1Zb" "1ZB"
# If a datasize has a volume size that is not a multiple of the blocksize,
# explicitly check that its size has been rounded up to the nearest multiple
# The volume with the exact size must exist in the "size" array above
set -A explicit_size_check "35K"
set -A expected_rounded_size "40960"

View File

@ -31,6 +31,7 @@
. $STF_SUITE/include/libtest.shlib
. $STF_SUITE/tests/functional/cli_root/zfs_create/zfs_create.cfg
. $STF_SUITE/tests/functional/cli_root/zfs_create/zfs_create_common.kshlib
#
# DESCRIPTION:
@ -39,6 +40,8 @@
# STRATEGY:
# 1. Create a volume in the storage pool.
# 2. Verify the volume is created correctly.
# 3. Verify that the volume created has its volsize rounded to the nearest
# multiple of the blocksize (in this case, the default blocksize)
#
verify_runnable "global"
@ -76,6 +79,15 @@ while (( $j < ${#size[*]} )); do
fi
((j = j + 1))
done
typeset -i j=0
while (( $j < ${#explicit_size_check[*]} )); do
propertycheck ${TESTPOOL}/${TESTVOL}${explicit_size_check[j]} \
volsize=${expected_rounded_size[j]} || \
log_fail "volsize ${size[j]} was not rounded up"
((j = j + 1))
done
log_pass "'zfs create -s -V <size> <volume>' works as expected."