Allow opt-in of zvol blocks in special class

Reviewed-by: Brian Behlendorf <behlendorf1@llnl.gov>
Reviewed-by: Alexander Motin <mav@FreeBSD.org>
Reviewed-by: Kjeld Schouten <kjeld@schouten-lebbing.nl>
Signed-off-by: Don Brady <dev.fs.zfs@gmail.com>
Closes #14876
This commit is contained in:
Don Brady 2025-05-24 14:44:26 -06:00 committed by GitHub
parent 9d76950d67
commit b048bfa9c1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 75 additions and 10 deletions

View File

@ -1281,12 +1281,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

View File

@ -488,7 +488,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
@ -503,7 +504,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

View File

@ -737,7 +737,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);

View File

@ -2489,7 +2489,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;
zp->zp_storage_type = dn ? dn->dn_storage_type : DMU_OT_NONE;

View File

@ -2064,11 +2064,11 @@ spa_preferred_class(spa_t *spa, const zio_t *zio)
}
/*
* 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 && zio->io_size <= zp->zp_zpl_smallblk) {
metaslab_class_t *special = spa_special_class(spa);
uint64_t alloc = metaslab_class_get_alloc(special);

View File

@ -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]

View File

@ -429,6 +429,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 \

View File

@ -0,0 +1,60 @@
#!/bin/ksh -p
# SPDX-License-Identifier: CDDL-1.0
#
# 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