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, using property name aliases
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 aliased 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 alias override and exclude options work as expected."
49log_onexit cleanup
50
51orig=$TESTPOOL/$TESTFS1
52origsub=$orig/sub
53dest=$TESTPOOL/$TESTFS2
54destsub=$dest/sub
55typeset streamfile_full=$TESTDIR/streamfile_full.$$
56typeset streamfile_incr=$TESTDIR/streamfile_incr.$$
57typeset streamfile_repl=$TESTDIR/streamfile_repl.$$
58typeset streamfile_trun=$TESTDIR/streamfile_trun.$$
59
60#
61# 3.1 Verify we can't specify the same property in multiple -o or -x options
62#     or an invalid value was specified.
63#
64# Create a full send stream
65log_must zfs create $orig
66log_must zfs snapshot $orig@snap1
67log_must eval "zfs send $orig@snap1 > $streamfile_full"
68# Verify we reject invalid options
69log_mustnot eval "zfs recv $dest -o compress < $streamfile_full"
70log_mustnot eval "zfs recv $dest -x compress=off < $streamfile_full"
71log_mustnot eval "zfs recv $dest -o compress=off -x compress < $streamfile_full"
72log_mustnot eval "zfs recv $dest -o compress=off -o compress=on < $streamfile_full"
73log_mustnot eval "zfs recv $dest -x compress -x compress < $streamfile_full"
74log_mustnot eval "zfs recv $dest -o version=1 < $streamfile_full"
75log_mustnot eval "zfs recv $dest -x version < $streamfile_full"
76log_mustnot eval "zfs recv $dest -x normalization < $streamfile_full"
77# Verify we also reject invalid ZVOL options
78log_must zfs create -V 32K -s $orig/zvol
79log_must eval "zfs send $orig@snap1 > $streamfile_full"
80log_mustnot eval "zfs recv $dest -x volblock < $streamfile_full"
81log_mustnot eval "zfs recv $dest -o volblock=32K < $streamfile_full"
82# Cleanup
83block_device_wait
84log_must_busy zfs destroy -r -f $orig
85
86#
87# 3.2 Verify -o property=value works on streams without properties.
88#
89# Create a full send stream
90log_must zfs create $orig
91log_must zfs snapshot $orig@snap1
92log_must eval "zfs send $orig@snap1 > $streamfile_full"
93# Receive the full stream, override some properties
94log_must eval "zfs recv -o compress=on -o '$userprop:dest'='$userval' "\
95	"$dest < $streamfile_full"
96log_must eval "check_prop_source $dest compression on local"
97log_must eval "check_prop_source $dest '$userprop:dest' '$userval' local"
98# Cleanup
99log_must zfs destroy -r -f $orig
100log_must zfs destroy -r -f $dest
101
102#
103# 3.3 Verify -o property=value and -x work
104#     for an incremental replication send stream.
105#
106# Create a dataset tree and receive it
107log_must zfs create $orig
108log_must zfs create $origsub
109log_must zfs snapshot -r $orig@snap1
110log_must eval "zfs send -R $orig@snap1 > $streamfile_repl"
111log_must eval "zfs recv $dest < $streamfile_repl"
112# Fill the datasets with properties and create an incremental replication stream
113log_must zfs snapshot -r $orig@snap2
114log_must zfs snapshot -r $orig@snap3
115log_must eval "zfs set copies=2 $orig"
116log_must eval "zfs set dnsize=4k $orig"
117log_must eval "zfs set compression=gzip $origsub"
118log_must eval "zfs send -R -I $orig@snap1 $orig@snap3 > $streamfile_incr"
119# Sets various combination of override and exclude options
120log_must eval "zfs recv -F -o atime=off -o quota=123456789 -o checksum=sha512" \
121	" -o dnsize=2k -x compress $dest < $streamfile_incr"
122# Verify we can correctly override and exclude properties
123log_must eval "check_prop_source $dest copies 2 received"
124log_must eval "check_prop_source $dest atime off local"
125log_must eval "check_prop_source $dest quota 123456789 local"
126log_must eval "check_prop_source $dest checksum sha512 local"
127log_must eval "check_prop_source $dest dnodesize 2k local"
128log_must eval "check_prop_inherit $destsub copies $dest"
129log_must eval "check_prop_inherit $destsub atime $dest"
130log_must eval "check_prop_inherit $destsub checksum $dest"
131log_must eval "check_prop_source $destsub quota 0 default"
132log_must eval "check_prop_source $destsub compression on default"
133# Cleanup
134log_must zfs destroy -r -f $orig
135log_must zfs destroy -r -f $dest
136
137#
138# 3.4 Verify '-x property' does not remove existing local properties and a
139#     modified sent property is received and updated to the new value but can
140#     still be excluded.
141#
142# Create a dataset tree
143log_must zfs create $orig
144log_must zfs create $origsub
145log_must zfs snapshot -r $orig@snap1
146log_must eval "zfs set copies=2 $orig"
147log_must eval "zfs send -R $orig@snap1 > $streamfile_repl"
148log_must eval "zfs receive $dest < $streamfile_repl"
149log_must eval "check_prop_source $dest copies 2 received"
150log_must eval "check_prop_inherit $destsub copies $dest"
151# Set new custom properties on both source and destination
152log_must eval "zfs set copies=3 $orig"
153log_must eval "zfs set compression=on $orig"
154log_must eval "zfs set compression=lzjb $origsub"
155log_must eval "zfs set compression=gzip $dest"
156# Receive the new stream, verify we preserve locally set properties
157log_must zfs snapshot -r $orig@snap2
158log_must zfs snapshot -r $orig@snap3
159log_must eval "zfs send -R -I $orig@snap1 $orig@snap3 > $streamfile_incr"
160log_must eval "zfs recv -F -x copies -x compress $dest < $streamfile_incr"
161log_must eval "check_prop_source $dest copies 1 default"
162log_must eval "check_prop_received $dest copies 3"
163log_must eval "check_prop_source $destsub copies 1 default"
164log_must eval "check_prop_received $destsub copies '-'"
165log_must eval "check_prop_source $dest compression gzip local"
166log_must eval "check_prop_inherit $destsub compression $dest"
167# Cleanup
168log_must zfs destroy -r -f $orig
169log_must zfs destroy -r -f $dest
170
171#
172# 3.6 Verify we correctly restore existing properties on a failed receive
173#
174# Receive a "clean" dataset tree
175log_must zfs create $orig
176log_must zfs create $origsub
177log_must zfs snapshot -r $orig@snap1
178log_must eval "zfs send -R $orig@snap1 > $streamfile_repl"
179log_must eval "zfs receive $dest < $streamfile_repl"
180# Set custom properties on the destination
181log_must eval "zfs set compress=on $dest"
182log_must eval "zfs set compress=lzjb $destsub"
183# Create a truncated incremental replication stream
184mntpnt=$(get_prop mountpoint $orig)
185log_must eval "dd if=/dev/urandom of=$mntpnt/file bs=1024k count=10"
186log_must zfs snapshot -r $orig@snap2
187log_must zfs snapshot -r $orig@snap3
188log_must eval "zfs send -R -I $orig@snap1 $orig@snap3 > $streamfile_incr"
189log_must eval "dd if=$streamfile_incr of=$streamfile_trun bs=1024k count=9"
190# Receive the truncated stream, verify original properties are kept
191log_mustnot eval "zfs recv -F -o copies=3 -o compress=gzip "\
192	"$dest < $streamfile_trun"
193log_must eval "check_prop_source $dest copies 1 default"
194log_must eval "check_prop_source $destsub copies 1 default"
195log_must eval "check_prop_source $dest compression on local"
196log_must eval "check_prop_source $destsub compression lzjb local"
197# Cleanup
198log_must zfs destroy -r -f $orig
199log_must zfs destroy -r -f $dest
200
201#
202# 3.7 Verify that we can't get around checking a property is readonly
203#     by using the alias or receiving a parent replication stream.
204log_must zfs create $orig
205log_must zfs create -V 128K -s $origsub
206log_must zfs snapshot -r $orig@snap1
207log_must eval "zfs send -R $orig@snap1 > $streamfile_repl"
208log_mustnot eval "zfs receive -o volblock=64k $dest < $streamfile_repl"
209# Cleanup
210block_device_wait
211log_must_busy zfs destroy -r -f $orig
212
213log_pass "ZFS receive property alias override and exclude options passed."
214