From c04bd0855772fe13ff3283b07b518fd6019cec7d Mon Sep 17 00:00:00 2001 From: Don Brady Date: Wed, 17 May 2023 15:13:41 -0600 Subject: [PATCH] Allow opt-in of zvol blocks in special class Signed-off-by: Don Brady --- man/man7/zfsprops.7 | 4 +- man/man7/zpoolconcepts.7 | 5 +- module/zcommon/zfs_prop.c | 3 +- module/zfs/dmu.c | 3 +- module/zfs/spa_misc.c | 6 +- tests/runfiles/common.run | 3 +- tests/zfs-tests/tests/Makefile.am | 1 + .../alloc_class/alloc_class_016_pos.ksh | 59 +++++++++++++++++++ 8 files changed, 74 insertions(+), 10 deletions(-) create mode 100755 tests/zfs-tests/tests/functional/alloc_class/alloc_class_016_pos.ksh diff --git a/man/man7/zfsprops.7 b/man/man7/zfsprops.7 index 8f6b919cfc..7c4af89a07 100644 --- a/man/man7/zfsprops.7 +++ b/man/man7/zfsprops.7 @@ -1216,12 +1216,12 @@ This feature must be enabled to be used .Pc . .It Sy special_small_blocks Ns = Ns Ar size This value represents the threshold block size for including small file -blocks into the special allocation class. +or zvol blocks into the special allocation class. Blocks smaller than or equal to this value will be assigned to the special allocation class while greater blocks will be assigned to the regular class. Valid values are zero or a power of two from 512 up to 1048576 (1 MiB). -The default size is 0 which means no small file blocks +The default size is 0 which means no small file or zvol blocks will be allocated in the special class. .Pp Before setting this property, a special class vdev must be added to the diff --git a/man/man7/zpoolconcepts.7 b/man/man7/zpoolconcepts.7 index db3fd49262..9a9e5aae9f 100644 --- a/man/man7/zpoolconcepts.7 +++ b/man/man7/zpoolconcepts.7 @@ -489,7 +489,8 @@ current state of the pool won't be scanned during a scrub. Allocations in the special class are dedicated to specific block types. By default, this includes all metadata, the indirect blocks of user data, and any deduplication tables. -The class can also be provisioned to accept small file blocks. +The class can also be provisioned to accept small file blocks or zvol blocks +on a per dataset granularity. .Pp A pool must always have at least one normal .Pq non- Ns Sy dedup Ns /- Ns Sy special @@ -504,7 +505,7 @@ Deduplication tables can be excluded from the special class by unsetting the .Sy zfs_ddt_data_is_special ZFS module parameter. .Pp -Inclusion of small file blocks in the special class is opt-in. +Inclusion of small file or zvol blocks in the special class is opt-in. Each dataset can control the size of small file blocks allowed in the special class by setting the .Sy special_small_blocks diff --git a/module/zcommon/zfs_prop.c b/module/zcommon/zfs_prop.c index 3db6fd13f4..518e8bd6eb 100644 --- a/module/zcommon/zfs_prop.c +++ b/module/zcommon/zfs_prop.c @@ -687,7 +687,8 @@ zfs_prop_init(void) ZFS_TYPE_FILESYSTEM, "512 to 1M, power of 2", "RECSIZE", B_FALSE, sfeatures); zprop_register_number(ZFS_PROP_SPECIAL_SMALL_BLOCKS, - "special_small_blocks", 0, PROP_INHERIT, ZFS_TYPE_FILESYSTEM, + "special_small_blocks", 0, PROP_INHERIT, + ZFS_TYPE_FILESYSTEM | ZFS_TYPE_VOLUME, "zero or 512 to 1M, power of 2", "SPECIAL_SMALL_BLOCKS", B_FALSE, sfeatures); diff --git a/module/zfs/dmu.c b/module/zfs/dmu.c index 8a13b8f410..517b5efa25 100644 --- a/module/zfs/dmu.c +++ b/module/zfs/dmu.c @@ -2109,7 +2109,8 @@ dmu_write_policy(objset_t *os, dnode_t *dn, int level, int wp, zio_prop_t *zp) memset(zp->zp_salt, 0, ZIO_DATA_SALT_LEN); memset(zp->zp_iv, 0, ZIO_DATA_IV_LEN); memset(zp->zp_mac, 0, ZIO_DATA_MAC_LEN); - zp->zp_zpl_smallblk = DMU_OT_IS_FILE(zp->zp_type) ? + zp->zp_zpl_smallblk = (DMU_OT_IS_FILE(zp->zp_type) || + zp->zp_type == DMU_OT_ZVOL) ? os->os_zpl_special_smallblock : 0; ASSERT3U(zp->zp_compress, !=, ZIO_COMPRESS_INHERIT); diff --git a/module/zfs/spa_misc.c b/module/zfs/spa_misc.c index 54a0eeccf2..ca773b2c2b 100644 --- a/module/zfs/spa_misc.c +++ b/module/zfs/spa_misc.c @@ -1980,11 +1980,11 @@ spa_preferred_class(spa_t *spa, uint64_t size, dmu_object_type_t objtype, } /* - * Allow small file blocks in special class in some cases (like - * for the dRAID vdev feature). But always leave a reserve of + * Allow small file or zvol blocks in special class if opted in by + * the special_smallblk property. However, always leave a reserve of * zfs_special_class_metadata_reserve_pct exclusively for metadata. */ - if (DMU_OT_IS_FILE(objtype) && + if ((DMU_OT_IS_FILE(objtype) || objtype == DMU_OT_ZVOL) && has_special_class && size <= special_smallblk) { metaslab_class_t *special = spa_special_class(spa); uint64_t alloc = metaslab_class_get_alloc(special); diff --git a/tests/runfiles/common.run b/tests/runfiles/common.run index 1665e20e0e..a6a2381c79 100644 --- a/tests/runfiles/common.run +++ b/tests/runfiles/common.run @@ -37,7 +37,8 @@ tests = ['alloc_class_001_pos', 'alloc_class_002_neg', 'alloc_class_003_pos', 'alloc_class_004_pos', 'alloc_class_005_pos', 'alloc_class_006_pos', 'alloc_class_007_pos', 'alloc_class_008_pos', 'alloc_class_009_pos', 'alloc_class_010_pos', 'alloc_class_011_neg', 'alloc_class_012_pos', - 'alloc_class_013_pos', 'alloc_class_014_neg', 'alloc_class_015_pos'] + 'alloc_class_013_pos', 'alloc_class_014_neg', 'alloc_class_015_pos', + 'alloc_class_016_pos'] tags = ['functional', 'alloc_class'] [tests/functional/append] diff --git a/tests/zfs-tests/tests/Makefile.am b/tests/zfs-tests/tests/Makefile.am index a4932fc988..18275487e2 100644 --- a/tests/zfs-tests/tests/Makefile.am +++ b/tests/zfs-tests/tests/Makefile.am @@ -417,6 +417,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \ functional/alloc_class/alloc_class_013_pos.ksh \ functional/alloc_class/alloc_class_014_neg.ksh \ functional/alloc_class/alloc_class_015_pos.ksh \ + functional/alloc_class/alloc_class_016_pos.ksh \ functional/alloc_class/cleanup.ksh \ functional/alloc_class/setup.ksh \ functional/append/file_append.ksh \ diff --git a/tests/zfs-tests/tests/functional/alloc_class/alloc_class_016_pos.ksh b/tests/zfs-tests/tests/functional/alloc_class/alloc_class_016_pos.ksh new file mode 100755 index 0000000000..1dfd19449d --- /dev/null +++ b/tests/zfs-tests/tests/functional/alloc_class/alloc_class_016_pos.ksh @@ -0,0 +1,59 @@ +#!/bin/ksh -p + +# +# This file and its contents are supplied under the terms of the +# Common Development and Distribution License ("CDDL"), version 1.0. +# You may only use this file in accordance with the terms of version +# 1.0 of the CDDL. +# +# A full copy of the text of the CDDL should have accompanied this +# source. A copy of the CDDL is also available via the Internet at +# http://www.illumos.org/license/CDDL. +# + +. $STF_SUITE/tests/functional/alloc_class/alloc_class.kshlib + +# +# DESCRIPTION: +# File blocks and zvol blocks, where special_small_blocks is active, +# are expected to end up in the special class. +# + +verify_runnable "global" + +claim="File and zvol blocks using special_small_blocks end up in special class" + +log_assert $claim +log_onexit cleanup +log_must disk_setup + +log_must zpool create $TESTPOOL $ZPOOL_DISKS special $CLASS_DISK0 + +# Provision a filesystem with special_small_blocks and copy 10M to it +log_must zfs create -o compression=off -o special_small_blocks=32K \ + -o recordsize=32K $TESTPOOL/$TESTFS +log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS/testfile bs=1M count=10 + +# Provision a volume with special_small_blocks and copy 10M to it +log_must zfs create -V 100M -b 32K -o special_small_blocks=32K \ + -o compression=off $TESTPOOL/$TESTVOL +block_device_wait "$ZVOL_DEVDIR/$TESTPOOL/$TESTVOL" +log_must dd if=/dev/urandom of=$ZVOL_DEVDIR/$TESTPOOL/$TESTVOL bs=1M count=10 + +sync_pool $TESTPOOL +zpool list -v $TESTPOOL + +# Get the amount allocated to special vdev using vdev 'allocated' property +result=$(zpool get -Hp allocated $TESTPOOL $CLASS_DISK0) +set -- $result +allocated=$3 +echo $allocated bytes allocated on special device $CLASS_DISK0 + +# Confirm that at least 20M was allocated +if [[ $allocated -lt 20971520 ]] +then + log_fail "$allocated on special vdev $CLASS_DISK0, but expecting 20M" +fi + +log_must zpool destroy -f "$TESTPOOL" +log_pass $claim