Handle interaction between gang blocks, copies, and FDT.

With the advent of fast dedup, there are no longer separate dedup tables
for different copies values. There is now logic that will add DVAs to
the dedup table entry if more copies are needed for new writes. However,
this interacts poorly with ganging. There are two different cases that
can result in mixed gang/non-gang BPs, which are illegal in ZFS.

This change modifies updates of existing FDT; if there are already gang
DVAs in the FDT, we prevent the new write from extending the DDT
entry. We cannot safely mix different gang trees in one block
pointer. if there are non-gang DVAs in the FDT, then this allocation may
not be gangs. If it would gang, we have to redo the whole write as a
non-dedup write.

This change also fixes a refcount leak that could occur if the lead DDT
write failed.

Sponsored by: iXsystems, Inc.
Sponsored-by: Klara, Inc.
Reviewed-by: Alexander Motin <mav@FreeBSD.org>
Reviewed-by: Tony Hutter <hutter2@llnl.gov>
Signed-off-by: Paul Dagnelie <paul.dagnelie@klarasystems.com>
Closes: #17123
This commit is contained in:
Paul Dagnelie
2025-04-21 08:26:30 -07:00
committed by GitHub
parent 1d8f625233
commit 5f5321effa
6 changed files with 156 additions and 14 deletions
+1 -1
View File
@@ -726,7 +726,7 @@ 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']
tests = ['gang_blocks_redundant', 'gang_blocks_ddt_copies']
tags = ['functional', 'gang_blocks']
[tests/functional/grow]
+1
View File
@@ -1561,6 +1561,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_ddt_copies.ksh \
functional/gang_blocks/gang_blocks_redundant.ksh \
functional/gang_blocks/setup.ksh \
functional/grow/grow_pool_001_pos.ksh \
@@ -0,0 +1,79 @@
#!/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 mixed gang blocks and copies interact correctly in FDT
#
# Strategy:
# 1. Store a block with copies = 1 in the DDT unganged.
# 2. Add a new entry with copies = 2 that gangs, ensure it doesn't panic
# 3. Store a block with copies = 1 in the DDT ganged.
# 4. Add a new entry with copies = 3 that doesn't gang, ensure that it doesn't panic.
#
. $STF_SUITE/include/libtest.shlib
. $STF_SUITE/tests/functional/gang_blocks/gang_blocks.kshlib
log_assert "Verify that mixed gang blocks and copies interact correctly in FDT"
save_tunable DEDUP_LOG_TXG_MAX
function cleanup2
{
zfs destroy $TESTPOOL/fs1
zfs destroy $TESTPOOL/fs2
restore_tunable DEDUP_LOG_TXG_MAX
cleanup
}
preamble
log_onexit cleanup2
log_must zpool create -f -o ashift=9 -o feature@block_cloning=disabled $TESTPOOL $DISKS
log_must zfs create -o recordsize=64k -o dedup=on $TESTPOOL/fs1
log_must zfs create -o recordsize=64k -o dedup=on -o copies=3 $TESTPOOL/fs2
set_tunable32 DEDUP_LOG_TXG_MAX 1
log_must dd if=/dev/urandom of=/$TESTPOOL/fs1/f1 bs=64k count=1
log_must sync_pool $TESTPOOL
set_tunable32 METASLAB_FORCE_GANGING 20000
set_tunable32 METASLAB_FORCE_GANGING_PCT 100
log_must dd if=/$TESTPOOL/fs1/f1 of=/$TESTPOOL/fs2/f1 bs=64k count=1
log_must sync_pool $TESTPOOL
log_must rm /$TESTPOOL/fs*/f1
log_must sync_pool $TESTPOOL
log_must dd if=/dev/urandom of=/$TESTPOOL/fs1/f1 bs=64k count=1
log_must sync_pool $TESTPOOL
log_must zdb -D $TESTPOOL
set_tunable32 METASLAB_FORCE_GANGING_PCT 0
log_must dd if=/$TESTPOOL/fs1/f1 of=/$TESTPOOL/fs2/f1 bs=64k count=1
log_must sync_pool $TESTPOOL
log_must rm /$TESTPOOL/fs*/f1
log_must sync_pool $TESTPOOL
set_tunable32 METASLAB_FORCE_GANGING_PCT 50
set_tunable32 METASLAB_FORCE_GANGING 40000
log_must dd if=/dev/urandom of=/$TESTPOOL/f1 bs=64k count=1
for i in `seq 1 16`; do
log_must cp /$TESTPOOL/f1 /$TESTPOOL/fs2/f1
log_must cp /$TESTPOOL/f1 /$TESTPOOL/fs1/f1
log_must sync_pool $TESTPOOL
log_must zdb -D $TESTPOOL
done
log_pass "Verify that mixed gang blocks and copies interact correctly in FDT"