1 #!/bin/ksh
   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 (c) 2012 by Delphix. All rights reserved.
  19 #
  20 
  21 . $STF_SUITE/include/libtest.shlib
  22 #
  23 # DESCRIPTION:
  24 #       Verify 'zfs send' can generate valid streams with different options
  25 #
  26 # STRATEGY:
  27 #       1. Create datasets
  28 #       2. Write some data to the datasets
  29 #       3. Create a full send streams
  30 #       4. Receive the send stream
  31 #       5. Do a dry run with different options and verify the generated size
  32 #          estimate against the received stream
  33 #
  34 
  35 verify_runnable "both"
  36 
  37 function cleanup
  38 {
  39         for ds in $datasets; do
  40                 datasetexists $ds && $ZFS destroy -rf $ds
  41         done
  42 }
  43 
  44 function cal_percentage
  45 {
  46         typeset value=$1
  47         return=$($ECHO "$PERCENT * $value" | bc)
  48         return=$($ECHO "$return / 100" | bc)
  49         echo $return
  50 }
  51 
  52 function get_estimate_size
  53 {
  54         typeset snapshot=$1
  55         typeset option=$2
  56         typeset base_snapshot=${3:-""}
  57         if [[ -z $3 ]];then
  58                 typeset total_size=$($ZFS send $option $snapshot 2>&1 | $TAIL -1)
  59         else
  60                 typeset total_size=$($ZFS send $option $base_snapshot $snapshot \
  61                      2>&1 | $TAIL -1)
  62         fi
  63         if [[ $options == *"P"* ]]; then
  64                 total_size=$($ECHO "$total_size" | $AWK '{print $2}')
  65         else
  66                 total_size=$($ECHO "$total_size" | $AWK '{print $5}')
  67                 total_size=${total_size%M}
  68                 total_size=$($ECHO "$total_size * $block_count" | bc)
  69         fi
  70         $ECHO $total_size
  71 
  72 }
  73 
  74 function verify_size_estimates
  75 {
  76         typeset options=$1
  77         typeset file_size=$2
  78         typeset refer_diff=$($ECHO "$refer_size - $estimate_size" | bc)
  79         refer_diff=$($ECHO "$refer_diff / 1" | bc)
  80         refer_diff=$($ECHO "$refer_diff" | $AWK '{print ($1 < 0) ? ($1 * -1): $1'})
  81         typeset file_diff=$($ECHO "$file_size - $estimate_size" | bc)
  82         file_diff=$($ECHO "$file_diff / 1" | bc)
  83         file_diff=$($ECHO "$file_diff" | $AWK '{print ($1 < 0) ? ($1 * -1):$1'})
  84         typeset expected_diff=$(cal_percentage $refer_size)
  85 
  86         [[ -z $refer_diff && -z $file_diff && -z $expected_diff ]] && \
  87             log_fail "zfs send $options failed"
  88         [[ $refer_diff -le $expected_diff &&  \
  89             $file_diff -le $expected_diff ]] || \
  90             log_fail "zfs send $options gives wrong size estimates"
  91 }
  92 
  93 log_assert "Verify 'zfs send -nvP' generates valid stream estimates"
  94 log_onexit cleanup
  95 typeset -l block_count=0
  96 typeset -l block_size
  97 typeset -i PERCENT=1
  98 
  99 ((block_count=1024*1024))
 100 
 101 # create dataset
 102 log_must $ZFS create $TESTPOOL/$TESTFS1
 103 
 104 # create multiple snapshot for the dataset with data
 105 for block_size in 64 128 256; do
 106         log_must $DD if=/dev/urandom of=/$TESTPOOL/$TESTFS1/file$block_size \
 107             bs=1M count=$block_size
 108         log_must $ZFS snapshot $TESTPOOL/$TESTFS1@snap$block_size
 109 done
 110 
 111 full_snapshot="$TESTPOOL/$TESTFS1@snap64"
 112 increamental_snapshot="$TESTPOOL/$TESTFS1@snap256"
 113 
 114 full_size=$($ZFS send $full_snapshot 2>&1 | wc -c)
 115 increamental_size=$($ZFS send $increamental_snapshot 2>&1 | wc -c)
 116 increamental_send=$($ZFS send -i $full_snapshot $increamental_snapshot 2>&1 | wc -c)
 117 
 118 log_note "verify zfs send -nv"
 119 options="-nv"
 120 refer_size=$(get_prop refer $full_snapshot)
 121 estimate_size=$(get_estimate_size $full_snapshot $options)
 122 log_must verify_size_estimates $options $full_size
 123 
 124 log_note "verify zfs send -Pnv"
 125 options="-Pnv"
 126 
 127 estimate_size=$(get_estimate_size $full_snapshot $options)
 128 log_must verify_size_estimates $options $full_size
 129 
 130 log_note "verify zfs send -nv for multiple snapshot send"
 131 options="-nv"
 132 refer_size=$(get_prop refer $increamental_snapshot)
 133 
 134 estimate_size=$(get_estimate_size $increamental_snapshot $options)
 135 log_must verify_size_estimates $options $increamental_size
 136 
 137 log_note "verify zfs send -vPn for multiple snapshot send"
 138 options="-vPn"
 139 
 140 estimate_size=$(get_estimate_size $increamental_snapshot $options)
 141 log_must verify_size_estimates $options $increamental_size
 142 
 143 log_note "verify zfs send -inv for increamental send"
 144 options="-nvi"
 145 refer_size=$(get_prop refer $increamental_snapshot)
 146 deduct_size=$(get_prop refer $full_snapshot)
 147 refer_size=$($ECHO "$refer_size - $deduct_size" | bc)
 148 
 149 estimate_size=$(get_estimate_size $increamental_snapshot $options $full_snapshot)
 150 log_must verify_size_estimates $options $increamental_send
 151 
 152 log_note "verify zfs send -ivPn for increamental send"
 153 options="-vPni"
 154 
 155 estimate_size=$(get_estimate_size $increamental_snapshot $options $full_snapshot)
 156 log_must verify_size_estimates $options $increamental_send
 157 
 158 log_must $ZFS destroy -r $TESTPOOL/$TESTFS1
 159 
 160 #setup_recursive_send
 161 datasets="$TESTPOOL/$TESTFS1 $TESTPOOL/$TESTFS1/$TESTFS2
 162     $TESTPOOL/$TESTFS1/$TESTFS2/$TESTFS3"
 163 # create nested datasets
 164 log_must $ZFS create -p $TESTPOOL/$TESTFS1/$TESTFS2/$TESTFS3
 165 
 166 # verify dataset creation
 167 for ds in $datasets; do
 168         datasetexists $ds || log_fail "Create $ds dataset fail."
 169 done
 170 for ds in $datasets; do
 171         log_must $DD if=/dev/urandom of=/$ds/file64 \
 172             bs=1M count=64
 173 done
 174 
 175 # create recursive nested snapshot
 176 log_must $ZFS snapshot -r $TESTPOOL/$TESTFS1@snap64
 177 for ds in $datasets; do
 178         datasetexists $ds@snap64 || log_fail "Create $ds@snap64 snapshot fail."
 179 done
 180 recursive_size=$($ZFS send -R $full_snapshot 2>&1 | wc -c)
 181 log_note "verify zfs send -Rnv for recursive send"
 182 options="-Rnv"
 183 refer_size=$(get_prop refer $full_snapshot)
 184 refer_size=$($ECHO "$refer_size * 3" | bc)
 185 
 186 estimate_size=$(get_estimate_size $full_snapshot $options)
 187 log_must verify_size_estimates $options $recursive_size
 188 
 189 log_note "verify zfs send -RvPn for recursive send"
 190 options="-RvPn"
 191 estimate_size=$(get_estimate_size $full_snapshot $options)
 192 log_must verify_size_estimates $options $recursive_size
 193 
 194 log_pass "'zfs send' prints the correct size estimates using '-n' and '-P' options."