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