xref: /illumos-gate/usr/src/test/zfs-tests/tests/functional/cli_root/zfs_receive/receive-o-x_props_override.ksh (revision 5801b0f01c3c34499a929ed96164a5a68b470945)
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
36verify_runnable "both"
37
38function 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	destroy_dataset "$orig" "-rf"
45	destroy_dataset "$dest" "-rf"
46}
47
48log_assert "ZFS receive property override and exclude options work as expected."
49log_onexit cleanup
50
51orig=$TESTPOOL/$TESTFS1
52origsub=$orig/sub
53dest=$TESTPOOL/$TESTFS2
54destsub=$dest/sub
55typeset userprop=$(valid_user_property 8)
56typeset userval=$(user_property_value 8)
57typeset streamfile_full=$TESTDIR/streamfile_full.$$
58typeset streamfile_incr=$TESTDIR/streamfile_incr.$$
59typeset streamfile_repl=$TESTDIR/streamfile_repl.$$
60typeset streamfile_trun=$TESTDIR/streamfile_trun.$$
61
62#
63# 3.1 Verify we can't specify the same property in multiple -o or -x options
64#     or an invalid value was specified.
65#
66# Create a full send stream
67log_must zfs create $orig
68log_must zfs snapshot $orig@snap1
69log_must eval "zfs send $orig@snap1 > $streamfile_full"
70# Verify we reject invalid options
71log_mustnot eval "zfs recv $dest -o atime < $streamfile_full"
72log_mustnot eval "zfs recv $dest -x atime=off < $streamfile_full"
73log_mustnot eval "zfs recv $dest -o atime=off -x atime < $streamfile_full"
74log_mustnot eval "zfs recv $dest -o atime=off -o atime=on < $streamfile_full"
75log_mustnot eval "zfs recv $dest -x atime -x atime < $streamfile_full"
76log_mustnot eval "zfs recv $dest -o version=1 < $streamfile_full"
77log_mustnot eval "zfs recv $dest -x version < $streamfile_full"
78log_mustnot eval "zfs recv $dest -x normalization < $streamfile_full"
79# Verify we also reject invalid ZVOL options
80log_must zfs create -V 32K -s $orig/zvol
81log_must eval "zfs send $orig@snap1 > $streamfile_full"
82log_mustnot eval "zfs recv $dest -x volsize < $streamfile_full"
83log_mustnot eval "zfs recv $dest -o volsize=32K < $streamfile_full"
84# Cleanup
85block_device_wait
86log_must_busy zfs destroy -r -f $orig
87
88#
89# 3.2 Verify -o property=value works on streams without properties.
90#
91# Create a full send stream
92log_must zfs create $orig
93log_must zfs snapshot $orig@snap1
94log_must eval "zfs send $orig@snap1 > $streamfile_full"
95# Receive the full stream, override some properties
96log_must eval "zfs recv -o compression=on -o '$userprop:dest'='$userval' "\
97	"$dest < $streamfile_full"
98log_must eval "check_prop_source $dest compression on local"
99log_must eval "check_prop_source $dest '$userprop:dest' '$userval' local"
100# Cleanup
101log_must zfs destroy -r -f $orig
102log_must zfs destroy -r -f $dest
103
104#
105# 3.3 Verify -o property=value and -x work on both native and user properties
106#     for an incremental replication send stream.
107#
108# Create a dataset tree and receive it
109log_must zfs create $orig
110log_must zfs create $origsub
111log_must zfs snapshot -r $orig@snap1
112log_must eval "zfs send -R $orig@snap1 > $streamfile_repl"
113log_must eval "zfs recv $dest < $streamfile_repl"
114# Fill the datasets with properties and create an incremental replication stream
115log_must zfs snapshot -r $orig@snap2
116log_must zfs snapshot -r $orig@snap3
117log_must eval "zfs set copies=2 $orig"
118log_must eval "zfs set '$userprop:orig'='$userval' $orig"
119log_must eval "zfs set '$userprop:orig'='$userval' $origsub"
120log_must eval "zfs set '$userprop:snap'='$userval' $orig@snap1"
121log_must eval "zfs set '$userprop:snap'='$userval' $origsub@snap3"
122log_must eval "zfs send -R -I $orig@snap1 $orig@snap3 > $streamfile_incr"
123# Sets various combination of override and exclude options
124log_must eval "zfs recv -F -o atime=off -o '$userprop:dest2'='$userval' "\
125	"-o quota=123456789 -x compression "\
126        "-x '$userprop:orig' -x '$userprop:snap3' $dest < $streamfile_incr"
127# Verify we can correctly override and exclude properties
128log_must eval "check_prop_source $dest copies 2 received"
129log_must eval "check_prop_source $dest atime off local"
130log_must eval "check_prop_source $dest '$userprop:dest2' '$userval' local"
131log_must eval "check_prop_source $dest quota 123456789 local"
132log_must eval "check_prop_inherit $destsub copies $dest"
133log_must eval "check_prop_inherit $destsub atime $dest"
134log_must eval "check_prop_inherit $destsub '$userprop:dest2' $dest"
135log_must eval "check_prop_source $destsub quota 0 default"
136log_must eval "check_prop_source $destsub compression off default"
137log_must eval "check_prop_missing $dest '$userprop:orig'"
138log_must eval "check_prop_missing $destsub '$userprop:orig'"
139log_must eval "check_prop_source " \
140	"$dest@snap1 '$userprop:snap' '$userval' received"
141log_must eval "check_prop_source " \
142	"$destsub@snap3 '$userprop:snap' '$userval' received"
143log_must eval "check_prop_missing $dest@snap3 '$userprop:snap3'"
144log_must eval "check_prop_missing $destsub@snap3 '$userprop:snap3'"
145# Cleanup
146log_must zfs destroy -r -f $orig
147log_must zfs destroy -r -f $dest
148
149#
150# 3.4 Verify '-x property' does not remove existing local properties and a
151#     modified sent property is received and updated to the new value but can
152#     still be excluded.
153#
154# Create a dataset tree
155log_must zfs create $orig
156log_must zfs create $origsub
157log_must zfs snapshot -r $orig@snap1
158log_must eval "zfs set copies=2 $orig"
159log_must eval "zfs set '$userprop:orig'='oldval' $orig"
160log_must eval "zfs set '$userprop:orig'='oldsubval' $origsub"
161log_must eval "zfs send -R $orig@snap1 > $streamfile_repl"
162log_must eval "zfs receive $dest < $streamfile_repl"
163log_must eval "check_prop_source $dest copies 2 received"
164log_must eval "check_prop_inherit $destsub copies $dest"
165log_must eval "check_prop_source $dest '$userprop:orig' 'oldval' received"
166log_must eval "check_prop_source $destsub '$userprop:orig' 'oldsubval' received"
167# Set new custom properties on both source and destination
168log_must eval "zfs set copies=3 $orig"
169log_must eval "zfs set '$userprop:orig'='newval' $orig"
170log_must eval "zfs set '$userprop:orig'='newsubval' $origsub"
171log_must eval "zfs set compression=gzip $dest"
172log_must eval "zfs set '$userprop:dest'='localval' $dest"
173# Receive the new stream, verify we preserve locally set properties
174log_must zfs snapshot -r $orig@snap2
175log_must zfs snapshot -r $orig@snap3
176log_must eval "zfs send -R -I $orig@snap1 $orig@snap3 > $streamfile_incr"
177log_must eval "zfs recv -F -x copies -x compression -x '$userprop:orig' " \
178	"-x '$userprop:dest' $dest < $streamfile_incr"
179log_must eval "check_prop_source $dest '$userprop:dest' 'localval' local"
180log_must eval "check_prop_received $dest '$userprop:orig' 'newval'"
181log_must eval "check_prop_received $destsub '$userprop:orig' 'newsubval'"
182log_must eval "check_prop_missing $dest '$userprop:orig'"
183log_must eval "check_prop_missing $destsub '$userprop:orig'"
184log_must eval "check_prop_source $dest copies 1 default"
185log_must eval "check_prop_received $dest copies 3"
186log_must eval "check_prop_source $destsub copies 1 default"
187log_must eval "check_prop_received $destsub copies '-'"
188log_must eval "check_prop_source $dest compression gzip local"
189log_must eval "check_prop_inherit $destsub compression $dest"
190# Cleanup
191log_must zfs destroy -r -f $orig
192log_must zfs destroy -r -f $dest
193
194#
195# 3.5 Verify we can exclude non-inheritable properties from a send stream
196#
197# Create a dataset tree and replication stream
198log_must zfs create $orig
199log_must zfs create $origsub
200log_must zfs snapshot -r $orig@snap1
201log_must eval "zfs set quota=123456789 $orig"
202log_must eval "zfs send -R $orig@snap1 > $streamfile_repl"
203# Receive the stream excluding non-inheritable properties
204log_must eval "zfs recv -F -x quota $dest < $streamfile_repl"
205log_must eval "check_prop_source $dest quota 0 default"
206log_must eval "check_prop_source $destsub quota 0 default"
207# Set some non-inheritable properties on the destination, verify we keep them
208log_must eval "zfs set quota=123456789 $dest"
209log_must eval "zfs set canmount=off $destsub"
210log_must zfs snapshot -r $orig@snap2
211log_must zfs snapshot -r $orig@snap3
212log_must eval "zfs send -R -I $orig@snap1 $orig@snap3 > $streamfile_incr"
213log_must eval "zfs recv -F -x quota -x canmount $dest < $streamfile_incr"
214log_must eval "check_prop_source $dest quota 123456789 local"
215log_must eval "check_prop_source $destsub quota 0 default"
216log_must eval "check_prop_source $destsub canmount off local"
217# Cleanup
218log_must zfs destroy -r -f $orig
219log_must zfs destroy -r -f $dest
220
221#
222# 3.6 Verify we correctly restore existing properties on a failed receive
223#
224# Receive a "clean" dataset tree
225log_must zfs create $orig
226log_must zfs create $origsub
227log_must zfs snapshot -r $orig@snap1
228log_must eval "zfs send -R $orig@snap1 > $streamfile_repl"
229log_must eval "zfs receive $dest < $streamfile_repl"
230# Set custom properties on the destination
231log_must eval "zfs set atime=off $dest"
232log_must eval "zfs set quota=123456789 $dest"
233log_must eval "zfs set '$userprop:orig'='$userval' $dest"
234log_must eval "zfs set '$userprop:origsub'='$userval' $destsub"
235# Create a truncated incremental replication stream
236mntpnt=$(get_prop mountpoint $orig)
237log_must eval "dd if=/dev/urandom of=$mntpnt/file bs=1024k count=10"
238log_must zfs snapshot -r $orig@snap2
239log_must zfs snapshot -r $orig@snap3
240log_must eval "zfs send -R -I $orig@snap1 $orig@snap3 > $streamfile_incr"
241log_must eval "dd if=$streamfile_incr of=$streamfile_trun bs=1024k count=9"
242# Receive the truncated stream, verify original properties are kept
243log_mustnot eval "zfs recv -F -o copies=3 -o quota=987654321 "\
244	"-o '$userprop:new'='badval' $dest < $streamfile_trun"
245log_must eval "check_prop_source $dest copies 1 default"
246log_must eval "check_prop_source $destsub copies 1 default"
247log_must eval "check_prop_source $dest atime off local"
248log_must eval "check_prop_inherit $destsub atime $dest"
249log_must eval "check_prop_source $dest quota 123456789 local"
250log_must eval "check_prop_source $destsub quota 0 default"
251log_must eval "check_prop_source $dest '$userprop:orig' '$userval' local"
252log_must eval "check_prop_inherit $destsub '$userprop:orig' $dest"
253log_must eval "check_prop_source $destsub '$userprop:origsub' '$userval' local"
254log_must eval "check_prop_missing $dest '$userprop:new'"
255# Cleanup
256log_must zfs destroy -r -f $orig
257log_must zfs destroy -r -f $dest
258
259#
260# 3.7 Verify we can't receive a send stream overriding or excluding properties
261#     invalid for the dataset type unless the stream it's recursive, in which
262#     case only the appropriate properties are set on the destination.
263#
264log_must zfs create -V 128K -s $orig
265log_must zfs snapshot $orig@snap1
266log_must eval "zfs send $orig@snap1 > $streamfile_full"
267log_mustnot eval "zfs receive -x atime $dest < $streamfile_full"
268log_mustnot eval "zfs receive -o atime=off $dest < $streamfile_full"
269log_must_busy zfs destroy -r -f $orig
270log_must zfs create $orig
271log_must zfs create -V 128K -s $origsub
272log_must zfs snapshot -r $orig@snap1
273log_must eval "zfs send -R $orig@snap1 > $streamfile_repl"
274log_must eval "zfs receive -o atime=off $dest < $streamfile_repl"
275log_must eval "check_prop_source $dest type filesystem -"
276log_must eval "check_prop_source $dest atime off local"
277log_must eval "check_prop_source $destsub type volume -"
278log_must eval "check_prop_source $destsub atime - -"
279# Cleanup
280block_device_wait
281log_must_busy zfs destroy -r -f $orig
282log_must_busy zfs destroy -r -f $dest
283
284#
285# 3.8 Verify 'zfs recv -x|-o' works correctly when used in conjunction with -d
286#     and -e options.
287#
288log_must zfs create -p $orig/1/2/3/4
289log_must eval "zfs set copies=2 $orig"
290log_must eval "zfs set atime=on $orig"
291log_must eval "zfs set '$userprop:orig'='oldval' $orig"
292log_must zfs snapshot -r $orig@snap1
293log_must eval "zfs send -R $orig/1/2@snap1 > $streamfile_repl"
294# Verify 'zfs recv -e'
295log_must zfs create $dest
296log_must eval "zfs receive -e -o copies=3 -x atime "\
297	"-o '$userprop:orig'='newval' $dest < $streamfile_repl"
298log_must datasetexists $dest/2/3/4
299log_must eval "check_prop_source $dest/2 copies 3 local"
300log_must eval "check_prop_inherit $dest/2/3/4 copies $dest/2"
301log_must eval "check_prop_source $dest/2/3/4 atime on default"
302log_must eval "check_prop_source $dest/2 '$userprop:orig' 'newval' local"
303log_must eval "check_prop_inherit $dest/2/3/4 '$userprop:orig' $dest/2"
304log_must zfs destroy -r -f $dest
305# Verify 'zfs recv -d'
306log_must zfs create $dest
307typeset fs="$(echo $orig | awk -F'/' '{print $NF}')"
308log_must eval "zfs receive -d -o copies=3 -x atime "\
309	"-o '$userprop:orig'='newval' $dest < $streamfile_repl"
310log_must datasetexists $dest/$fs/1/2/3/4
311log_must eval "check_prop_source $dest/$fs/1/2 copies 3 local"
312log_must eval "check_prop_inherit $dest/$fs/1/2/3/4 copies $dest/$fs/1/2"
313log_must eval "check_prop_source $dest/$fs/1/2/3/4 atime on default"
314log_must eval "check_prop_source $dest/$fs/1/2 '$userprop:orig' 'newval' local"
315log_must eval "check_prop_inherit $dest/$fs/1/2/3/4 '$userprop:orig' $dest/$fs/1/2"
316# We don't need to cleanup here
317
318log_pass "ZFS receive property override and exclude options passed."
319