1#!/bin/ksh 2# 3# This file and its contents are supplied under the terms of the 4# Common Development and Distribution License ("CDDL"), version 1.0. 5# You may only use this file in accordance with the terms of version 6# 1.0 of the CDDL. 7# 8# A full copy of the text of the CDDL should have accompanied this 9# source. A copy of the CDDL is also available via the Internet at 10# http://www.illumos.org/license/CDDL. 11# 12 13# 14# Copyright (c) 2012, 2017 by Delphix. All rights reserved. 15# 16 17# 18# DESCRIPTION 19# Verify that "zfs list" gives correct values for written and written@ 20# properties for the dataset when different operations are on done on it 21# 22# 23# STRATEGY 24# 1) Create recursive datasets 25# 2) Take snapshots, write data and verify written/ written@ properties for 26# following cases 27# a) Delete data 28# b) Write Data 29# c) Clone 30# d) Delete snapshot 31# e) Recursive datasets 32 33. $STF_SUITE/include/libtest.shlib 34. $STF_SUITE/include/math.shlib 35 36function cleanup 37{ 38 for ds in $datasets; do 39 datasetexists $ds && destroy_dataset $TESTPOOL/$TESTFS1 -R 40 done 41} 42function get_prop_mb 43{ 44 typeset prop=$1 45 typeset dataset=$2 46 typeset -l value=$(get_prop $prop $dataset) 47 ((value = value / mb_block)) 48 echo $value 49} 50 51datasets="$TESTPOOL/$TESTFS1 $TESTPOOL/$TESTFS1/$TESTFS2 \ 52 $TESTPOOL/$TESTFS1/$TESTFS2/$TESTFS3" 53 54log_assert "verify zfs written and written@ property" 55log_onexit cleanup 56 57typeset -l i=1 58typeset -l blocks=50 59typeset -l expected_written=0 60typeset -l expected_writtenat=0 61typeset -l written=0 62typeset -l total=0 63typeset -l snap1_size=0 64typeset -l snap2_size=0 65typeset -l snap3_size=0 66typeset -l mb_block=0 67((mb_block = 1024 * 1024)) 68 69log_note "verify written property statistics for dataset" 70log_must zfs create -p $TESTPOOL/$TESTFS1/$TESTFS2/$TESTFS3 71for i in 1 2 3; do 72 log_must zfs snapshot $TESTPOOL/$TESTFS1@snap$i 73 log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS1/testfile.$i bs=1M \ 74 count=$blocks 75 sync_pool 76 written=$(get_prop written $TESTPOOL/$TESTFS1) 77 ((expected_written=blocks * mb_block)) 78 within_percent $written $expected_written 99.5 || \ 79 log_fail "Unexpected written value $written $expected_written" 80 ((total = total + blocks)) 81 ((blocks = blocks + 50)) 82done 83 84log_note "verify written property statistics for snapshots" 85blocks=0 86for i in 1 2 3; do 87 written=$(get_prop written $TESTPOOL/$TESTFS1@snap$i) 88 if [[ $blocks -eq 0 ]]; then 89 # Written value for the first non-clone snapshot is 90 # expected to be equal to the referenced value. 91 expected_written=$( \ 92 get_prop referenced $TESTPOOL/$TESTFS1@snap$i) 93 else 94 ((expected_written = blocks * mb_block)) 95 fi 96 within_percent $written $expected_written 99.5 || \ 97 log_fail "Unexpected written value $written $expected_written $i" 98 ((blocks = blocks + 50)) 99done 100 101snap1_size=$total 102((snap2_size = total-50)) 103((snap3_size = total-100)) 104 105log_note "verify written@ for the same dataset" 106blocks=50 107for i in 1 2 3; do 108 writtenat=$(get_prop written@snap$i $TESTPOOL/$TESTFS1) 109 ((expected_writtenat = total * mb_block)) 110 within_percent $writtenat $expected_writtenat 99.5 || \ 111 log_fail "Unexpected written@ value" 112 ((total = total - blocks)) 113 ((blocks = blocks + 50)) 114done 115log_note "delete data" 116before_written=$(get_prop written $TESTPOOL/$TESTFS1) 117log_must rm /$TESTPOOL/$TESTFS1/testfile.3 118snap3_size=0 119sync_pool 120written=$(get_prop written $TESTPOOL/$TESTFS1) 121writtenat3=$(get_prop written@snap3 $TESTPOOL/$TESTFS1) 122[[ $written -eq $writtenat3 ]] || \ 123 log_fail "Written and written@ don't match $written $writtenat3" 124within_percent $written $before_written 0.1 && \ 125 log_fail "Unexpected written value after delete $written $before_written" 126writtenat=$(get_prop written@snap1 $TESTPOOL/$TESTFS1) 127((snap1_size = snap1_size - 150)) 128((expected_writtenat = snap1_size * mb_block)) 129within_percent $writtenat $expected_writtenat 99.5 || \ 130 log_fail "Unexpected written value after delete $writtenat $expected_writtenat" 131writtenat=$(get_prop written@snap2 $TESTPOOL/$TESTFS1) 132((snap2_size = snap2_size - 150)) 133((expected_writtenat = snap2_size * mb_block)) 134within_percent $writtenat $expected_writtenat 99.5 || \ 135 log_fail "Unexpected written value after delete" 136 137log_note "write data" 138blocks=20 139log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS1/testfile.3 bs=1M \ 140 count=$blocks 141sync_pool 142written=$(get_prop written $TESTPOOL/$TESTFS1) 143writtenat1=$(get_prop written@snap1 $TESTPOOL/$TESTFS1) 144writtenat2=$(get_prop written@snap2 $TESTPOOL/$TESTFS1) 145writtenat3=$(get_prop written@snap3 $TESTPOOL/$TESTFS1) 146((snap3_size = snap3_size + blocks)) 147((expected_writtenat = snap3_size * mb_block)) 148[[ $written -eq $writtenat3 ]] || \ 149 log_fail "Unexpected_written value" 150within_percent $writtenat3 $expected_writtenat 99.5 || \ 151 log_fail "Unexpected_written@ value for snap3" 152((snap2_size = snap2_size + blocks)) 153((expected_writtenat = snap2_size * mb_block)) 154within_percent $writtenat2 $expected_writtenat 99.5 || \ 155 log_fail "Unexpected_written@ value for snap2" 156((snap1_size = snap1_size + blocks)) 157((expected_writtenat = snap1_size * mb_block)) 158within_percent $writtenat1 $expected_writtenat 99.5 || \ 159 log_fail "Unexpected_written@ value for snap1" 160 161log_note "write data to a clone" 162before_clone=$(get_prop written $TESTPOOL/$TESTFS1) 163log_must zfs clone $TESTPOOL/$TESTFS1@snap1 $TESTPOOL/$TESTFS1/snap1.clone 164log_must dd if=/dev/urandom of=/$TESTPOOL/$TESTFS1/snap1.clone/testfile bs=1M \ 165 count=40 166sync_pool 167after_clone=$(get_prop written $TESTPOOL/$TESTFS1) 168within_percent $before_clone $after_clone 99.5 || \ 169 log_fail "unexpected written for clone $before_clone $after_clone" 170 171log_note "deleted snapshot" 172typeset -l before_written1=$(get_prop_mb written@snap1 $TESTPOOL/$TESTFS1) 173typeset -l before_written3=$(get_prop_mb written@snap3 $TESTPOOL/$TESTFS1) 174typeset -l snap_before_written2=$(get_prop_mb written $TESTPOOL/$TESTFS1@snap2) 175typeset -l snap_before_written3=$(get_prop_mb written $TESTPOOL/$TESTFS1@snap3) 176log_must zfs destroy $TESTPOOL/$TESTFS1@snap2 177log_mustnot snapexists $TESTPOOL/$TESTFS1@snap2 178sync_pool 179written1=$(get_prop_mb written@snap1 $TESTPOOL/$TESTFS1) 180written3=$(get_prop_mb written@snap3 $TESTPOOL/$TESTFS1) 181[[ $before_written1 -eq $written1 && $before_written3 -eq $written3 ]] || \ 182 log_fail "unexpected written values $before_written1 $written1" 183typeset -l expected_written3 184((expected_written3 = snap_before_written2 + snap_before_written3)) 185prev_written=$(get_prop_mb written $TESTPOOL/$TESTFS1@snap3) 186within_percent $prev_written $expected_written3 99.5 || \ 187 log_fail "unexpected written value $prev_written $expected_written3" 188 189log_must zfs destroy $TESTPOOL/$TESTFS1@snap3 190log_mustnot snapexists $TESTPOOL/$TESTFS1@snap3 191written=$(get_prop written $TESTPOOL/$TESTFS1) 192writtenat1=$(get_prop written@snap1 $TESTPOOL/$TESTFS1) 193[[ $written -ne $writtenat1 ]] && \ 194 log_fail "Unexpected last snapshot written value" 195 196log_note "verify written@ property for recursive datasets" 197blocks=10 198log_must zfs snapshot -r $TESTPOOL/$TESTFS1@now 199for ds in $datasets; do 200 writtenat=$(get_prop written@now $ds) 201 [[ $writtenat -ne 0 ]] && \ 202 log_fail "Unexpected written@ value" 203 log_must dd if=/dev/urandom of=/$ds/testfile bs=1M count=$blocks 204 sync_pool 205 writtenat=$(get_prop written@now $ds) 206 ((expected_writtenat = blocks * mb_block)) 207 within_percent $writtenat $expected_writtenat 0.1 || \ 208 log_fail "Unexpected written value" 209 ((blocks = blocks + 10)) 210done 211 212log_note "verify written@ output for recursive datasets" 213blocks=20 214for ds in $datasets; do 215 log_must zfs snapshot $ds@current 216 log_must dd if=/dev/urandom of=/$ds/testfile bs=1M \ 217 count=$blocks 218 sync_pool 219done 220recursive_output=$(zfs get -p -r written@current $TESTPOOL | \ 221 grep -ve $TESTFS1@ -e $TESTFS2@ -e $TESTFS3@ -e "VALUE" | grep -v "-") 222expected="$((20 * mb_block))" 223for ds in $datasets; do 224 writtenat=$(echo "$recursive_output" | grep -v $ds/) 225 writtenat=$(echo "$writtenat" | awk -v ds="$ds" '$0 ~ ds {print $3}') 226 within_percent $writtenat $expected 99.5 || \ 227 log_fail "Unexpected written@ value on $ds" 228done 229 230log_pass "zfs written and written@ property fields print correct values" 231