1#!/bin/ksh
2
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# http://www.illumos.org/license/CDDL.
12#
13
14#
15# Copyright (c) 2019, Lawrence Livermore National Security, LLC.
16# Copyright (c) 2021, George Amanakis. All rights reserved.
17#
18
19. $STF_SUITE/include/libtest.shlib
20. $STF_SUITE/include/properties.shlib
21. $STF_SUITE/tests/functional/rsend/rsend.kshlib
22
23#
24# Description:
25# Verify encrypted raw sending to pools with greater ashift succeeds.
26#
27# Strategy:
28# 1) Create a set of files each containing some file data in an
29#	encrypted filesystem.
30# 2) Snapshot and raw send these files to a pool with greater ashift
31# 3) Verify that all the xattrs (and thus the spill block) were
32#    preserved when receiving the incremental stream.
33# 4) Repeat the test for a non-encrypted filesystem using raw send
34#
35
36verify_runnable "both"
37
38log_assert "Verify raw sending to pools with greater ashift succeeds"
39
40if is_freebsd; then
41	log_unsupported "Runs too long on FreeBSD 14 (Issue #14961)"
42fi
43
44function cleanup
45{
46	rm -f $BACKDIR/fs@*
47	poolexists pool9 && destroy_pool pool9
48	poolexists pool12 && destroy_pool pool12
49	log_must rm -f $TESTDIR/vdev_a $TESTDIR/vdev_b
50}
51
52function xattr_test
53{
54	log_must zfs set xattr=sa pool9/$1
55	log_must zfs set dnodesize=legacy pool9/$1
56	log_must zfs set recordsize=128k pool9/$1
57	rand_set_prop pool9/$1 compression "${compress_prop_vals[@]}"
58
59	# Create 40 files each with a spill block containing xattrs.  Each file
60	# will be modified in a different way to validate the incremental receive.
61	for i in {1..40}; do
62		file="/pool9/$1/file$i"
63
64		log_must mkfile 16384 $file
65		for j in {1..20}; do
66			log_must set_xattr "testattr$j" "$attrvalue" $file
67		done
68	done
69
70	# Snapshot the pool and send it to the new dataset.
71	log_must zfs snapshot pool9/$1@snap1
72	log_must eval "zfs send -w pool9/$1@snap1 >$BACKDIR/$1@snap1"
73	log_must eval "zfs recv pool12/$1 < $BACKDIR/$1@snap1"
74
75	#
76	# Modify file[1-6]'s contents but not the spill blocks.
77	#
78	# file1 - Increase record size; single block
79	# file2 - Increase record size; multiple blocks
80	# file3 - Truncate file to zero size; single block
81	# file4 - Truncate file to smaller size; single block
82	# file5 - Truncate file to much larger size; add holes
83	# file6 - Truncate file to embedded size; embedded data
84	#
85	log_must mkfile 32768 /pool9/$1/file1
86	log_must mkfile 1048576 /pool9/$1/file2
87	log_must truncate -s 0 /pool9/$1/file3
88	log_must truncate -s 8192 /pool9/$1/file4
89	log_must truncate -s 1073741824 /pool9/$1/file5
90	log_must truncate -s 50 /pool9/$1/file6
91
92	#
93	# Modify file[11-16]'s contents and their spill blocks.
94	#
95	# file11 - Increase record size; single block
96	# file12 - Increase record size; multiple blocks
97	# file13 - Truncate file to zero size; single block
98	# file14 - Truncate file to smaller size; single block
99	# file15 - Truncate file to much larger size; add holes
100	# file16 - Truncate file to embedded size; embedded data
101	#
102	log_must mkfile 32768 /pool9/$1/file11
103	log_must mkfile 1048576 /pool9/$1/file12
104	log_must truncate -s 0 /pool9/$1/file13
105	log_must truncate -s 8192 /pool9/$1/file14
106	log_must truncate -s 1073741824 /pool9/$1/file15
107	log_must truncate -s 50 /pool9/$1/file16
108
109	for i in {11..20}; do
110		log_must rm_xattr testattr1 /pool9/$1/file$i
111	done
112
113	#
114	# Modify file[21-26]'s contents and remove their spill blocks.
115	#
116	# file21 - Increase record size; single block
117	# file22 - Increase record size; multiple blocks
118	# file23 - Truncate file to zero size; single block
119	# file24 - Truncate file to smaller size; single block
120	# file25 - Truncate file to much larger size; add holes
121	# file26 - Truncate file to embedded size; embedded data
122	#
123	log_must mkfile 32768 /pool9/$1/file21
124	log_must mkfile 1048576 /pool9/$1/file22
125	log_must truncate -s 0 /pool9/$1/file23
126	log_must truncate -s 8192 /pool9/$1/file24
127	log_must truncate -s 1073741824 /pool9/$1/file25
128	log_must truncate -s 50 /pool9/$1/file26
129
130	for i in {21..30}; do
131		for j in {1..20}; do
132			log_must rm_xattr testattr$j /pool9/$1/file$i
133		done
134	done
135
136	#
137	# Modify file[31-40]'s spill blocks but not the file contents.
138	#
139	for i in {31..40}; do
140		file="/pool9/$1/file$i"
141		log_must rm_xattr testattr$(((RANDOM % 20) + 1)) $file
142		log_must set_xattr testattr$(((RANDOM % 20) + 1)) "$attrvalue" $file
143	done
144
145	# Snapshot the pool and send the incremental snapshot.
146	log_must zfs snapshot pool9/$1@snap2
147	log_must eval "zfs send -w -i pool9/$1@snap1 pool9/$1@snap2 >$BACKDIR/$1@snap2"
148	log_must eval "zfs recv pool12/$1 < $BACKDIR/$1@snap2"
149}
150
151attrvalue="abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
152
153log_onexit cleanup
154
155# Create pools
156truncate -s $MINVDEVSIZE $TESTDIR/vdev_a
157truncate -s $MINVDEVSIZE $TESTDIR/vdev_b
158log_must zpool create -f -o ashift=9 pool9 $TESTDIR/vdev_a
159log_must zpool create -f -o ashift=12 pool12 $TESTDIR/vdev_b
160
161# Create encrypted fs
162log_must eval "echo 'password' | zfs create -o encryption=on" \
163	"-o keyformat=passphrase -o keylocation=prompt " \
164	"pool9/encfs"
165
166# Run xattr tests for encrypted fs
167xattr_test encfs
168
169# Calculate the expected recursive checksum for source encrypted fs
170expected_cksum=$(recursive_cksum /pool9/encfs)
171
172# Mount target encrypted fs
173log_must eval "echo 'password' | zfs load-key pool12/encfs"
174log_must zfs mount pool12/encfs
175
176# Validate the received copy using the received recursive checksum
177actual_cksum=$(recursive_cksum /pool12/encfs)
178if [[ "$expected_cksum" != "$actual_cksum" ]]; then
179	log_fail "Checksums differ ($expected_cksum != $actual_cksum)"
180fi
181
182# Perform the same test but without encryption (send -w)
183log_must zfs create pool9/fs
184
185# Run xattr tests for non-encrypted fs
186xattr_test fs
187
188# Calculate the expected recursive checksum for source non-encrypted fs
189expected_cksum=$(recursive_cksum /pool9/fs)
190
191# Validate the received copy using the received recursive checksum
192actual_cksum=$(recursive_cksum /pool12/fs)
193if [[ "$expected_cksum" != "$actual_cksum" ]]; then
194	log_fail "Checksums differ ($expected_cksum != $actual_cksum)"
195fi
196
197log_pass "Verify raw sending to pools with greater ashift succeeds"
198