1#!/bin/ksh -p 2# SPDX-License-Identifier: CDDL-1.0 3# 4# This file and its contents are supplied under the terms of the 5# Common Development and Distribution License ("CDDL"), version 1.0. 6# You may only use this file in accordance with the terms of version 7# 1.0 of the CDDL. 8# 9# A full copy of the text of the CDDL should have accompanied this 10# source. A copy of the CDDL is also available via the Internet at 11# https://opensource.org/license/CDDL-1.0. 12# 13 14# 15# Copyright (c) 2023, Kay Pedersen <mail@mkwg.de> 16# 17 18. $STF_SUITE/include/libtest.shlib 19. $STF_SUITE/tests/functional/block_cloning/block_cloning.kshlib 20. $STF_SUITE/tests/functional/bclone/bclone_common.kshlib 21 22verify_runnable "global" 23 24verify_crossfs_block_cloning 25 26claim="Block cloning across encrypted datasets." 27 28log_assert $claim 29 30DS1="$TESTPOOL/encrypted1" 31DS2="$TESTPOOL/encrypted2" 32DS1_NC="$TESTPOOL/notcrypted1" 33PASSPHRASE="top_secret" 34 35function prepare_enc 36{ 37 log_must zpool create -o feature@block_cloning=enabled $TESTPOOL $DISKS 38 log_must eval "echo $PASSPHRASE | zfs create -o encryption=on" \ 39 "-o keyformat=passphrase -o keylocation=prompt $DS1" 40 log_must eval "echo $PASSPHRASE | zfs create -o encryption=on" \ 41 "-o keyformat=passphrase -o keylocation=prompt $DS2" 42 log_must zfs create $DS1/child1 43 log_must zfs create $DS1/child2 44 log_must zfs create $DS1_NC 45 46 log_note "Create test file" 47 # we must wait until the src file txg is written to the disk otherwise we 48 # will fallback to normal copy. See "dmu_read_l0_bps" in 49 # "zfs/module/zfs/dmu.c" and "zfs_clone_range" in 50 # "zfs/module/zfs/zfs_vnops.c" 51 log_must dd if=/dev/urandom of=/$DS1/file bs=128K count=4 52 log_must dd if=/dev/urandom of=/$DS1/child1/file bs=128K count=4 53 log_must dd if=/dev/urandom of=/$DS1_NC/file bs=128K count=4 54 log_must sync_pool $TESTPOOL 55} 56 57function cleanup_enc 58{ 59 datasetexists $TESTPOOL && destroy_pool $TESTPOOL 60} 61 62function clone_and_check 63{ 64 I_FILE="$1" 65 O_FILE=$2 66 I_DS=$3 67 O_DS=$4 68 SAME_BLOCKS=$5 69 # the CLONE option provides a choice between copy_file_range 70 # which should clone and a dd which is a copy no matter what 71 CLONE=$6 72 SNAPSHOT=$7 73 if [ ${#SNAPSHOT} -gt 0 ]; then 74 I_FILE=".zfs/snapshot/$SNAPSHOT/$1" 75 fi 76 if [ $CLONE ]; then 77 log_must clonefile -f "/$I_DS/$I_FILE" "/$O_DS/$O_FILE" 0 0 524288 78 else 79 log_must dd if="/$I_DS/$I_FILE" of="/$O_DS/$O_FILE" bs=128K 80 fi 81 log_must sync_pool $TESTPOOL 82 83 log_must have_same_content "/$I_DS/$I_FILE" "/$O_DS/$O_FILE" 84 85 if [ ${#SNAPSHOT} -gt 0 ]; then 86 I_DS="$I_DS@$SNAPSHOT" 87 I_FILE="$1" 88 fi 89 typeset blocks=$(get_same_blocks \ 90 $I_DS $I_FILE $O_DS $O_FILE $PASSPHRASE) 91 log_must [ "$blocks" = "$SAME_BLOCKS" ] 92} 93 94log_onexit cleanup_enc 95 96prepare_enc 97 98log_note "Cloning entire file with copy_file_range across different enc" \ 99 "roots, should fallback" 100# we are expecting no same block map. 101clone_and_check "file" "clone" $DS1 $DS2 "" true 102log_note "check if the file is still readable and the same after" \ 103 "unmount and key unload, shouldn't fail" 104typeset hash1=$(xxh128digest "/$DS1/file") 105log_must zfs umount $DS1 && zfs unload-key $DS1 106typeset hash2=$(xxh128digest "/$DS2/clone") 107log_must [ "$hash1" = "$hash2" ] 108 109cleanup_enc 110prepare_enc 111 112log_note "Cloning entire file with copy_file_range across different child datasets" 113# clone shouldn't work because of deriving a new master key for the child 114# we are expecting no same block map. 115clone_and_check "file" "clone" $DS1 "$DS1/child1" "" true 116clone_and_check "file" "clone" "$DS1/child1" "$DS1/child2" "" true 117 118cleanup_enc 119prepare_enc 120 121log_note "Copying entire file with copy_file_range across same snapshot" 122log_must zfs snapshot -r $DS1@s1 123log_must sync_pool $TESTPOOL 124log_must rm -f "/$DS1/file" 125log_must sync_pool $TESTPOOL 126clone_and_check "file" "clone" "$DS1" "$DS1" "0 1 2 3" true "s1" 127 128cleanup_enc 129prepare_enc 130 131log_note "Copying entire file with copy_file_range across different snapshot" 132clone_and_check "file" "file" $DS1 $DS2 "" true 133log_must zfs snapshot -r $DS2@s1 134log_must sync_pool $TESTPOOL 135log_must rm -f "/$DS1/file" "/$DS2/file" 136log_must sync_pool $TESTPOOL 137clone_and_check "file" "clone" "$DS2" "$DS1" "" true "s1" 138typeset hash1=$(xxh128digest "/$DS1/.zfs/snapshot/s1/file") 139log_note "destroy the snapshot and check if the file is still readable and" \ 140 "has the same content" 141log_must zfs destroy -r $DS2@s1 142log_must sync_pool $TESTPOOL 143typeset hash2=$(xxh128digest "/$DS1/file") 144log_must [ "$hash1" = "$hash2" ] 145 146cleanup_enc 147prepare_enc 148 149log_note "Copying with copy_file_range from non encrypted to encrypted" 150clone_and_check "file" "copy" $DS1_NC $DS1 "" true 151 152cleanup_enc 153prepare_enc 154 155log_note "Copying with copy_file_range from encrypted to non encrypted" 156clone_and_check "file" "copy" $DS1 $DS1_NC "" true 157 158log_must sync_pool $TESTPOOL 159 160log_pass $claim 161