5 # This file and its contents are supplied under the terms of the
6 # Common Development and Distribution License ("CDDL"), version 1.0.
7 # You may only use this file in accordance with the terms of version
10 # A full copy of the text of the CDDL should have accompanied this
11 # source. A copy of the CDDL is also available via the Internet at
12 # http://www.illumos.org/license/CDDL.
18 # Copyright 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
21 . $STF_SUITE/include/libtest.shlib
22 . $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
26 # Verify ZFS property override (-o) and exclude (-x) options work when
27 # receiving a send stream
30 # 1. Create a filesystem with children.
31 # 2. Snapshot the filesystems.
32 # 3. Create various send streams (full, incremental, replication) and verify
33 # we can both override and exclude native and user properties.
36 verify_runnable "both"
40 log_must rm -f $streamfile_full
41 log_must rm -f $streamfile_incr
42 log_must rm -f $streamfile_repl
43 log_must rm -f $streamfile_trun
44 destroy_dataset "$orig" "-rf"
45 destroy_dataset "$dest" "-rf"
48 log_assert "ZFS receive property override and exclude options work as expected."
51 orig=$TESTPOOL/$TESTFS1
53 dest=$TESTPOOL/$TESTFS2
55 typeset userprop=$(valid_user_property 8)
56 typeset userval=$(user_property_value 8)
57 typeset streamfile_full=$TESTDIR/streamfile_full.$$
58 typeset streamfile_incr=$TESTDIR/streamfile_incr.$$
59 typeset streamfile_repl=$TESTDIR/streamfile_repl.$$
60 typeset streamfile_trun=$TESTDIR/streamfile_trun.$$
63 # 3.1 Verify we can't specify the same property in multiple -o or -x options
64 # or an invalid value was specified.
66 # Create a full send stream
67 log_must zfs create $orig
68 log_must zfs snapshot $orig@snap1
69 log_must eval "zfs send $orig@snap1 > $streamfile_full"
70 # Verify we reject invalid options
71 log_mustnot eval "zfs recv $dest -o atime < $streamfile_full"
72 log_mustnot eval "zfs recv $dest -x atime=off < $streamfile_full"
73 log_mustnot eval "zfs recv $dest -o atime=off -x atime < $streamfile_full"
74 log_mustnot eval "zfs recv $dest -o atime=off -o atime=on < $streamfile_full"
75 log_mustnot eval "zfs recv $dest -x atime -x atime < $streamfile_full"
76 log_mustnot eval "zfs recv $dest -o version=1 < $streamfile_full"
77 log_mustnot eval "zfs recv $dest -x version < $streamfile_full"
78 log_mustnot eval "zfs recv $dest -x normalization < $streamfile_full"
79 # Verify we also reject invalid ZVOL options
80 log_must zfs create -V 32K -s $orig/zvol
81 log_must eval "zfs send $orig@snap1 > $streamfile_full"
82 log_mustnot eval "zfs recv $dest -x volsize < $streamfile_full"
83 log_mustnot eval "zfs recv $dest -o volsize=32K < $streamfile_full"
86 log_must_busy zfs destroy -r -f $orig
89 # 3.2 Verify -o property=value works on streams without properties.
91 # Create a full send stream
92 log_must zfs create $orig
93 log_must zfs snapshot $orig@snap1
94 log_must eval "zfs send $orig@snap1 > $streamfile_full"
95 # Receive the full stream, override some properties
96 log_must eval "zfs recv -o compression=on -o '$userprop:dest'='$userval' "\
97 "$dest < $streamfile_full"
98 log_must eval "check_prop_source $dest compression on local"
99 log_must eval "check_prop_source $dest '$userprop:dest' '$userval' local"
101 log_must zfs destroy -r -f $orig
102 log_must zfs destroy -r -f $dest
105 # 3.3 Verify -o property=value and -x work on both native and user properties
106 # for an incremental replication send stream.
108 # Create a dataset tree and receive it
109 log_must zfs create $orig
110 log_must zfs create $origsub
111 log_must zfs snapshot -r $orig@snap1
112 log_must eval "zfs send -R $orig@snap1 > $streamfile_repl"
113 log_must eval "zfs recv $dest < $streamfile_repl"
114 # Fill the datasets with properties and create an incremental replication stream
115 log_must zfs snapshot -r $orig@snap2
116 log_must zfs snapshot -r $orig@snap3
117 log_must eval "zfs set copies=2 $orig"
118 log_must eval "zfs set '$userprop:orig'='$userval' $orig"
119 log_must eval "zfs set '$userprop:orig'='$userval' $origsub"
120 log_must eval "zfs set '$userprop:snap'='$userval' $orig@snap1"
121 log_must eval "zfs set '$userprop:snap'='$userval' $origsub@snap3"
122 log_must eval "zfs send -R -I $orig@snap1 $orig@snap3 > $streamfile_incr"
123 # Sets various combination of override and exclude options
124 log_must eval "zfs recv -F -o atime=off -o '$userprop:dest2'='$userval' "\
125 "-o quota=123456789 -o checksum=sha512 -x compression "\
126 "-x '$userprop:orig' -x '$userprop:snap3' $dest < $streamfile_incr"
127 # Verify we can correctly override and exclude properties
128 log_must eval "check_prop_source $dest copies 2 received"
129 log_must eval "check_prop_source $dest atime off local"
130 log_must eval "check_prop_source $dest '$userprop:dest2' '$userval' local"
131 log_must eval "check_prop_source $dest quota 123456789 local"
132 log_must eval "check_prop_source $dest checksum sha512 local"
133 log_must eval "check_prop_inherit $destsub copies $dest"
134 log_must eval "check_prop_inherit $destsub atime $dest"
135 log_must eval "check_prop_inherit $destsub checksum $dest"
136 log_must eval "check_prop_inherit $destsub '$userprop:dest2' $dest"
137 log_must eval "check_prop_source $destsub quota 0 default"
138 log_must eval "check_prop_source $destsub compression off default"
139 log_must eval "check_prop_missing $dest '$userprop:orig'"
140 log_must eval "check_prop_missing $destsub '$userprop:orig'"
141 log_must eval "check_prop_source " \
142 "$dest@snap1 '$userprop:snap' '$userval' received"
143 log_must eval "check_prop_source " \
144 "$destsub@snap3 '$userprop:snap' '$userval' received"
145 log_must eval "check_prop_missing $dest@snap3 '$userprop:snap3'"
146 log_must eval "check_prop_missing $destsub@snap3 '$userprop:snap3'"
148 log_must zfs destroy -r -f $orig
149 log_must zfs destroy -r -f $dest
152 # 3.4 Verify '-x property' does not remove existing local properties and a
153 # modified sent property is received and updated to the new value but can
156 # Create a dataset tree
157 log_must zfs create $orig
158 log_must zfs create $origsub
159 log_must zfs snapshot -r $orig@snap1
160 log_must eval "zfs set copies=2 $orig"
161 log_must eval "zfs set '$userprop:orig'='oldval' $orig"
162 log_must eval "zfs set '$userprop:orig'='oldsubval' $origsub"
163 log_must eval "zfs send -R $orig@snap1 > $streamfile_repl"
164 log_must eval "zfs receive $dest < $streamfile_repl"
165 log_must eval "check_prop_source $dest copies 2 received"
166 log_must eval "check_prop_inherit $destsub copies $dest"
167 log_must eval "check_prop_source $dest '$userprop:orig' 'oldval' received"
168 log_must eval "check_prop_source $destsub '$userprop:orig' 'oldsubval' received"
169 # Set new custom properties on both source and destination
170 log_must eval "zfs set copies=3 $orig"
171 log_must eval "zfs set '$userprop:orig'='newval' $orig"
172 log_must eval "zfs set '$userprop:orig'='newsubval' $origsub"
173 log_must eval "zfs set compression=gzip $dest"
174 log_must eval "zfs set '$userprop:dest'='localval' $dest"
175 # Receive the new stream, verify we preserve locally set properties
176 log_must zfs snapshot -r $orig@snap2
177 log_must zfs snapshot -r $orig@snap3
178 log_must eval "zfs send -R -I $orig@snap1 $orig@snap3 > $streamfile_incr"
179 log_must eval "zfs recv -F -x copies -x compression -x '$userprop:orig' " \
180 "-x '$userprop:dest' $dest < $streamfile_incr"
181 log_must eval "check_prop_source $dest '$userprop:dest' 'localval' local"
182 log_must eval "check_prop_received $dest '$userprop:orig' 'newval'"
183 log_must eval "check_prop_received $destsub '$userprop:orig' 'newsubval'"
184 log_must eval "check_prop_missing $dest '$userprop:orig'"
185 log_must eval "check_prop_missing $destsub '$userprop:orig'"
186 log_must eval "check_prop_source $dest copies 1 default"
187 log_must eval "check_prop_received $dest copies 3"
188 log_must eval "check_prop_source $destsub copies 1 default"
189 log_must eval "check_prop_received $destsub copies '-'"
190 log_must eval "check_prop_source $dest compression gzip local"
191 log_must eval "check_prop_inherit $destsub compression $dest"
193 log_must zfs destroy -r -f $orig
194 log_must zfs destroy -r -f $dest
197 # 3.5 Verify we can exclude non-inheritable properties from a send stream
199 # Create a dataset tree and replication stream
200 log_must zfs create $orig
201 log_must zfs create $origsub
202 log_must zfs snapshot -r $orig@snap1
203 log_must eval "zfs set quota=123456789 $orig"
204 log_must eval "zfs send -R $orig@snap1 > $streamfile_repl"
205 # Receive the stream excluding non-inheritable properties
206 log_must eval "zfs recv -F -x quota $dest < $streamfile_repl"
207 log_must eval "check_prop_source $dest quota 0 default"
208 log_must eval "check_prop_source $destsub quota 0 default"
209 # Set some non-inheritable properties on the destination, verify we keep them
210 log_must eval "zfs set quota=123456789 $dest"
211 log_must eval "zfs set canmount=off $destsub"
212 log_must zfs snapshot -r $orig@snap2
213 log_must zfs snapshot -r $orig@snap3
214 log_must eval "zfs send -R -I $orig@snap1 $orig@snap3 > $streamfile_incr"
215 log_must eval "zfs recv -F -x quota -x canmount $dest < $streamfile_incr"
216 log_must eval "check_prop_source $dest quota 123456789 local"
217 log_must eval "check_prop_source $destsub quota 0 default"
218 log_must eval "check_prop_source $destsub canmount off local"
220 log_must zfs destroy -r -f $orig
221 log_must zfs destroy -r -f $dest
224 # 3.6 Verify we correctly restore existing properties on a failed receive
226 # Receive a "clean" dataset tree
227 log_must zfs create $orig
228 log_must zfs create $origsub
229 log_must zfs snapshot -r $orig@snap1
230 log_must eval "zfs send -R $orig@snap1 > $streamfile_repl"
231 log_must eval "zfs receive $dest < $streamfile_repl"
232 # Set custom properties on the destination
233 log_must eval "zfs set atime=off $dest"
234 log_must eval "zfs set quota=123456789 $dest"
235 log_must eval "zfs set '$userprop:orig'='$userval' $dest"
236 log_must eval "zfs set '$userprop:origsub'='$userval' $destsub"
237 # Create a truncated incremental replication stream
238 mntpnt=$(get_prop mountpoint $orig)
239 log_must eval "dd if=/dev/urandom of=$mntpnt/file bs=1024k count=10"
240 log_must zfs snapshot -r $orig@snap2
241 log_must zfs snapshot -r $orig@snap3
242 log_must eval "zfs send -R -I $orig@snap1 $orig@snap3 > $streamfile_incr"
243 log_must eval "dd if=$streamfile_incr of=$streamfile_trun bs=1024k count=9"
244 # Receive the truncated stream, verify original properties are kept
245 log_mustnot eval "zfs recv -F -o copies=3 -o quota=987654321 "\
246 "-o '$userprop:new'='badval' $dest < $streamfile_trun"
247 log_must eval "check_prop_source $dest copies 1 default"
248 log_must eval "check_prop_source $destsub copies 1 default"
249 log_must eval "check_prop_source $dest atime off local"
250 log_must eval "check_prop_inherit $destsub atime $dest"
251 log_must eval "check_prop_source $dest quota 123456789 local"
252 log_must eval "check_prop_source $destsub quota 0 default"
253 log_must eval "check_prop_source $dest '$userprop:orig' '$userval' local"
254 log_must eval "check_prop_inherit $destsub '$userprop:orig' $dest"
255 log_must eval "check_prop_source $destsub '$userprop:origsub' '$userval' local"
256 log_must eval "check_prop_missing $dest '$userprop:new'"
258 log_must zfs destroy -r -f $orig
259 log_must zfs destroy -r -f $dest
262 # 3.7 Verify we can't receive a send stream overriding or excluding properties
263 # invalid for the dataset type unless the stream it's recursive, in which
264 # case only the appropriate properties are set on the destination.
266 log_must zfs create -V 128K -s $orig
267 log_must zfs snapshot $orig@snap1
268 log_must eval "zfs send $orig@snap1 > $streamfile_full"
269 log_mustnot eval "zfs receive -x atime $dest < $streamfile_full"
270 log_mustnot eval "zfs receive -o atime=off $dest < $streamfile_full"
271 log_must_busy zfs destroy -r -f $orig
272 log_must zfs create $orig
273 log_must zfs create -V 128K -s $origsub
274 log_must zfs snapshot -r $orig@snap1
275 log_must eval "zfs send -R $orig@snap1 > $streamfile_repl"
276 log_must eval "zfs receive -o atime=off $dest < $streamfile_repl"
277 log_must eval "check_prop_source $dest type filesystem -"
278 log_must eval "check_prop_source $dest atime off local"
279 log_must eval "check_prop_source $destsub type volume -"
280 log_must eval "check_prop_source $destsub atime - -"
283 log_must_busy zfs destroy -r -f $orig
284 log_must_busy zfs destroy -r -f $dest
287 # 3.8 Verify 'zfs recv -x|-o' works correctly when used in conjunction with -d
290 log_must zfs create -p $orig/1/2/3/4
291 log_must eval "zfs set copies=2 $orig"
292 log_must eval "zfs set atime=on $orig"
293 log_must eval "zfs set '$userprop:orig'='oldval' $orig"
294 log_must zfs snapshot -r $orig@snap1
295 log_must eval "zfs send -R $orig/1/2@snap1 > $streamfile_repl"
296 # Verify 'zfs recv -e'
297 log_must zfs create $dest
298 log_must eval "zfs receive -e -o copies=3 -x atime "\
299 "-o '$userprop:orig'='newval' $dest < $streamfile_repl"
300 log_must datasetexists $dest/2/3/4
301 log_must eval "check_prop_source $dest/2 copies 3 local"
302 log_must eval "check_prop_inherit $dest/2/3/4 copies $dest/2"
303 log_must eval "check_prop_source $dest/2/3/4 atime on default"
304 log_must eval "check_prop_source $dest/2 '$userprop:orig' 'newval' local"
305 log_must eval "check_prop_inherit $dest/2/3/4 '$userprop:orig' $dest/2"
306 log_must zfs destroy -r -f $dest
307 # Verify 'zfs recv -d'
308 log_must zfs create $dest
309 typeset fs="$(echo $orig | awk -F'/' '{print $NF}')"
310 log_must eval "zfs receive -d -o copies=3 -x atime "\
311 "-o '$userprop:orig'='newval' $dest < $streamfile_repl"
312 log_must datasetexists $dest/$fs/1/2/3/4
313 log_must eval "check_prop_source $dest/$fs/1/2 copies 3 local"
314 log_must eval "check_prop_inherit $dest/$fs/1/2/3/4 copies $dest/$fs/1/2"
315 log_must eval "check_prop_source $dest/$fs/1/2/3/4 atime on default"
316 log_must eval "check_prop_source $dest/$fs/1/2 '$userprop:orig' 'newval' local"
317 log_must eval "check_prop_inherit $dest/$fs/1/2/3/4 '$userprop:orig' $dest/$fs/1/2"
318 # We don't need to cleanup here
320 log_pass "ZFS receive property override and exclude options passed."