xref: /freebsd/sys/contrib/openzfs/tests/zfs-tests/tests/functional/redacted_send/redacted.kshlib (revision 61145dc2b94f12f6a47344fb9aac702321880e43)
1#!/bin/ksh
2# SPDX-License-Identifier: CDDL-1.0
3
4#
5# CDDL HEADER START
6#
7# The contents of this file are subject to the terms of the
8# Common Development and Distribution License (the "License").
9# You may not use this file except in compliance with the License.
10#
11# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
12# or https://opensource.org/licenses/CDDL-1.0.
13# See the License for the specific language governing permissions
14# and limitations under the License.
15#
16# When distributing Covered Code, include this CDDL HEADER in each
17# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
18# If applicable, add the following below this CDDL HEADER, with the
19# fields enclosed by brackets "[]" replaced with your own identifying
20# information: Portions Copyright [yyyy] [name of copyright owner]
21#
22# CDDL HEADER END
23#
24
25#
26# Copyright (c) 2016, 2018 by Delphix. All rights reserved.
27#
28
29. $STF_SUITE/include/libtest.shlib
30. $STF_SUITE/tests/functional/rsend/rsend.kshlib
31. $STF_SUITE/tests/functional/redacted_send/redacted.cfg
32
33if ! is_linux; then
34	alias udevadm=:
35fi
36
37function setup_dataset
38{
39	typeset ds_name=$1
40	typeset opts=$2
41	typeset file_create_func=$3
42	typeset sendfs="$POOL/$ds_name"
43	[[ -n $file_create_func ]] || file_create_func=setup_common
44
45	log_must zfs create $opts $sendfs
46
47	$file_create_func $sendfs
48
49	log_must zfs snapshot $sendfs@snap
50	log_must zfs clone $opts $sendfs@snap $POOL/${ds_name}_clone
51	log_must zfs snapshot $POOL/${ds_name}_clone@snap
52}
53
54function setup_common
55{
56	typeset sendfs=$1
57
58	typeset mntpnt=$(get_prop mountpoint $sendfs)
59	typeset bs=$(get_prop recsize $sendfs)
60	log_must dd if=/dev/urandom of=$mntpnt/f1 bs=$bs count=16
61	log_must dd if=/dev/urandom of=$mntpnt/f2 bs=$bs count=32
62}
63
64function setup_embedded
65{
66	typeset sendfs=$1
67
68	typeset recsize
69	typeset mntpnt=$(get_prop mountpoint $sendfs)
70	for recsize in 512 1024 2048 4096 8192 16384; do
71		if is_illumos; then
72			log_must mkholes -d $((recsize - 8)):8 $mntpnt/$recsize
73		else
74			log_must dd if=/dev/urandom of=$mntpnt/$recsize bs=8 \
75			    count=1 seek=$(((recsize / 8) - 1))
76		fi
77	done
78}
79
80function setup_holes
81{
82	typeset sendfs=$1
83
84	typeset mntpnt=$(get_prop mountpoint $sendfs)
85	typeset M=$((1024 * 1024))
86
87	if is_illumos; then
88		log_must mkholes -d 0:$((8 * M)) $mntpnt/f1
89		log_must mkholes -d 0:$M -d $((7 * M)):$M $mntpnt/f2
90		log_must mkholes -d $M:$((6 * M)) -h $((7 * M)):$M $mntpnt/f3
91		log_must mkholes -h 0:$((8 * M)) $mntpnt/f4
92	else
93		log_must dd if=/dev/urandom of=$mntpnt/f1 bs=8M count=1
94
95		log_must dd if=/dev/urandom of=$mntpnt/f2 bs=1M count=1
96		log_must dd if=/dev/urandom of=$mntpnt/f2 bs=1M count=1 seek=7 \
97		    conv=notrunc
98
99		log_must dd if=/dev/urandom of=$mntpnt/f3 bs=1M count=6 seek=1
100		log_must truncate -s $((8 * M)) $mntpnt/f3
101
102		log_must truncate -s $((8 * M)) $mntpnt/f4
103	fi
104
105	log_must zfs create $sendfs/manyrm
106	for i in {1..256}; do
107		log_must stride_dd -i /dev/urandom -o $mntpnt/manyrm/f$i -b 512 \
108		    -c $(random_int_between 1 100) -s $(random_int_between 1 4)
109	done
110
111	log_must zfs snapshot $sendfs/manyrm@snap
112	log_must zfs clone $sendfs/manyrm@snap $sendfs/manyrm_clone
113	log_must zfs snapshot $sendfs/manyrm_clone@snap
114}
115
116function setup_incrementals
117{
118	typeset sendfs=$1
119
120	typeset mntpnt=$(get_prop mountpoint $sendfs)
121	typeset bs=$(get_prop recsize $sendfs)
122	log_must dd if=/dev/urandom of=$mntpnt/f1 bs=$bs count=16
123	log_must dd if=/dev/urandom of=$mntpnt/f2 bs=$bs count=32
124	log_must mkdir $mntpnt/d1
125	log_must eval "cat $mntpnt/f1 $mntpnt/f2 >$mntpnt/d1/f1"
126	log_must zfs snapshot $sendfs@snap0
127
128	log_must zfs clone $sendfs@snap0 $POOL/hole
129	mntpnt=$(get_prop mountpoint $POOL/hole)
130	log_must dd if=/dev/zero of=$mntpnt/f2 bs=$bs count=16 conv=notrunc
131	log_must zfs snapshot $POOL/hole@snap
132
133	log_must zfs clone $sendfs@snap0 $POOL/stride3
134	mntpnt=$(get_prop mountpoint $POOL/stride3)
135	log_must stride_dd -i /dev/urandom -o $mntpnt/f2 -b $bs -c 11 -s 3
136	log_must zfs snapshot $POOL/stride3@snap
137
138	log_must zfs clone $sendfs@snap0 $POOL/stride5
139	mntpnt=$(get_prop mountpoint $POOL/stride5)
140	log_must stride_dd -i /dev/urandom -o $mntpnt/f2 -b $bs -c 7 -s 5
141	log_must zfs snapshot $POOL/stride5@snap
142
143	log_must zfs clone $sendfs@snap0 $POOL/int
144	log_must zfs snapshot $POOL/int@snap
145
146	log_must zfs clone $POOL/int@snap $POOL/rm
147	mntpnt=$(get_prop mountpoint $POOL/rm)
148	log_must rm -rf $mntpnt/[df][12]
149	log_must zfs snapshot $POOL/rm@snap
150
151	log_must zfs clone $POOL/int@snap $POOL/write
152	mntpnt=$(get_prop mountpoint $POOL/write)
153	log_must dd if=/dev/urandom of=$mntpnt/f1 bs=512 count=16 conv=notrunc
154	log_must dd if=/dev/urandom of=$mntpnt/d1/f1 bs=512 count=16 seek=16 \
155	    conv=notrunc
156	log_must zfs snapshot $POOL/write@snap
157}
158
159function setup_mounts
160{
161	typeset sendfs=$1
162
163	typeset mntpnt=$(get_prop mountpoint $sendfs)
164	log_must touch $mntpnt/empty
165	log_must dd if=/dev/urandom of=$mntpnt/contents1 bs=512 count=2
166	log_must dd if=/dev/urandom of=$mntpnt/contents2 bs=512 count=2
167	log_must mkdir $mntpnt/dir1
168	log_must touch $mntpnt/dir1/empty
169	log_must dd if=/dev/urandom of=$mntpnt/dir1/contents1 bs=512 count=2
170	log_must dd if=/dev/urandom of=$mntpnt/dir1/contents2 bs=512 count=2
171	log_must mkdir $mntpnt/dir1/dir2
172	log_must touch $mntpnt/dir1/dir2/empty
173	log_must dd if=/dev/urandom of=$mntpnt/dir1/dir2/file bs=512 count=2
174
175	log_must zfs create -s -V 16p $sendfs/vol
176	log_must zfs snapshot $sendfs/vol@snap
177	log_must zfs clone $sendfs/vol@snap $sendfs/vol_clone
178	log_must zfs snapshot $sendfs/vol_clone@snap
179}
180
181function mount_redacted
182{
183	typeset flag=''
184	while getopts "f" opt; do
185		case $opt in
186		f)
187			flag='-f'
188			;;
189		esac
190	done
191	shift $(($OPTIND - 1))
192
193	typeset ds=$1
194	log_must set_tunable32 ALLOW_REDACTED_DATASET_MOUNT 1
195	zfs mount $flag -oro $ds || return 1
196	log_must set_tunable32 ALLOW_REDACTED_DATASET_MOUNT 0
197	return 0
198}
199
200function unmount_redacted
201{
202	typeset ds=$1
203
204	zfs unmount $ds
205}
206
207#
208# This function calls a utility that prints out the ranges where a file
209# and its redacted counterpart differ, each range on a new line like this:
210#
211# 0,131072
212# 1966080,131072
213# 3932160,131072
214#
215# The output is then checked against a variable containing the expected
216# output to verify the redacted ranges are the ones expected.
217#
218function compare_files
219{
220	typeset sendfs=$1
221	typeset recvfs=$2
222	typeset file=$3
223	typeset expected="$4"
224	typeset tmpfile="$tmpdir/get_file.out"
225
226	log_must mount_redacted -f $recvfs
227
228	typeset file1="$(get_prop mountpoint $sendfs)/$file"
229	typeset file2="$(get_prop mountpoint $recvfs)/$file"
230	log_note "Comparing $file1 and $file2"
231	[[ -f $file1 ]] || log_fail "File $file1 does not exist."
232	[[ -f $file2 ]] || log_fail "File $file2 does not exist."
233
234	log_must eval "get_diff $file1 $file2 >$tmpfile"
235	typeset range="$(<$tmpfile)"
236	log_must unmount_redacted $recvfs
237	[[ "$expected" = "$range" ]] || log_fail "Unexpected range: $range"
238}
239
240function redacted_cleanup
241{
242	typeset ds_list=$@
243	typeset ds
244
245	for ds in $ds_list; do
246		zfs destroy -R $ds
247	done
248
249	set_tunable32 ALLOW_REDACTED_DATASET_MOUNT 0
250	rm -f $(get_prop mountpoint $POOL)/tmp/*
251}
252
253# Retrieve the redaction list of a bookmark or snapshot, using
254# the property or zdb output, as requested.
255function get_guid_list
256{
257	typeset filename=$1
258	typeset dataset=$2
259	typeset use_zdb=${3:-false}
260
261	if $use_zdb; then
262		guid_list=$(zdb -vvvv $dataset | sed -e 's/,//g' \
263		    -ne 's/^.*Snapshots: \[\(.*\)\]/\1/p')
264	else
265		guid_list=$(get_prop redact_snaps $dataset)
266	fi
267
268	for guid in $(echo $guid_list | tr ',' ' '); do
269		echo $guid
270	done | sort >$filename
271}
272