1# 2# CDDL HEADER START 3# 4# The contents of this file are subject to the terms of the 5# Common Development and Distribution License (the "License"). 6# You may not use this file except in compliance with the License. 7# 8# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9# or http://www.opensolaris.org/os/licensing. 10# See the License for the specific language governing permissions 11# and limitations under the License. 12# 13# When distributing Covered Code, include this CDDL HEADER in each 14# file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15# If applicable, add the following below this CDDL HEADER, with the 16# fields enclosed by brackets "[]" replaced with your own identifying 17# information: Portions Copyright [yyyy] [name of copyright owner] 18# 19# CDDL HEADER END 20# 21 22# 23# Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24# Use is subject to license terms. 25# 26 27# 28# Copyright (c) 2012, 2016 by Delphix. All rights reserved. 29# 30 31. $STF_SUITE/include/libtest.shlib 32. $STF_SUITE/tests/functional/cli_root/zfs_rollback/zfs_rollback.cfg 33 34# Get file sum 35# 36# $1 full file name 37function getsum #fname 38{ 39 (( ${#1} == 0 )) && \ 40 log_fail "Need give file name." 41 return $(sum $1 | awk '{print $1}') 42} 43 44# Define global variable checksum, get the original file sum. 45# 46origsum=$(getsum /etc/passwd) 47 48# 49# Setup or recover the test environment. Firstly, copy /etc/passwd to ZFS file 50# system or volume, then make a snapshot or clone. Repeat up to three times. 51# 52# $1 number of snapshot. Note: Currently only support three snapshots. 53# $2 indicate if it is necessary to create clone 54# 55function setup_snap_env 56{ 57 typeset -i cnt=${1:-3} 58 typeset createclone=${2:-"false"} 59 60 if datasetnonexists $FS; then 61 log_must zfs create $FS 62 log_must zfs set mountpoint=$TESTDIR $FS 63 fi 64 # Volume can't be created in Local Zone. 65 if datasetnonexists $VOL && is_global_zone; then 66 log_must zfs create -V $VOLSIZE $VOL 67 block_device_wait 68 fi 69 70 # Make sure $VOL is volume 71 typeset type=$(get_prop type $VOL) 72 if datasetexists $VOL && \ 73 [[ $type == 'volume' ]]; then 74 # 75 # At the first time, Make a UFS file system in volume and 76 # mount it. Otherwise, only check if this ufs|ext file system 77 # was mounted. 78 # 79 log_must new_fs $ZVOL_DEVDIR/$VOL 80 81 [[ ! -d $TESTDIR1 ]] && log_must mkdir $TESTDIR1 82 83 # Make sure the ufs|ext filesystem hasn't been mounted, 84 # then mount the new ufs|ext filesystem. 85 if ! ismounted $TESTDIR1 $NEWFS_DEFAULT_FS; then 86 log_must mount $ZVOL_DEVDIR/$VOL $TESTDIR1 87 fi 88 fi 89 90 # Separately Create three snapshots for file system & volume 91 typeset -i ind=0 92 typeset dtst 93 for dtst in $FS $VOL; do 94 # Volume can be created in Local Zone. 95 if [[ $dtst == $VOL ]]; then 96 if ! is_global_zone; then 97 break 98 fi 99 fi 100 101 ind=0 102 while (( ind < cnt )); do 103 case $dtst in 104 $FS) 105 eval typeset snap=\$FSSNAP$ind 106 eval typeset clone=\$FSCLONE$ind 107 eval typeset fname=\$TESTDIR/\$TESTFILE$ind 108 ;; 109 $VOL) 110 eval typeset snap=\$VOLSNAP$ind 111 eval typeset clone=\$VOLCLONE$ind 112 eval typeset fname=\$TESTDIR1/\$TESTFILE$ind 113 ;; 114 esac 115 116 if datasetnonexists $snap; then 117 log_must cp /etc/passwd $fname 118 if is_linux || is_freebsd; then 119 log_must sync 120 else 121 # 122 # using 'lockfs -f' to flush the writes 123 # to disk before taking a snapshot. 124 # 125 if [[ $dtst == $VOL ]]; then 126 log_must lockfs -f $TESTDIR1 127 fi 128 fi 129 if is_freebsd && [[ $dtst == $VOL ]]; then 130 # Though sync does start a fs sync on 131 # FreeBSD, it does not wait for it to 132 # finish. We can force a blocking sync 133 # by updating the fs mount instead. 134 # Otherwise, the snapshot might occur 135 # with the fs in an unmountable state. 136 log_must mount -ur \ 137 $ZVOL_DEVDIR/$VOL $TESTDIR1 138 fi 139 log_must zfs snapshot $snap 140 if is_freebsd && [[ $dtst == $VOL ]]; then 141 log_must mount -uw \ 142 $ZVOL_DEVDIR/$VOL $TESTDIR1 143 fi 144 fi 145 if [[ $createclone == "true" ]]; then 146 if datasetnonexists $clone; then 147 log_must zfs clone $snap $clone 148 block_device_wait 149 fi 150 fi 151 (( ind += 1 )) 152 done 153 done 154} 155 156function setup_clone_env 157{ 158 setup_snap_env $1 "true" 159} 160 161# 162# Clean up the test environment 163# 164# $1 number of snapshot Note: Currently only support three snapshots. 165# 166function cleanup_env 167{ 168 typeset -i cnt=${1:-3} 169 typeset -i ind=0 170 typeset dtst 171 typeset snap 172 173 pkill -x dd 174 175 if ismounted $TESTDIR1 $NEWFS_DEFAULT_FS; then 176 log_must umount -f $TESTDIR1 177 fi 178 179 [[ -d $TESTDIR ]] && log_must rm -rf $TESTDIR/* 180 [[ -d $TESTDIR1 ]] && log_must rm -rf $TESTDIR1/* 181 182 for dtst in $FS $VOL; do 183 for snap in $TESTSNAP $TESTSNAP1 $TESTSNAP2; do 184 if snapexists $dtst@$snap; then 185 log_must zfs destroy -Rf $dtst@$snap 186 fi 187 done 188 done 189 190 # Restore original test environment 191 if datasetnonexists $FS ; then 192 log_must zfs create $FS 193 fi 194 if datasetnonexists $VOL ; then 195 if is_global_zone ; then 196 log_must zfs create -V $VOLSIZE $VOL 197 else 198 log_must zfs create $VOL 199 fi 200 fi 201} 202 203# 204# check if the specified files have specified status. 205# 206# $1 expected status 207# $2-n full file name 208# If it is true return 0, else return 1 209# 210function file_status 211{ 212 (( $# == 0 )) && \ 213 log_fail "The file name is not defined." 214 215 typeset opt 216 case $1 in 217 exist) opt="-e" ;; 218 nonexist) opt="! -e" ;; 219 *) log_fail "Unsupported file status." ;; 220 esac 221 222 shift 223 while (( $# > 0 )); do 224 eval [[ $opt $1 ]] || return 1 225 shift 226 done 227 228 return 0 229} 230 231function files_exist 232{ 233 file_status "exist" $@ 234} 235 236function files_nonexist 237{ 238 file_status "nonexist" $@ 239} 240 241# 242# According to snapshot check if the file system was recovered to the right 243# point. 244# 245# $1 snapshot. fs@snap or vol@snap 246# 247function check_files 248{ 249 typeset dtst=$1 250 251 if [[ $(get_prop type $dtst) != snapshot ]]; then 252 log_fail "Parameter must be a snapshot." 253 fi 254 255 typeset fsvol=${dtst%%@*} 256 typeset snap=${dtst##*@} 257 if [[ $(get_prop type $fsvol) == "filesystem" ]]; then 258 ind="" 259 else 260 ind="1" 261 fi 262 263 eval typeset file0=\$TESTDIR$ind/\$TESTFILE0 264 eval typeset file1=\$TESTDIR$ind/\$TESTFILE1 265 eval typeset file2=\$TESTDIR$ind/\$TESTFILE2 266 267 case $snap in 268 $TESTSNAP2) 269 log_must files_exist $file0 $file1 $file2 270 271 typeset sum0=$(getsum $file0) 272 typeset sum1=$(getsum $file1) 273 typeset sum2=$(getsum $file2) 274 if [[ $sum0 != $origsum || \ 275 $sum1 != $origsum || sum2 != $origsum ]] 276 then 277 log_fail "After rollback, file sum is changed." 278 fi 279 ;; 280 $TESTSNAP1) 281 log_must files_exist $file0 $file1 282 log_must files_nonexist $file2 283 284 typeset sum0=$(getsum $file0) 285 typeset sum1=$(getsum $file1) 286 if [[ $sum0 != $origsum || $sum1 != $origsum ]] 287 then 288 log_fail "After rollback, file sum is changed." 289 fi 290 ;; 291 $TESTSNAP) 292 log_must files_exist $file0 293 log_must files_nonexist $file1 $file2 294 295 typeset sum0=$(getsum $file0) 296 if [[ $sum0 != $origsum ]]; then 297 log_fail "After rollback, file sum is changed." 298 fi 299 ;; 300 esac 301} 302 303# According to dataset type, write file to different directories. 304# 305# $1 dataset 306# 307function write_mountpoint_dir 308{ 309 typeset dtst=$1 310 typeset dir 311 312 if [[ $dtst == $FS ]]; then 313 dir=$TESTDIR 314 log_must ismounted $dir 315 else 316 dir=$TESTDIR1 317 log_must ismounted $dir $NEWFS_DEFAULT_FS 318 fi 319 dd if=/dev/urandom of=$dir/$TESTFILE1 & 320 log_must sleep 3 321} 322