xref: /illumos-gate/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_receive/zfs_receive_010_pos.ksh (revision 621be8d08fd45483b5ca1cb8e2e88239f1502b4d)
1#!/bin/ksh -p
2#
3# CDDL HEADER START
4#
5# The contents of this file are subject to the terms of the
6# Common Development and Distribution License (the "License").
7# You may not use this file except in compliance with the License.
8#
9# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10# or http://www.opensolaris.org/os/licensing.
11# See the License for the specific language governing permissions
12# and limitations under the License.
13#
14# When distributing Covered Code, include this CDDL HEADER in each
15# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16# If applicable, add the following below this CDDL HEADER, with the
17# fields enclosed by brackets "[]" replaced with your own identifying
18# information: Portions Copyright [yyyy] [name of copyright owner]
19#
20# CDDL HEADER END
21#
22
23#
24# Copyright (c) 2015 by Delphix. All rights reserved.
25#
26
27. $STF_SUITE/include/libtest.shlib
28
29#
30# DESCRIPTION:
31# Test that receiving a full send as a clone works correctly.
32#
33# STRATEGY:
34# 1. Create pool and filesystems.
35# 2. Send filesystem, receive as clone of itself.
36# 3. Verify that nop-write saves space.
37# 4. Send filesystem, receive as clone of other filesystem.
38# 5. Verify that contents are correct.
39# 6. Repeat steps 4 and 5 with filesystems swapped.
40#
41
42verify_runnable "both"
43
44fs=$TESTPOOL/$TESTFS/base/fs
45fs2=$TESTPOOL/$TESTFS/base/fs2
46rfs=$TESTPOOL/$TESTFS/base/rfs
47
48function make_object
49{
50	local objnum=$1
51	local mntpnt=$2
52	local type=$3
53	if [[ $type == "file" ]]; then
54		$DD if=/dev/urandom of=${mntpnt}/f$objnum bs=512 count=16
55	elif [[ $type == "hole1" ]]; then
56		$DD if=/dev/urandom of=${mntpnt}/fh$objnum bs=512 count=5 stride=4
57	elif [[ $type == "hole2" ]]; then
58		$DD if=/dev/urandom of=${mntpnt}/fh$objnum bs=512 count=4 stride=5
59	elif [[ $type == "directory" ]]; then
60		$MKDIR ${mntpnt}/d$objnum
61	elif [[ $type == "missing" ]]; then
62		$TOUCH ${mntpnt}/h$objnum
63	fi
64}
65
66function create_pair
67{
68	local objnum=$1
69	local mntpnt1=$2
70	local mntpnt2=$3
71	local type1=$4
72	local type2=$5
73	make_object $objnum $mntpnt1 $type1
74	make_object $objnum $mntpnt2 $type2
75}
76
77function cleanup
78{
79	$ZFS destroy -Rf $TESTPOOL/$TESTFS/base
80	rm /tmp/zr010p*
81}
82
83log_assert "zfs receive of full send as clone should work"
84log_onexit cleanup
85log_must $ZFS create -o checksum=sha256 -o compression=gzip -o recordsize=512 \
86	$TESTPOOL/$TESTFS/base
87
88log_must $ZFS create $fs
89log_must $ZFS create $fs2
90mntpnt=$(get_prop mountpoint $fs)
91mntpnt2=$(get_prop mountpoint $fs2)
92
93#
94# Now, we create the two filesystems.  By creating objects with
95# different types and the same object number in each filesystem, we
96# create a situation where, when you receive the full send of each as
97# a clone of the other, we will test to ensure that the code correctly
98# handles receiving all object types onto all other object types.
99#
100
101# Receive a file onto a file (and vice versa).
102create_pair 8 $mntpnt $mntpnt2 "file" "file"
103
104# Receive a file onto a file with holes (and vice versa).
105create_pair 9 $mntpnt $mntpnt2 "file" "hole1"
106
107# Receive a file onto a directory (and vice versa).
108create_pair 10 $mntpnt $mntpnt2 "file" "directory"
109
110# Receive a file onto a missing object (and vice versa).
111create_pair 11 $mntpnt $mntpnt2 "file" "missing"
112
113# Receive a file with holes onto a file with holes (and vice versa).
114create_pair 12 $mntpnt $mntpnt2 "hole1" "hole2"
115
116# Receive a file with holes onto a directory (and vice versa).
117create_pair 13 $mntpnt $mntpnt2 "hole1" "directory"
118
119# Receive a file with holes onto a missing object (and vice versa).
120create_pair 14 $mntpnt $mntpnt2 "hole1" "missing"
121
122# Receive a directory onto a directory (and vice versa).
123create_pair 15 $mntpnt $mntpnt2 "directory" "directory"
124
125# Receive a directory onto a missing object (and vice versa).
126create_pair 16 $mntpnt $mntpnt2 "directory" "missing"
127
128# Receive a missing object onto a missing object (and vice versa).
129create_pair 17 $mntpnt $mntpnt2 "missing" "missing"
130
131# Receive a file with a different record size onto a file (and vice versa).
132log_must $ZFS set recordsize=128k $fs
133$DD if=/dev/urandom of=$mntpnt/f18 bs=128k count=64
134$TOUCH $mntpnt2/f18
135
136# Remove objects that are intended to be missing.
137$RM $mntpnt/h17
138$RM $mntpnt2/h*
139
140# Add empty objects to $fs to exercise dmu_traverse code
141for i in `seq 1 100`; do
142	log_must touch $mntpnt/uf$i
143done
144
145log_must $ZFS snapshot $fs@s1
146log_must $ZFS snapshot $fs2@s1
147
148log_must $ZFS send $fs@s1 > /tmp/zr010p
149log_must $ZFS send $fs2@s1 > /tmp/zr010p2
150
151
152#
153# Test that, when we receive a full send as a clone of itself,
154# nop-write saves us all the space used by data blocks.
155#
156cat /tmp/zr010p | log_must $ZFS receive -o origin=$fs@s1 $rfs
157size=$(get_prop used $rfs)
158size2=$(get_prop used $fs)
159if [[ $size -ge $(($size2 / 10)) ]] then
160        log_fail "nop-write failure; expected usage less than "\
161		"$(($size2 / 10)), but is using $size"
162fi
163log_must $ZFS destroy -fr $rfs
164
165# Correctness testing: receive each full send as a clone of the other fiesystem.
166cat /tmp/zr010p | log_must $ZFS receive -o origin=$fs2@s1 $rfs
167mntpnt_old=$(get_prop mountpoint $fs)
168mntpnt_new=$(get_prop mountpoint $rfs)
169log_must $DIFF -r $mntpnt_old $mntpnt_new
170log_must $ZFS destroy -r $rfs
171
172cat /tmp/zr010p2 | log_must $ZFS receive -o origin=$fs@s1 $rfs
173mntpnt_old=$(get_prop mountpoint $fs2)
174mntpnt_new=$(get_prop mountpoint $rfs)
175log_must $DIFF -r $mntpnt_old $mntpnt_new
176
177log_pass "zfs receive of full send as clone works"
178