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 by Lawrence Livermore National Security, LLC.
16#
17
18. $STF_SUITE/include/libtest.shlib
19. $STF_SUITE/tests/functional/rsend/rsend.kshlib
20
21#
22# Description:
23# Verify spill blocks are correctly preserved.
24#
25# Strategy:
26# 1) Create a set of files each containing some file data.
27# 2) Add enough xattrs to the file to require a spill block.
28# 3) Snapshot and send these files to a new dataset.
29# 4) Modify the files and spill blocks in a variety of ways.
30# 5) Send the changes using an incremental send stream.
31# 6) Verify that all the xattrs (and thus the spill block) were
32#    preserved when receiving the incremental stream.
33#
34
35verify_runnable "both"
36
37log_assert "Verify spill blocks are correctly preserved"
38
39function cleanup
40{
41	rm -f $BACKDIR/fs@*
42	destroy_dataset $POOL/fs "-rR"
43	destroy_dataset $POOL/newfs "-rR"
44}
45
46attrvalue="abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz"
47
48log_onexit cleanup
49
50log_must zfs create $POOL/fs
51log_must zfs set xattr=sa $POOL/fs
52log_must zfs set dnodesize=legacy $POOL/fs
53log_must zfs set recordsize=128k $POOL/fs
54
55# Create 40 files each with a spill block containing xattrs.  Each file
56# will be modified in a different way to validate the incremental receive.
57for i in {1..40}; do
58	file="/$POOL/fs/file$i"
59
60	log_must mkfile 16384 $file
61	for j in {1..20}; do
62		log_must attr -qs "testattr$j" -V "$attrvalue" $file
63	done
64done
65
66# Snapshot the pool and send it to the new dataset.
67log_must zfs snapshot $POOL/fs@snap1
68log_must eval "zfs send -e $POOL/fs@snap1 >$BACKDIR/fs@snap1"
69log_must eval "zfs recv $POOL/newfs < $BACKDIR/fs@snap1"
70
71#
72# Modify file[1-6]'s contents but not the spill blocks.
73#
74# file1 - Increase record size; single block
75# file2 - Increase record size; multiple blocks
76# file3 - Truncate file to zero size; single block
77# file4 - Truncate file to smaller size; single block
78# file5 - Truncate file to much larger size; add holes
79# file6 - Truncate file to embedded size; embedded data
80#
81log_must mkfile 32768 /$POOL/fs/file1
82log_must mkfile 1048576 /$POOL/fs/file2
83log_must truncate -s 0 /$POOL/fs/file3
84log_must truncate -s 8192 /$POOL/fs/file4
85log_must truncate -s 1073741824 /$POOL/fs/file5
86log_must truncate -s 50 /$POOL/fs/file6
87
88#
89# Modify file[11-16]'s contents and their spill blocks.
90#
91# file11 - Increase record size; single block
92# file12 - Increase record size; multiple blocks
93# file13 - Truncate file to zero size; single block
94# file14 - Truncate file to smaller size; single block
95# file15 - Truncate file to much larger size; add holes
96# file16 - Truncate file to embedded size; embedded data
97#
98log_must mkfile 32768 /$POOL/fs/file11
99log_must mkfile 1048576 /$POOL/fs/file12
100log_must truncate -s 0 /$POOL/fs/file13
101log_must truncate -s 8192 /$POOL/fs/file14
102log_must truncate -s 1073741824 /$POOL/fs/file15
103log_must truncate -s 50 /$POOL/fs/file16
104
105for i in {11..20}; do
106	log_must attr -qr testattr1 /$POOL/fs/file$i
107done
108
109#
110# Modify file[21-26]'s contents and remove their spill blocks.
111#
112# file21 - Increase record size; single block
113# file22 - Increase record size; multiple blocks
114# file23 - Truncate file to zero size; single block
115# file24 - Truncate file to smaller size; single block
116# file25 - Truncate file to much larger size; add holes
117# file26 - Truncate file to embedded size; embedded data
118#
119log_must mkfile 32768 /$POOL/fs/file21
120log_must mkfile 1048576 /$POOL/fs/file22
121log_must truncate -s 0 /$POOL/fs/file23
122log_must truncate -s 8192 /$POOL/fs/file24
123log_must truncate -s 1073741824 /$POOL/fs/file25
124log_must truncate -s 50 /$POOL/fs/file26
125
126for i in {21..30}; do
127	for j in {1..20}; do
128		log_must attr -qr testattr$j /$POOL/fs/file$i
129	done
130done
131
132#
133# Modify file[31-40]'s spill blocks but not the file contents.
134#
135for i in {31..40}; do
136	file="/$POOL/fs/file$i"
137	log_must attr -qr testattr$(((RANDOM % 20) + 1)) $file
138	log_must attr -qs testattr$(((RANDOM % 20) + 1)) -V "$attrvalue" $file
139done
140
141# Calculate the expected recursive checksum for the source.
142expected_cksum=$(recursive_cksum /$POOL/fs)
143
144# Snapshot the pool and send the incremental snapshot.
145log_must zfs snapshot $POOL/fs@snap2
146log_must eval "zfs send -e -i $POOL/fs@snap1 $POOL/fs@snap2 >$BACKDIR/fs@snap2"
147log_must eval "zfs recv -F $POOL/newfs < $BACKDIR/fs@snap2"
148
149# Validate the received copy using the received recursive checksum.
150actual_cksum=$(recursive_cksum /$POOL/newfs)
151if [[ "$expected_cksum" != "$actual_cksum" ]]; then
152	log_fail "Checksums differ ($expected_cksum != $actual_cksum)"
153fi
154
155log_pass "Verify spill blocks are correctly preserved"
156