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/tests/functional/rsend/rsend.kshlib
21
22#
23# Description:
24# Verify spill blocks are correctly preserved in raw sends.
25#
26# Strategy:
27# 1) Create a set of files each containing some file data in an
28#	encrypted filesystem.
29# 2) Add enough xattrs to the file to require a spill block.
30# 3) Snapshot and raw send these files to a new dataset.
31# 4) Modify the files and spill blocks in a variety of ways.
32# 5) Send the changes using an raw incremental send stream.
33# 6) Verify that all the xattrs (and thus the spill block) were
34#    preserved when receiving the incremental stream.
35#
36
37verify_runnable "both"
38
39log_assert "Verify spill blocks are correctly preserved in raw sends"
40
41function cleanup
42{
43	rm -f $BACKDIR/fs@*
44	destroy_dataset $POOL/fs "-rR"
45	destroy_dataset $POOL/newfs "-rR"
46}
47
48attrvalue="abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
49
50log_onexit cleanup
51
52log_must eval "echo 'password' | zfs create -o encryption=on" \
53	"-o keyformat=passphrase -o keylocation=prompt " \
54	"$POOL/fs"
55log_must zfs set xattr=sa $POOL/fs
56log_must zfs set dnodesize=legacy $POOL/fs
57log_must zfs set recordsize=128k $POOL/fs
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.
61for i in {1..40}; do
62	file="/$POOL/fs/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
68done
69
70# Snapshot the pool and send it to the new dataset.
71log_must zfs snapshot $POOL/fs@snap1
72log_must eval "zfs send -w $POOL/fs@snap1 >$BACKDIR/fs@snap1"
73log_must eval "zfs recv $POOL/newfs < $BACKDIR/fs@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#
85log_must mkfile 32768 /$POOL/fs/file1
86log_must mkfile 1048576 /$POOL/fs/file2
87log_must truncate -s 0 /$POOL/fs/file3
88log_must truncate -s 8192 /$POOL/fs/file4
89log_must truncate -s 1073741824 /$POOL/fs/file5
90log_must truncate -s 50 /$POOL/fs/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#
102log_must mkfile 32768 /$POOL/fs/file11
103log_must mkfile 1048576 /$POOL/fs/file12
104log_must truncate -s 0 /$POOL/fs/file13
105log_must truncate -s 8192 /$POOL/fs/file14
106log_must truncate -s 1073741824 /$POOL/fs/file15
107log_must truncate -s 50 /$POOL/fs/file16
108
109for i in {11..20}; do
110	log_must rm_xattr testattr1 /$POOL/fs/file$i
111done
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#
123log_must mkfile 32768 /$POOL/fs/file21
124log_must mkfile 1048576 /$POOL/fs/file22
125log_must truncate -s 0 /$POOL/fs/file23
126log_must truncate -s 8192 /$POOL/fs/file24
127log_must truncate -s 1073741824 /$POOL/fs/file25
128log_must truncate -s 50 /$POOL/fs/file26
129
130for i in {21..30}; do
131	for j in {1..20}; do
132		log_must rm_xattr testattr$j /$POOL/fs/file$i
133	done
134done
135
136#
137# Modify file[31-40]'s spill blocks but not the file contents.
138#
139for i in {31..40}; do
140	file="/$POOL/fs/file$i"
141	log_must rm_xattr testattr$(((RANDOM % 20) + 1)) $file
142	log_must set_xattr testattr$(((RANDOM % 20) + 1)) "$attrvalue" $file
143done
144
145# Calculate the expected recursive checksum for the source.
146expected_cksum=$(recursive_cksum /$POOL/fs)
147
148# Snapshot the pool and send the incremental snapshot.
149log_must zfs snapshot $POOL/fs@snap2
150log_must eval "zfs send -w -i $POOL/fs@snap1 $POOL/fs@snap2 >$BACKDIR/fs@snap2"
151log_must eval "zfs recv $POOL/newfs < $BACKDIR/fs@snap2"
152log_must eval "echo 'password' | zfs load-key $POOL/newfs"
153log_must zfs mount $POOL/newfs
154
155# Validate the received copy using the received recursive checksum.
156actual_cksum=$(recursive_cksum /$POOL/newfs)
157if [[ "$expected_cksum" != "$actual_cksum" ]]; then
158	log_fail "Checksums differ ($expected_cksum != $actual_cksum)"
159fi
160
161log_pass "Verify spill blocks are correctly preserved in raw sends"
162