From eeeb0ba9a562fb3647751409bb2aebe91815f64d Mon Sep 17 00:00:00 2001 From: Alex John Date: Sun, 12 Apr 2020 00:16:49 +0800 Subject: [PATCH] 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. Reported-by: puffi Signed-off-by: Alex John --- cmd/zfs/zfs_main.c | 23 +++++++++++++++++++ man/man8/zfs-create.8 | 3 +-- .../cli_root/zfs_create/zfs_create.cfg | 8 ++++++- .../zfs_create/zfs_create_002_pos.ksh | 14 +++++++++++ 4 files changed, 45 insertions(+), 3 deletions(-) diff --git a/cmd/zfs/zfs_main.c b/cmd/zfs/zfs_main.c index ae71cdc881fe..a9c4ca0bc21b 100644 --- a/cmd/zfs/zfs_main.c +++ b/cmd/zfs/zfs_main.c @@ -1038,6 +1038,29 @@ 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) + nomem(); + } + } + + if (type == ZFS_TYPE_VOLUME && !noreserve) { uint64_t spa_version; zfs_prop_t resv_prop; diff --git a/man/man8/zfs-create.8 b/man/man8/zfs-create.8 index 6aef2bb572d7..24ad77d021b6 100644 --- a/man/man8/zfs-create.8 +++ b/man/man8/zfs-create.8 @@ -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 diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create.cfg b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create.cfg index b96908ce12c7..9bf25327ef8d 100644 --- a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create.cfg +++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create.cfg @@ -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" diff --git a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_002_pos.ksh b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_002_pos.ksh index 6f36b40bfd59..cabe984ca2d3 100755 --- a/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_002_pos.ksh +++ b/tests/zfs-tests/tests/functional/cli_root/zfs_create/zfs_create_002_pos.ksh @@ -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" @@ -78,4 +81,15 @@ while (( $j < ${#size[*]} )); do ((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 ' works as expected."