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 -o checksum=sha512 -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_source $dest checksum sha512 local" 133log_must eval "check_prop_inherit $destsub copies $dest" 134log_must eval "check_prop_inherit $destsub atime $dest" 135log_must eval "check_prop_inherit $destsub checksum $dest" 136log_must eval "check_prop_inherit $destsub '$userprop:dest2' $dest" 137log_must eval "check_prop_source $destsub quota 0 default" 138log_must eval "check_prop_source $destsub compression on default" 139log_must eval "check_prop_missing $dest '$userprop:orig'" 140log_must eval "check_prop_missing $destsub '$userprop:orig'" 141log_must eval "check_prop_source " \ 142 "$dest@snap1 '$userprop:snap' '$userval' received" 143log_must eval "check_prop_source " \ 144 "$destsub@snap3 '$userprop:snap' '$userval' received" 145log_must eval "check_prop_missing $dest@snap3 '$userprop:snap3'" 146log_must eval "check_prop_missing $destsub@snap3 '$userprop:snap3'" 147# Cleanup 148log_must zfs destroy -r -f $orig 149log_must zfs destroy -r -f $dest 150 151# 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 154# still be excluded. 155# 156# Create a dataset tree 157log_must zfs create $orig 158log_must zfs create $origsub 159log_must zfs snapshot -r $orig@snap1 160log_must eval "zfs set copies=2 $orig" 161log_must eval "zfs set '$userprop:orig'='oldval' $orig" 162log_must eval "zfs set '$userprop:orig'='oldsubval' $origsub" 163log_must eval "zfs send -R $orig@snap1 > $streamfile_repl" 164log_must eval "zfs receive $dest < $streamfile_repl" 165log_must eval "check_prop_source $dest copies 2 received" 166log_must eval "check_prop_inherit $destsub copies $dest" 167log_must eval "check_prop_source $dest '$userprop:orig' 'oldval' received" 168log_must eval "check_prop_source $destsub '$userprop:orig' 'oldsubval' received" 169# Set new custom properties on both source and destination 170log_must eval "zfs set copies=3 $orig" 171log_must eval "zfs set '$userprop:orig'='newval' $orig" 172log_must eval "zfs set '$userprop:orig'='newsubval' $origsub" 173log_must eval "zfs set compression=gzip $dest" 174log_must eval "zfs set '$userprop:dest'='localval' $dest" 175# Receive the new stream, verify we preserve locally set properties 176log_must zfs snapshot -r $orig@snap2 177log_must zfs snapshot -r $orig@snap3 178log_must eval "zfs send -R -I $orig@snap1 $orig@snap3 > $streamfile_incr" 179log_must eval "zfs recv -F -x copies -x compression -x '$userprop:orig' " \ 180 "-x '$userprop:dest' $dest < $streamfile_incr" 181log_must eval "check_prop_source $dest '$userprop:dest' 'localval' local" 182log_must eval "check_prop_received $dest '$userprop:orig' 'newval'" 183log_must eval "check_prop_received $destsub '$userprop:orig' 'newsubval'" 184log_must eval "check_prop_missing $dest '$userprop:orig'" 185log_must eval "check_prop_missing $destsub '$userprop:orig'" 186log_must eval "check_prop_source $dest copies 1 default" 187log_must eval "check_prop_received $dest copies 3" 188log_must eval "check_prop_source $destsub copies 1 default" 189log_must eval "check_prop_received $destsub copies '-'" 190log_must eval "check_prop_source $dest compression gzip local" 191log_must eval "check_prop_inherit $destsub compression $dest" 192# Cleanup 193log_must zfs destroy -r -f $orig 194log_must zfs destroy -r -f $dest 195 196# 197# 3.5 Verify we can exclude non-inheritable properties from a send stream 198# 199# Create a dataset tree and replication stream 200log_must zfs create $orig 201log_must zfs create $origsub 202log_must zfs snapshot -r $orig@snap1 203log_must eval "zfs set quota=123456789 $orig" 204log_must eval "zfs send -R $orig@snap1 > $streamfile_repl" 205# Receive the stream excluding non-inheritable properties 206log_must eval "zfs recv -F -x quota $dest < $streamfile_repl" 207log_must eval "check_prop_source $dest quota 0 default" 208log_must eval "check_prop_source $destsub quota 0 default" 209# Set some non-inheritable properties on the destination, verify we keep them 210log_must eval "zfs set quota=123456789 $dest" 211log_must eval "zfs set canmount=off $destsub" 212log_must zfs snapshot -r $orig@snap2 213log_must zfs snapshot -r $orig@snap3 214log_must eval "zfs send -R -I $orig@snap1 $orig@snap3 > $streamfile_incr" 215log_must eval "zfs recv -F -x quota -x canmount $dest < $streamfile_incr" 216log_must eval "check_prop_source $dest quota 123456789 local" 217log_must eval "check_prop_source $destsub quota 0 default" 218log_must eval "check_prop_source $destsub canmount off local" 219# Cleanup 220log_must zfs destroy -r -f $orig 221log_must zfs destroy -r -f $dest 222 223# 224# 3.6 Verify we correctly restore existing properties on a failed receive 225# 226# Receive a "clean" dataset tree 227log_must zfs create $orig 228log_must zfs create $origsub 229log_must zfs snapshot -r $orig@snap1 230log_must eval "zfs send -R $orig@snap1 > $streamfile_repl" 231log_must eval "zfs receive $dest < $streamfile_repl" 232# Set custom properties on the destination 233log_must eval "zfs set atime=off $dest" 234log_must eval "zfs set quota=123456789 $dest" 235log_must eval "zfs set '$userprop:orig'='$userval' $dest" 236log_must eval "zfs set '$userprop:origsub'='$userval' $destsub" 237# Create a truncated incremental replication stream 238mntpnt=$(get_prop mountpoint $orig) 239log_must eval "dd if=/dev/urandom of=$mntpnt/file bs=1024k count=10" 240log_must zfs snapshot -r $orig@snap2 241log_must zfs snapshot -r $orig@snap3 242log_must eval "zfs send -R -I $orig@snap1 $orig@snap3 > $streamfile_incr" 243log_must eval "dd if=$streamfile_incr of=$streamfile_trun bs=1024k count=9" 244# Receive the truncated stream, verify original properties are kept 245log_mustnot eval "zfs recv -F -o copies=3 -o quota=987654321 "\ 246 "-o '$userprop:new'='badval' $dest < $streamfile_trun" 247log_must eval "check_prop_source $dest copies 1 default" 248log_must eval "check_prop_source $destsub copies 1 default" 249log_must eval "check_prop_source $dest atime off local" 250log_must eval "check_prop_inherit $destsub atime $dest" 251log_must eval "check_prop_source $dest quota 123456789 local" 252log_must eval "check_prop_source $destsub quota 0 default" 253log_must eval "check_prop_source $dest '$userprop:orig' '$userval' local" 254log_must eval "check_prop_inherit $destsub '$userprop:orig' $dest" 255log_must eval "check_prop_source $destsub '$userprop:origsub' '$userval' local" 256log_must eval "check_prop_missing $dest '$userprop:new'" 257# Cleanup 258log_must zfs destroy -r -f $orig 259log_must zfs destroy -r -f $dest 260 261# 262# 3.7 Verify we can receive a send stream excluding but not overriding 263# properties invalid for the dataset type, in which case only the 264# appropriate properties are set on the destination. 265log_must zfs create -V 128K -s $orig 266log_must zfs snapshot $orig@snap1 267log_must eval "zfs send $orig@snap1 > $streamfile_full" 268log_mustnot eval "zfs receive -o atime=off $dest < $streamfile_full" 269log_mustnot eval "zfs receive -o atime=off -x canmount $dest < $streamfile_full" 270log_must eval "zfs receive -x atime -x canmount $dest < $streamfile_full" 271log_must eval "check_prop_source $dest type volume -" 272log_must eval "check_prop_source $dest atime - -" 273log_must eval "check_prop_source $dest canmount - -" 274log_must_busy zfs destroy -r -f $orig 275log_must_busy zfs destroy -r -f $dest 276# Recursive sends also accept (and ignore) such overrides 277log_must zfs create $orig 278log_must zfs create -V 128K -s $origsub 279log_must zfs snapshot -r $orig@snap1 280log_must eval "zfs send -R $orig@snap1 > $streamfile_repl" 281log_must eval "zfs receive -o atime=off $dest < $streamfile_repl" 282log_must eval "check_prop_source $dest type filesystem -" 283log_must eval "check_prop_source $dest atime off local" 284log_must eval "check_prop_source $destsub type volume -" 285log_must eval "check_prop_source $destsub atime - -" 286# Cleanup 287block_device_wait 288log_must_busy zfs destroy -r -f $orig 289log_must_busy zfs destroy -r -f $dest 290 291# 292# 3.8 Verify 'zfs recv -x|-o' works correctly when used in conjunction with -d 293# and -e options. 294# 295log_must zfs create -p $orig/1/2/3/4 296log_must eval "zfs set copies=2 $orig" 297log_must eval "zfs set atime=on $orig" 298log_must eval "zfs set '$userprop:orig'='oldval' $orig" 299log_must zfs snapshot -r $orig@snap1 300log_must eval "zfs send -R $orig/1/2@snap1 > $streamfile_repl" 301# Verify 'zfs recv -e' 302log_must zfs create $dest 303log_must eval "zfs receive -e -o copies=3 -x atime "\ 304 "-o '$userprop:orig'='newval' $dest < $streamfile_repl" 305log_must datasetexists $dest/2/3/4 306log_must eval "check_prop_source $dest/2 copies 3 local" 307log_must eval "check_prop_inherit $dest/2/3/4 copies $dest/2" 308log_must eval "check_prop_source $dest/2/3/4 atime on default" 309log_must eval "check_prop_source $dest/2 '$userprop:orig' 'newval' local" 310log_must eval "check_prop_inherit $dest/2/3/4 '$userprop:orig' $dest/2" 311log_must zfs destroy -r -f $dest 312# Verify 'zfs recv -d' 313log_must zfs create $dest 314typeset fs="$(echo $orig | awk -F'/' '{print $NF}')" 315log_must eval "zfs receive -d -o copies=3 -x atime "\ 316 "-o '$userprop:orig'='newval' $dest < $streamfile_repl" 317log_must datasetexists $dest/$fs/1/2/3/4 318log_must eval "check_prop_source $dest/$fs/1/2 copies 3 local" 319log_must eval "check_prop_inherit $dest/$fs/1/2/3/4 copies $dest/$fs/1/2" 320log_must eval "check_prop_source $dest/$fs/1/2/3/4 atime on default" 321log_must eval "check_prop_source $dest/$fs/1/2 '$userprop:orig' 'newval' local" 322log_must eval "check_prop_inherit $dest/$fs/1/2/3/4 '$userprop:orig' $dest/$fs/1/2" 323# We don't need to cleanup here 324 325log_pass "ZFS receive property override and exclude options passed." 326