1*5602294fSDan Kimmel#!/usr/bin/ksh
2*5602294fSDan Kimmel
3*5602294fSDan Kimmel#
4*5602294fSDan Kimmel# This file and its contents are supplied under the terms of the
5*5602294fSDan Kimmel# Common Development and Distribution License ("CDDL"), version 1.0.
6*5602294fSDan Kimmel# You may only use this file in accordance with the terms of version
7*5602294fSDan Kimmel# 1.0 of the CDDL.
8*5602294fSDan Kimmel#
9*5602294fSDan Kimmel# A full copy of the text of the CDDL should have accompanied this
10*5602294fSDan Kimmel# source.  A copy of the CDDL is also available via the Internet at
11*5602294fSDan Kimmel# http://www.illumos.org/license/CDDL.
12*5602294fSDan Kimmel#
13*5602294fSDan Kimmel
14*5602294fSDan Kimmel#
15*5602294fSDan Kimmel# Copyright (c) 2015 by Delphix. All rights reserved.
16*5602294fSDan Kimmel#
17*5602294fSDan Kimmel
18*5602294fSDan Kimmel. $STF_SUITE/tests/functional/rsend/rsend.kshlib
19*5602294fSDan Kimmel
20*5602294fSDan Kimmel#
21*5602294fSDan Kimmel# Description:
22*5602294fSDan Kimmel# Verify compressed send works correctly with datasets of varying recsize.
23*5602294fSDan Kimmel#
24*5602294fSDan Kimmel# Strategy:
25*5602294fSDan Kimmel# 1. Check the recv behavior (into pools with features enabled and disabled)
26*5602294fSDan Kimmel#    of all combinations of -c -p and -L. Verify the stream is compressed,
27*5602294fSDan Kimmel#    and that the recsize property and that of a received file is correct
28*5602294fSDan Kimmel#    according to this matrix:
29*5602294fSDan Kimmel#
30*5602294fSDan Kimmel# +---------+--------+------------+------------+-----------+-----------+
31*5602294fSDan Kimmel# | send    | send   | received   | received   | received  | received  |
32*5602294fSDan Kimmel# | stream  | stream | file bs    | prop       | file bs   | props     |
33*5602294fSDan Kimmel# | recsize | flags  | (disabled) | (disabled) | (enabled) | (enabled) |
34*5602294fSDan Kimmel# +---------+--------+------------+------------+-----------+-----------+
35*5602294fSDan Kimmel# |    128k |        |       128k |       128k |      128k |      128k |
36*5602294fSDan Kimmel# |    128k |     -c |      Fails |      Fails |      128k |      128k |
37*5602294fSDan Kimmel# |    128k |     -p |       128k |       128k |      128k |      128k |
38*5602294fSDan Kimmel# |    128k |     -L |       128k |       128k |      128k |      128k |
39*5602294fSDan Kimmel# |    128k |    -cp |      Fails |      Fails |      128k |      128k |
40*5602294fSDan Kimmel# |    128k |    -cL |      Fails |      Fails |      128k |      128k |
41*5602294fSDan Kimmel# |    128k |    -pL |       128k |       128k |      128k |      128k |
42*5602294fSDan Kimmel# |    128k |   -cpL |      Fails |      Fails |      128k |      128k |
43*5602294fSDan Kimmel# |      1m |        |      Fails |      Fails |      128k |      128k |
44*5602294fSDan Kimmel# |      1m |     -c |      Fails |      Fails |      128k |      128k |
45*5602294fSDan Kimmel# |      1m |     -p |       128k |       128k |      128k |        1m |
46*5602294fSDan Kimmel# |      1m |     -L |      Fails |      Fails |        1m |      128k |
47*5602294fSDan Kimmel# |      1m |    -cp |      Fails |      Fails |      128k |        1m |
48*5602294fSDan Kimmel# |      1m |    -cL |      Fails |      Fails |        1m |      128k |
49*5602294fSDan Kimmel# |      1m |    -pL |      Fails |      Fails |        1m |        1m |
50*5602294fSDan Kimmel# |      1m |   -cpL |      Fails |      Fails |        1m |        1m |
51*5602294fSDan Kimmel# +---------+--------+------------+------------+-----------+-----------+
52*5602294fSDan Kimmel#
53*5602294fSDan Kimmel
54*5602294fSDan Kimmelverify_runnable "both"
55*5602294fSDan Kimmel
56*5602294fSDan Kimmelfunction cleanup
57*5602294fSDan Kimmel{
58*5602294fSDan Kimmel	datasetexists $TESTPOOL/128k && log_must zfs destroy $TESTPOOL/128k
59*5602294fSDan Kimmel	datasetexists $TESTPOOL/1m && log_must zfs destroy $TESTPOOL/1m
60*5602294fSDan Kimmel	cleanup_pool $POOL2
61*5602294fSDan Kimmel	destroy_pool $POOL3
62*5602294fSDan Kimmel}
63*5602294fSDan Kimmel
64*5602294fSDan Kimmel# For a received stream, verify the recsize (prop and file) match expectations.
65*5602294fSDan Kimmelfunction check_recsize
66*5602294fSDan Kimmel{
67*5602294fSDan Kimmel	typeset recv_ds=$1
68*5602294fSDan Kimmel	typeset expected_file_bs=$2
69*5602294fSDan Kimmel	typeset expected_recsize=$3
70*5602294fSDan Kimmel	typeset file="$(get_prop mountpoint $recv_ds)/testfile"
71*5602294fSDan Kimmel
72*5602294fSDan Kimmel	[[ -f $file ]] || log_fail "file '$file' doesn't exist"
73*5602294fSDan Kimmel
74*5602294fSDan Kimmel	typeset read_recsize=$(get_prop recsize $recv_ds)
75*5602294fSDan Kimmel	typeset read_file_bs=$(stat $file | sed -n \
76*5602294fSDan Kimmel	    's/.*IO Block: \([0-9]*\).*/\1/p')
77*5602294fSDan Kimmel
78*5602294fSDan Kimmel	[[ $read_recsize = $expected_recsize ]] || log_fail \
79*5602294fSDan Kimmel	    "read_recsize: $read_recsize expected_recsize: $expected_recsize"
80*5602294fSDan Kimmel	[[ $read_file_bs = $expected_file_bs ]] || log_fail \
81*5602294fSDan Kimmel	    "read_file_bs: $read_file_bs expected_file_bs: $expected_file_bs"
82*5602294fSDan Kimmel}
83*5602294fSDan Kimmel
84*5602294fSDan Kimmel#
85*5602294fSDan Kimmel# This function does a zfs send and receive according to the parameters
86*5602294fSDan Kimmel# below, and verifies the data shown in the strategy section.
87*5602294fSDan Kimmel#
88*5602294fSDan Kimmel# -[cpL] flags to pass through to 'zfs send'
89*5602294fSDan Kimmel# -d Receive into a pool with all features disabled
90*5602294fSDan Kimmel#
91*5602294fSDan Kimmel# $1 The recordsize of the send dataset
92*5602294fSDan Kimmel# $2 Whether or not the recv should work.
93*5602294fSDan Kimmel# $3 The blocksize expected in a received file (default 128k)
94*5602294fSDan Kimmel# $4 The recordsize property expected in a received dataset (default 128k)
95*5602294fSDan Kimmel#
96*5602294fSDan Kimmelfunction check
97*5602294fSDan Kimmel{
98*5602294fSDan Kimmel	typeset recv_pool=$POOL2
99*5602294fSDan Kimmel	typeset flags='-'
100*5602294fSDan Kimmel
101*5602294fSDan Kimmel	while getopts "cdpL" opt; do
102*5602294fSDan Kimmel		case $opt in
103*5602294fSDan Kimmel		c)
104*5602294fSDan Kimmel			flags+='c'
105*5602294fSDan Kimmel			;;
106*5602294fSDan Kimmel		d)
107*5602294fSDan Kimmel			recv_pool=$POOL3
108*5602294fSDan Kimmel			;;
109*5602294fSDan Kimmel		p)
110*5602294fSDan Kimmel			flags+='p'
111*5602294fSDan Kimmel			;;
112*5602294fSDan Kimmel		L)
113*5602294fSDan Kimmel			flags+='L'
114*5602294fSDan Kimmel			;;
115*5602294fSDan Kimmel		esac
116*5602294fSDan Kimmel	done
117*5602294fSDan Kimmel	shift $(($OPTIND - 1))
118*5602294fSDan Kimmel	[[ ${#flags} -eq 1 ]] && flags=''
119*5602294fSDan Kimmel
120*5602294fSDan Kimmel	typeset recsize=$1
121*5602294fSDan Kimmel	typeset verify=$2
122*5602294fSDan Kimmel	typeset expected_file_bs=${3-131072}
123*5602294fSDan Kimmel	typeset expected_recsize=${4-131072}
124*5602294fSDan Kimmel	typeset send_ds=$TESTPOOL/$recsize
125*5602294fSDan Kimmel	typeset send_snap=$send_ds@snap
126*5602294fSDan Kimmel	typeset recv_ds=$recv_pool/$recsize
127*5602294fSDan Kimmel	typeset stream=$BACKDIR/stream.out
128*5602294fSDan Kimmel
129*5602294fSDan Kimmel	datasetexists $send_ds || log_fail "send ds: $send_ds doesn't exist"
130*5602294fSDan Kimmel	[[ -f $stream ]] && log_must rm $stream
131*5602294fSDan Kimmel	log_must eval "zfs send $flags $send_snap >$stream"
132*5602294fSDan Kimmel	$verify eval "zfs recv $recv_ds <$stream"
133*5602294fSDan Kimmel	typeset stream_size=$(cat $stream | zstreamdump | sed -n \
134*5602294fSDan Kimmel	    's/	Total write size = \(.*\) (0x.*)/\1/p')
135*5602294fSDan Kimmel
136*5602294fSDan Kimmel	#
137*5602294fSDan Kimmel	# Special case: For a send dataset with large blocks, don't try to
138*5602294fSDan Kimmel	# verify the stream size is correct if the compress flag is present
139*5602294fSDan Kimmel	# but the large blocks flag isn't. In these cases, the user data
140*5602294fSDan Kimmel	# isn't compressed in the stream (though metadata is) so the
141*5602294fSDan Kimmel	# verification would fail.
142*5602294fSDan Kimmel	#
143*5602294fSDan Kimmel	typeset do_size_test=true
144*5602294fSDan Kimmel	[[ $recsize = $large && $flags =~ 'c' && ! $flags =~ 'L' ]] && \
145*5602294fSDan Kimmel	    do_size_test=false
146*5602294fSDan Kimmel
147*5602294fSDan Kimmel	$do_size_test && verify_stream_size $stream $send_ds
148*5602294fSDan Kimmel
149*5602294fSDan Kimmel	if [[ $verify = "log_mustnot" ]]; then
150*5602294fSDan Kimmel		datasetnonexists $recv_ds || log_fail "$recv_ds shouldn't exist"
151*5602294fSDan Kimmel		return
152*5602294fSDan Kimmel	fi
153*5602294fSDan Kimmel
154*5602294fSDan Kimmel	check_recsize $recv_ds $expected_file_bs $expected_recsize
155*5602294fSDan Kimmel	$do_size_test && verify_stream_size $stream $recv_ds
156*5602294fSDan Kimmel	log_must zfs destroy -r $recv_ds
157*5602294fSDan Kimmel}
158*5602294fSDan Kimmel
159*5602294fSDan Kimmellog_assert "Verify compressed send works with datasets of varying recsize."
160*5602294fSDan Kimmellog_onexit cleanup
161*5602294fSDan Kimmeltypeset recsize opts dir
162*5602294fSDan Kimmeltypeset small=$((128 * 1024))
163*5602294fSDan Kimmeltypeset large=$((1024 * 1024))
164*5602294fSDan Kimmel
165*5602294fSDan Kimmel# Create POOL3 with features disabled and datasets to create test send streams
166*5602294fSDan Kimmellog_must zpool create -d $POOL3 $DISK3
167*5602294fSDan Kimmelwrite_compressible $BACKDIR 32m
168*5602294fSDan Kimmelfor recsize in $small $large; do
169*5602294fSDan Kimmel	log_must zfs create -o compress=gzip -o recsize=$recsize \
170*5602294fSDan Kimmel	    $TESTPOOL/$recsize
171*5602294fSDan Kimmel	dir=$(get_prop mountpoint $TESTPOOL/$recsize)
172*5602294fSDan Kimmel	log_must cp $BACKDIR/file.0 $dir/testfile
173*5602294fSDan Kimmel	log_must zfs snapshot $TESTPOOL/$recsize@snap
174*5602294fSDan Kimmeldone
175*5602294fSDan Kimmel
176*5602294fSDan Kimmel# Run tests for send streams without large blocks
177*5602294fSDan Kimmelfor opts in '' -d -c -p -dp -L -dL -cp -cL -pL -dpL -cpL; do
178*5602294fSDan Kimmel	check $opts $small log_must
179*5602294fSDan Kimmeldone
180*5602294fSDan Kimmelfor opts in -dc -dcp -dcL -dcpL; do
181*5602294fSDan Kimmel	check $opts $small log_mustnot
182*5602294fSDan Kimmeldone
183*5602294fSDan Kimmel
184*5602294fSDan Kimmel# Run tests for send streams with large blocks
185*5602294fSDan Kimmelfor opts in '' -d -dp -c; do
186*5602294fSDan Kimmel	check $opts $large log_must
187*5602294fSDan Kimmeldone
188*5602294fSDan Kimmelfor opts in -dc -dL -dcp -dcL -dpL -dcpL; do
189*5602294fSDan Kimmel	check $opts $large log_mustnot
190*5602294fSDan Kimmeldone
191*5602294fSDan Kimmelcheck -p $large log_must $small $large
192*5602294fSDan Kimmelcheck -L $large log_must $large $small
193*5602294fSDan Kimmelcheck -cp $large log_must $small $large
194*5602294fSDan Kimmelcheck -cL $large log_must $large $small
195*5602294fSDan Kimmelcheck -pL $large log_must $large $large
196*5602294fSDan Kimmelcheck -cpL $large log_must $large $large
197*5602294fSDan Kimmel
198*5602294fSDan Kimmellog_pass "Compressed send works with datasets of varying recsize."
199