Implement allocation size ranges and use for gang leaves (#17111)

When forced to resort to ganging, ZFS currently allocates three child
blocks, each one third of the size of the original. This is true
regardless of whether larger allocations could be made, which would
allow us to have fewer gang leaves. This improves performance when
fragmentation is high enough to require ganging, but not so high that
all the free ranges are only just big enough to hold a third of the
recordsize. This is also useful for improving the behavior of a future
change to allow larger gang headers.

We add the ability for the allocation codepath to allocate a range of
sizes instead of a single fixed size. We then use this to pre-allocate
the DVAs for the gang children. If those allocations fail, we fall back
to the normal write path, which will likely re-gang.

Signed-off-by: Paul Dagnelie <paul.dagnelie@klarasystems.com>
Co-authored-by: Paul Dagnelie <paul.dagnelie@klarasystems.com>
Reviewed-by: Alexander Motin <mav@FreeBSD.org>
Reviewed-by: Tony Hutter <hutter2@llnl.gov>
This commit is contained in:
Paul Dagnelie
2025-05-02 15:32:18 -07:00
committed by GitHub
parent a7de203c86
commit 246e5883bb
24 changed files with 392 additions and 107 deletions
+2 -1
View File
@@ -726,7 +726,8 @@ tests = ['large_dnode_001_pos', 'large_dnode_003_pos', 'large_dnode_004_neg',
tags = ['functional', 'features', 'large_dnode']
[tests/functional/gang_blocks]
tests = ['gang_blocks_redundant', 'gang_blocks_ddt_copies']
tests = ['gang_blocks_001_pos', 'gang_blocks_redundant',
'gang_blocks_ddt_copies']
tags = ['functional', 'gang_blocks']
[tests/functional/grow]
+4
View File
@@ -428,6 +428,10 @@ tests = ['large_dnode_003_pos', 'large_dnode_004_neg',
'large_dnode_005_pos', 'large_dnode_007_neg']
tags = ['functional', 'features', 'large_dnode']
[tests/functional/gang_blocks]
tests = ['gang_blocks_001_pos']
tags = ['functional', 'gang_blocks']
[tests/functional/grow]
pre =
post =
+1
View File
@@ -1562,6 +1562,7 @@ nobase_dist_datadir_zfs_tests_tests_SCRIPTS += \
functional/features/large_dnode/large_dnode_009_pos.ksh \
functional/features/large_dnode/setup.ksh \
functional/gang_blocks/cleanup.ksh \
functional/gang_blocks/gang_blocks_001_pos.ksh \
functional/gang_blocks/gang_blocks_ddt_copies.ksh \
functional/gang_blocks/gang_blocks_redundant.ksh \
functional/gang_blocks/setup.ksh \
@@ -0,0 +1,59 @@
#!/bin/ksh
# 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.
#
#
# Copyright (c) 2025 by Klara Inc.
#
#
# Description:
# Verify that gang block functionality behaves correctly.
#
# Strategy:
# 1. Create a pool without dynamic gang headers.
# 2. Set metaslab_force_ganging to force gang blocks to be created.
# 3. Verify that gang blocks can be read, written, and freed.
#
. $STF_SUITE/include/libtest.shlib
. $STF_SUITE/tests/functional/gang_blocks/gang_blocks.kshlib
log_assert "Gang blocks behave correctly."
preamble
log_onexit cleanup
log_must zpool create -f $TESTPOOL $DISKS
log_must zfs create -o recordsize=128k $TESTPOOL/$TESTFS
mountpoint=$(get_prop mountpoint $TESTPOOL/$TESTFS)
set_tunable64 METASLAB_FORCE_GANGING 100000
set_tunable32 METASLAB_FORCE_GANGING_PCT 100
path="${mountpoint}/file"
log_must dd if=/dev/urandom of=$path bs=128k count=1
log_must zpool sync $TESTPOOL
first_block=$(get_first_block_dva $TESTPOOL/$TESTFS file)
leaves=$(read_gang_header $TESTPOOL $first_block 200 | grep -v hole | wc -l)
[[ "$leaves" -gt 1 ]] || log_fail "Only one leaf in gang block, should not be possible"
orig_checksum="$(cat $path | xxh128digest)"
log_must verify_pool $TESTPOOL
log_must zinject -a
new_checksum="$(cat $path | xxh128digest)"
[[ "$orig_checksum" == "$new_checksum" ]] || log_fail "Checksum mismatch"
log_must rm $path
log_must verify_pool $TESTPOOL
log_pass "Gang blocks behave correctly."