]>
Commit | Line | Data |
---|---|---|
cae5b340 AX |
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, 2016 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 | ||
42 | verify_runnable "both" | |
43 | ||
44 | fs=$TESTPOOL/$TESTFS/base/fs | |
45 | fs2=$TESTPOOL/$TESTFS/base/fs2 | |
46 | rfs=$TESTPOOL/$TESTFS/base/rfs | |
47 | ||
48 | function make_object | |
49 | { | |
50 | typeset objnum=$1 | |
51 | typeset mntpnt=$2 | |
52 | typeset 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/zero of=${mntpnt}/fh$objnum bs=512 count=5 seek=4 conv=notrunc | |
57 | elif [[ $type == "hole2" ]]; then | |
58 | dd if=/dev/zero of=${mntpnt}/fh$objnum bs=512 count=4 seek=5 conv=notrunc | |
59 | elif [[ $type == "directory" ]]; then | |
60 | mkdir ${mntpnt}/d$objnum | |
61 | elif [[ $type == "missing" ]]; then | |
62 | touch ${mntpnt}/h$objnum | |
63 | fi | |
64 | } | |
65 | ||
66 | function create_pair | |
67 | { | |
68 | typeset objnum=$1 | |
69 | typeset mntpnt1=$2 | |
70 | typeset mntpnt2=$3 | |
71 | typeset type1=$4 | |
72 | typeset type2=$5 | |
73 | make_object $objnum $mntpnt1 $type1 | |
74 | make_object $objnum $mntpnt2 $type2 | |
75 | } | |
76 | ||
77 | function cleanup | |
78 | { | |
79 | zfs destroy -Rf $TESTPOOL/$TESTFS/base | |
80 | rm /tmp/zr010p* | |
81 | } | |
82 | ||
83 | log_assert "zfs receive of full send as clone should work" | |
84 | log_onexit cleanup | |
85 | log_must zfs create -o checksum=sha256 -o compression=gzip -o recordsize=512 \ | |
86 | $TESTPOOL/$TESTFS/base | |
87 | ||
88 | log_must zfs create $fs | |
89 | log_must zfs create $fs2 | |
90 | mntpnt=$(get_prop mountpoint $fs) | |
91 | mntpnt2=$(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). | |
102 | create_pair 8 $mntpnt $mntpnt2 "file" "file" | |
103 | ||
104 | # Receive a file onto a file with holes (and vice versa). | |
105 | create_pair 9 $mntpnt $mntpnt2 "file" "hole1" | |
106 | ||
107 | # Receive a file onto a directory (and vice versa). | |
108 | create_pair 10 $mntpnt $mntpnt2 "file" "directory" | |
109 | ||
110 | # Receive a file onto a missing object (and vice versa). | |
111 | create_pair 11 $mntpnt $mntpnt2 "file" "missing" | |
112 | ||
113 | # Receive a file with holes onto a file with holes (and vice versa). | |
114 | create_pair 12 $mntpnt $mntpnt2 "hole1" "hole2" | |
115 | ||
116 | # Receive a file with holes onto a directory (and vice versa). | |
117 | create_pair 13 $mntpnt $mntpnt2 "hole1" "directory" | |
118 | ||
119 | # Receive a file with holes onto a missing object (and vice versa). | |
120 | create_pair 14 $mntpnt $mntpnt2 "hole1" "missing" | |
121 | ||
122 | # Receive a directory onto a directory (and vice versa). | |
123 | create_pair 15 $mntpnt $mntpnt2 "directory" "directory" | |
124 | ||
125 | # Receive a directory onto a missing object (and vice versa). | |
126 | create_pair 16 $mntpnt $mntpnt2 "directory" "missing" | |
127 | ||
128 | # Receive a missing object onto a missing object (and vice versa). | |
129 | create_pair 17 $mntpnt $mntpnt2 "missing" "missing" | |
130 | ||
131 | # Receive a file with a different record size onto a file (and vice versa). | |
132 | log_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 | |
141 | for i in {1..100}; do | |
142 | log_must touch $mntpnt/uf$i | |
143 | done | |
144 | ||
145 | log_must zfs snapshot $fs@s1 | |
146 | log_must zfs snapshot $fs2@s1 | |
147 | ||
148 | log_must zfs send $fs@s1 > /tmp/zr010p | |
149 | log_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 | # | |
156 | cat /tmp/zr010p | log_must zfs receive -o origin=$fs@s1 $rfs | |
157 | size=$(get_prop used $rfs) | |
158 | size2=$(get_prop used $fs) | |
159 | if [[ $size -ge $(($size2 / 10)) ]] then | |
160 | log_fail "nop-write failure; expected usage less than "\ | |
161 | "$(($size2 / 10)), but is using $size" | |
162 | fi | |
163 | log_must zfs destroy -fr $rfs | |
164 | ||
165 | # Correctness testing: receive each full send as a clone of the other fiesystem. | |
166 | cat /tmp/zr010p | log_must zfs receive -o origin=$fs2@s1 $rfs | |
167 | mntpnt_old=$(get_prop mountpoint $fs) | |
168 | mntpnt_new=$(get_prop mountpoint $rfs) | |
169 | log_must diff -r $mntpnt_old $mntpnt_new | |
170 | log_must zfs destroy -r $rfs | |
171 | ||
172 | cat /tmp/zr010p2 | log_must zfs receive -o origin=$fs@s1 $rfs | |
173 | mntpnt_old=$(get_prop mountpoint $fs2) | |
174 | mntpnt_new=$(get_prop mountpoint $rfs) | |
175 | log_must diff -r $mntpnt_old $mntpnt_new | |
176 | ||
177 | log_pass "zfs receive of full send as clone works" |