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