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