]> git.proxmox.com Git - mirror_zfs-debian.git/blob - tests/zfs-tests/tests/functional/cli_root/zfs_receive/receive-o-x_props_override.ksh
7137fe278f98b9de418d374e4f65444a94b6b2d4
[mirror_zfs-debian.git] / tests / zfs-tests / tests / functional / cli_root / zfs_receive / receive-o-x_props_override.ksh
1 #!/bin/ksh -p
2 #
3 # CDDL HEADER START
4 #
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
8 # 1.0 of the CDDL.
9 #
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.
13 #
14 # CDDL HEADER END
15 #
16
17 #
18 # Copyright 2017, loli10K <ezomori.nozomu@gmail.com>. All rights reserved.
19 #
20
21 . $STF_SUITE/include/libtest.shlib
22 . $STF_SUITE/tests/functional/cli_root/zfs_set/zfs_set_common.kshlib
23
24 #
25 # DESCRIPTION:
26 # Verify ZFS property override (-o) and exclude (-x) options work when
27 # receiving a send stream
28 #
29 # STRATEGY:
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.
34 #
35
36 verify_runnable "both"
37
38 function cleanup
39 {
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 log_must zfs destroy -r -f $orig
45 log_must zfs destroy -r -f $dest
46 }
47
48 #
49 # Verify property $2 is set from source $4 on dataset $1 and has value $3.
50 #
51 # $1 checked dataset
52 # $2 user property
53 # $3 property value
54 # $4 source
55 #
56 function check_prop_source
57 {
58 typeset dataset="$1"
59 typeset prop="$2"
60 typeset value="$3"
61 typeset source="$4"
62 typeset chk_value=$(get_prop "$prop" "$dataset")
63 typeset chk_source=$(get_source "$prop" "$dataset")
64
65 if [[ "$chk_value" != "$value" || "$chk_source" != "$4" ]]
66 then
67 return 1
68 else
69 return 0
70 fi
71 }
72
73 #
74 # Verify target dataset $1 inherit property $2 from dataset $3.
75 #
76 # $1 checked dataset
77 # $2 property
78 # $3 inherited dataset
79 #
80 function check_prop_inherit
81 {
82 typeset checked_dtst="$1"
83 typeset prop="$2"
84 typeset inherited_dtst="$3"
85 typeset inherited_value=$(get_prop "$prop" "$inherited_dtst")
86 typeset value=$(get_prop "$prop" "$checked_dtst")
87 typeset source=$(get_source "$prop" "$checked_dtst")
88
89 if [[ "$value" != "$inherited_value" || \
90 "$source" != "inherited from $inherited_dtst" ]]
91 then
92 return 1
93 else
94 return 0
95 fi
96 }
97
98 #
99 # Verify property $2 received value on dataset $1 has value $3
100 #
101 # $1 checked dataset
102 # $2 property name
103 # $3 checked value
104 #
105 function check_prop_received
106 {
107 typeset dataset="$1"
108 typeset prop="$2"
109 typeset value="$3"
110
111 received=$(zfs get -H -o received "$prop" "$dataset")
112 if (($? != 0)); then
113 log_fail "Unable to get $prop received value for dataset " \
114 "$dataset"
115 fi
116 if [[ "$received" == "$value" ]]
117 then
118 return 0
119 else
120 return 1
121 fi
122 }
123
124 #
125 # Verify user property $2 is not set on dataset $1
126 #
127 # $1 checked dataset
128 # $2 property name
129 #
130 function check_prop_missing
131 {
132 typeset dataset="$1"
133 typeset prop="$2"
134
135 value=$(zfs get -H -o value "$prop" "$dataset")
136 if (($? != 0)); then
137 log_fail "Unable to get $prop value for dataset $dataset"
138 fi
139 if [[ "-" == "$value" ]]
140 then
141 return 0
142 else
143 return 1
144 fi
145 }
146
147 log_assert "ZFS receive property override and exclude options work as expected."
148 log_onexit cleanup
149
150 orig=$TESTPOOL/$TESTFS1
151 origsub=$orig/sub
152 dest=$TESTPOOL/$TESTFS2
153 destsub=$dest/sub
154 typeset userprop=$(valid_user_property 8)
155 typeset userval=$(user_property_value 8)
156 typeset streamfile_full=$TESTDIR/streamfile_full.$$
157 typeset streamfile_incr=$TESTDIR/streamfile_incr.$$
158 typeset streamfile_repl=$TESTDIR/streamfile_repl.$$
159 typeset streamfile_trun=$TESTDIR/streamfile_trun.$$
160
161 #
162 # 3.1 Verify we can't specify the same property in multiple -o or -x options
163 # or an invalid value was specified.
164 #
165 # Create a full send stream
166 log_must zfs create $orig
167 log_must zfs snapshot $orig@snap1
168 log_must eval "zfs send $orig@snap1 > $streamfile_full"
169 # Verify we reject invalid options
170 log_mustnot eval "zfs recv $dest -o atime < $streamfile_full"
171 log_mustnot eval "zfs recv $dest -x atime=off < $streamfile_full"
172 log_mustnot eval "zfs recv $dest -o atime=off -x atime < $streamfile_full"
173 log_mustnot eval "zfs recv $dest -o atime=off -o atime=on < $streamfile_full"
174 log_mustnot eval "zfs recv $dest -x atime -x atime < $streamfile_full"
175 log_mustnot eval "zfs recv $dest -o version=1 < $streamfile_full"
176 log_mustnot eval "zfs recv $dest -x version < $streamfile_full"
177 log_mustnot eval "zfs recv $dest -x normalization < $streamfile_full"
178 # Verify we also reject invalid ZVOL options
179 log_must zfs create -V 32K -s $orig/zvol
180 log_must eval "zfs send $orig@snap1 > $streamfile_full"
181 log_mustnot eval "zfs recv $dest -x volsize < $streamfile_full"
182 log_mustnot eval "zfs recv $dest -o volsize=32K < $streamfile_full"
183 # Cleanup
184 block_device_wait
185 log_must_busy zfs destroy -r -f $orig
186
187 #
188 # 3.2 Verify -o property=value works on streams without properties.
189 #
190 # Create a full send stream
191 log_must zfs create $orig
192 log_must zfs snapshot $orig@snap1
193 log_must eval "zfs send $orig@snap1 > $streamfile_full"
194 # Receive the full stream, override some properties
195 log_must eval "zfs recv -o compression=on -o '$userprop:dest'='$userval' "\
196 "$dest < $streamfile_full"
197 log_must eval "check_prop_source $dest compression on local"
198 log_must eval "check_prop_source $dest '$userprop:dest' '$userval' local"
199 # Cleanup
200 log_must zfs destroy -r -f $orig
201 log_must zfs destroy -r -f $dest
202
203 #
204 # 3.3 Verify -o property=value and -x work on both native and user properties
205 # for an incremental replication send stream.
206 #
207 # Create a dataset tree and receive it
208 log_must zfs create $orig
209 log_must zfs create $origsub
210 log_must zfs snapshot -r $orig@snap1
211 log_must eval "zfs send -R $orig@snap1 > $streamfile_repl"
212 log_must eval "zfs recv $dest < $streamfile_repl"
213 # Fill the datasets with properties and create an incremental replication stream
214 log_must zfs snapshot -r $orig@snap2
215 log_must eval "zfs set copies=2 $orig"
216 log_must eval "zfs set '$userprop:orig'='$userval' $orig"
217 log_must eval "zfs set '$userprop:orig'='$userval' $origsub"
218 log_must eval "zfs set '$userprop:snap'='$userval' $orig@snap1"
219 log_must eval "zfs set '$userprop:snap'='$userval' $origsub@snap2"
220 log_must eval "zfs send -R -I $orig@snap1 $orig@snap2 > $streamfile_incr"
221 # Sets various combination of override and exclude options
222 log_must eval "zfs recv -F -o atime=off -o '$userprop:dest2'='$userval' "\
223 "-o quota=123456789 -x compression -x '$userprop:orig' " \
224 "-x '$userprop:snap2' $dest < $streamfile_incr"
225 # Verify we can correctly override and exclude properties
226 log_must eval "check_prop_source $dest copies 2 received"
227 log_must eval "check_prop_source $dest atime off local"
228 log_must eval "check_prop_source $dest '$userprop:dest2' '$userval' local"
229 log_must eval "check_prop_source $dest quota 123456789 local"
230 log_must eval "check_prop_inherit $destsub copies $dest"
231 log_must eval "check_prop_inherit $destsub atime $dest"
232 log_must eval "check_prop_inherit $destsub '$userprop:dest2' $dest"
233 log_must eval "check_prop_source $destsub quota 0 default"
234 log_must eval "check_prop_source $destsub compression off default"
235 log_must eval "check_prop_missing $dest '$userprop:orig'"
236 log_must eval "check_prop_missing $destsub '$userprop:orig'"
237 log_must eval "check_prop_source " \
238 "$dest@snap1 '$userprop:snap' '$userval' received"
239 log_must eval "check_prop_source " \
240 "$destsub@snap2 '$userprop:snap' '$userval' received"
241 log_must eval "check_prop_missing $dest@snap2 '$userprop:snap2'"
242 log_must eval "check_prop_missing $destsub@snap2 '$userprop:snap2'"
243 # Cleanup
244 log_must zfs destroy -r -f $orig
245 log_must zfs destroy -r -f $dest
246
247 #
248 # 3.4 Verify '-x property' does not remove existing local properties and a
249 # modified sent property is received and updated to the new value but can
250 # still be excluded.
251 #
252 # Create a dataset tree
253 log_must zfs create $orig
254 log_must zfs create $origsub
255 log_must zfs snapshot -r $orig@snap1
256 log_must eval "zfs set copies=2 $orig"
257 log_must eval "zfs set '$userprop:orig'='oldval' $orig"
258 log_must eval "zfs set '$userprop:orig'='oldsubval' $origsub"
259 log_must eval "zfs send -R $orig@snap1 > $streamfile_repl"
260 log_must eval "zfs receive $dest < $streamfile_repl"
261 log_must eval "check_prop_source $dest copies 2 received"
262 log_must eval "check_prop_inherit $destsub copies $dest"
263 log_must eval "check_prop_source $dest '$userprop:orig' 'oldval' received"
264 log_must eval "check_prop_source $destsub '$userprop:orig' 'oldsubval' received"
265 # Set new custom properties on both source and destination
266 log_must eval "zfs set copies=3 $orig"
267 log_must eval "zfs set '$userprop:orig'='newval' $orig"
268 log_must eval "zfs set '$userprop:orig'='newsubval' $origsub"
269 log_must eval "zfs set compression=gzip $dest"
270 log_must eval "zfs set '$userprop:dest'='localval' $dest"
271 # Receive the new stream, verify we preserve locally set properties
272 log_must zfs snapshot -r $orig@snap2
273 log_must eval "zfs send -R -I $orig@snap1 $orig@snap2 > $streamfile_incr"
274 log_must eval "zfs recv -F -x copies -x compression -x '$userprop:orig' " \
275 "-x '$userprop:dest' $dest < $streamfile_incr"
276 log_must eval "check_prop_source $dest '$userprop:dest' 'localval' local"
277 log_must eval "check_prop_received $dest '$userprop:orig' 'newval'"
278 log_must eval "check_prop_received $destsub '$userprop:orig' 'newsubval'"
279 log_must eval "check_prop_missing $dest '$userprop:orig'"
280 log_must eval "check_prop_missing $destsub '$userprop:orig'"
281 log_must eval "check_prop_source $dest copies 1 default"
282 log_must eval "check_prop_received $dest copies 3"
283 log_must eval "check_prop_source $destsub copies 1 default"
284 log_must eval "check_prop_received $destsub copies '-'"
285 log_must eval "check_prop_source $dest compression gzip local"
286 log_must eval "check_prop_inherit $destsub compression $dest"
287 # Cleanup
288 log_must zfs destroy -r -f $orig
289 log_must zfs destroy -r -f $dest
290
291 #
292 # 3.5 Verify we can exclude non-inheritable properties from a send stream
293 #
294 # Create a dataset tree and replication stream
295 log_must zfs create $orig
296 log_must zfs create $origsub
297 log_must zfs snapshot -r $orig@snap1
298 log_must eval "zfs set quota=123456789 $orig"
299 log_must eval "zfs send -R $orig@snap1 > $streamfile_repl"
300 # Receive the stream excluding non-inheritable properties
301 log_must eval "zfs recv -F -x quota $dest < $streamfile_repl"
302 log_must eval "check_prop_source $dest quota 0 default"
303 log_must eval "check_prop_source $destsub quota 0 default"
304 # Set some non-inheritable properties on the destination, verify we keep them
305 log_must eval "zfs set quota=123456789 $dest"
306 log_must eval "zfs set canmount=off $destsub"
307 log_must zfs snapshot -r $orig@snap2
308 log_must eval "zfs send -R -I $orig@snap1 $orig@snap2 > $streamfile_incr"
309 log_must eval "zfs recv -F -x quota -x canmount $dest < $streamfile_incr"
310 log_must eval "check_prop_source $dest quota 123456789 local"
311 log_must eval "check_prop_source $destsub quota 0 default"
312 log_must eval "check_prop_source $destsub canmount off local"
313 # Cleanup
314 log_must zfs destroy -r -f $orig
315 log_must zfs destroy -r -f $dest
316
317 #
318 # 3.6 Verify we correctly restore existing properties on a failed receive
319 #
320 # Receive a "clean" dataset tree
321 log_must zfs create $orig
322 log_must zfs create $origsub
323 log_must zfs snapshot -r $orig@snap1
324 log_must eval "zfs send -R $orig@snap1 > $streamfile_repl"
325 log_must eval "zfs receive $dest < $streamfile_repl"
326 # Set custom properties on the destination
327 log_must eval "zfs set atime=off $dest"
328 log_must eval "zfs set quota=123456789 $dest"
329 log_must eval "zfs set '$userprop:orig'='$userval' $dest"
330 log_must eval "zfs set '$userprop:origsub'='$userval' $destsub"
331 # Create a truncated incremental replication stream
332 mntpnt=$(get_prop mountpoint $orig)
333 log_must eval "dd if=/dev/urandom of=$mntpnt/file bs=1024k count=10"
334 log_must zfs snapshot -r $orig@snap2
335 log_must eval "zfs send -R -I $orig@snap1 $orig@snap2 > $streamfile_incr"
336 log_must eval "dd if=$streamfile_incr of=$streamfile_trun bs=1024k count=9"
337 # Receive the truncated stream, verify original properties are kept
338 log_mustnot eval "zfs recv -F -o copies=3 -o quota=987654321 "\
339 "-o '$userprop:new'='badval' $dest < $streamfile_trun"
340 log_must eval "check_prop_source $dest copies 1 default"
341 log_must eval "check_prop_source $destsub copies 1 default"
342 log_must eval "check_prop_source $dest atime off local"
343 log_must eval "check_prop_inherit $destsub atime $dest"
344 log_must eval "check_prop_source $dest quota 123456789 local"
345 log_must eval "check_prop_source $destsub quota 0 default"
346 log_must eval "check_prop_source $dest '$userprop:orig' '$userval' local"
347 log_must eval "check_prop_inherit $destsub '$userprop:orig' $dest"
348 log_must eval "check_prop_source $destsub '$userprop:origsub' '$userval' local"
349 log_must eval "check_prop_missing $dest '$userprop:new'"
350 # Cleanup
351 log_must zfs destroy -r -f $orig
352 log_must zfs destroy -r -f $dest
353
354 #
355 # 3.7 Verify we can't receive a send stream overriding or excluding properties
356 # invalid for the dataset type unless the stream it's recursive, in which
357 # case only the appropriate properties are set on the destination.
358 #
359 log_must zfs create -V 128K -s $orig
360 log_must zfs snapshot $orig@snap1
361 log_must eval "zfs send $orig@snap1 > $streamfile_full"
362 log_mustnot eval "zfs receive -x atime $dest < $streamfile_full"
363 log_mustnot eval "zfs receive -o atime=off $dest < $streamfile_full"
364 log_must zfs destroy -r -f $orig
365 log_must zfs create $orig
366 log_must zfs create -V 128K -s $origsub
367 log_must zfs snapshot -r $orig@snap1
368 log_must eval "zfs send -R $orig@snap1 > $streamfile_repl"
369 log_must eval "zfs receive -o atime=off $dest < $streamfile_repl"
370 log_must eval "check_prop_source $dest type filesystem -"
371 log_must eval "check_prop_source $dest atime off local"
372 log_must eval "check_prop_source $destsub type volume -"
373 log_must eval "check_prop_source $destsub atime - -"
374 # We don't need to cleanup here
375
376 log_pass "ZFS receive property override and exclude options passed."