# # CDDL HEADER START # # The contents of this file are subject to the terms of the # Common Development and Distribution License (the "License"). # You may not use this file except in compliance with the License. # # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE # or http://www.opensolaris.org/os/licensing. # See the License for the specific language governing permissions # and limitations under the License. # # When distributing Covered Code, include this CDDL HEADER in each # file and include the License file at usr/src/OPENSOLARIS.LICENSE. # If applicable, add the following below this CDDL HEADER, with the # fields enclosed by brackets "[]" replaced with your own identifying # information: Portions Copyright [yyyy] [name of copyright owner] # # CDDL HEADER END # # # Copyright 2008 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # # # Copyright (c) 2012, 2016 by Delphix. All rights reserved. # . $STF_SUITE/include/libtest.shlib . $STF_SUITE/tests/functional/cli_root/zfs_rollback/zfs_rollback.cfg # Get file sum # # $1 full file name function getsum #fname { (( ${#1} == 0 )) && \ log_fail "Need give file name." return $(sum $1 | awk '{print $1}') } # Define global variable checksum, get the original file sum. # origsum=$(getsum /etc/passwd) # # Setup or recover the test environment. Firstly, copy /etc/passwd to ZFS file # system or volume, then make a snapshot or clone. Repeat up to three times. # # $1 number of snapshot. Note: Currently only support three snapshots. # $2 indicate if it is necessary to create clone # function setup_snap_env { typeset -i cnt=${1:-3} typeset createclone=${2:-"false"} if datasetnonexists $FS; then log_must zfs create $FS log_must zfs set mountpoint=$TESTDIR $FS fi # Volume can't be created in Local Zone. if datasetnonexists $VOL && is_global_zone; then log_must zfs create -V $VOLSIZE $VOL block_device_wait fi # Make sure $VOL is volume typeset type=$(get_prop type $VOL) if datasetexists $VOL && \ [[ $type == 'volume' ]]; then # # At the first time, Make a UFS file system in volume and # mount it. Otherwise, only check if this ufs|ext file system # was mounted. # log_must new_fs $ZVOL_DEVDIR/$VOL [[ ! -d $TESTDIR1 ]] && log_must mkdir $TESTDIR1 # Make sure the ufs|ext filesystem hasn't been mounted, # then mount the new ufs|ext filesystem. if ! ismounted $TESTDIR1 $NEWFS_DEFAULT_FS; then log_must mount $ZVOL_DEVDIR/$VOL $TESTDIR1 fi fi # Separately Create three snapshots for file system & volume typeset -i ind=0 typeset dtst for dtst in $FS $VOL; do # Volume can be created in Local Zone. if [[ $dtst == $VOL ]]; then if ! is_global_zone; then break fi fi ind=0 while (( ind < cnt )); do case $dtst in $FS) eval typeset snap=\$FSSNAP$ind eval typeset clone=\$FSCLONE$ind eval typeset fname=\$TESTDIR/\$TESTFILE$ind ;; $VOL) eval typeset snap=\$VOLSNAP$ind eval typeset clone=\$VOLCLONE$ind eval typeset fname=\$TESTDIR1/\$TESTFILE$ind ;; esac if datasetnonexists $snap; then log_must cp /etc/passwd $fname if is_linux || is_freebsd; then log_must sync else # # using 'lockfs -f' to flush the writes # to disk before taking a snapshot. # if [[ $dtst == $VOL ]]; then log_must lockfs -f $TESTDIR1 fi fi if is_freebsd && [[ $dtst == $VOL ]]; then # Though sync does start a fs sync on # FreeBSD, it does not wait for it to # finish. We can force a blocking sync # by updating the fs mount instead. # Otherwise, the snapshot might occur # with the fs in an unmountable state. log_must mount -ur \ $ZVOL_DEVDIR/$VOL $TESTDIR1 fi log_must zfs snapshot $snap if is_freebsd && [[ $dtst == $VOL ]]; then log_must mount -uw \ $ZVOL_DEVDIR/$VOL $TESTDIR1 fi fi if [[ $createclone == "true" ]]; then if datasetnonexists $clone; then log_must zfs clone $snap $clone block_device_wait fi fi (( ind += 1 )) done done } function setup_clone_env { setup_snap_env $1 "true" } # # Clean up the test environment # # $1 number of snapshot Note: Currently only support three snapshots. # function cleanup_env { typeset -i cnt=${1:-3} typeset -i ind=0 typeset dtst typeset snap pkill -x dd if ismounted $TESTDIR1 $NEWFS_DEFAULT_FS; then log_must umount -f $TESTDIR1 fi [[ -d $TESTDIR ]] && log_must rm -rf $TESTDIR/* [[ -d $TESTDIR1 ]] && log_must rm -rf $TESTDIR1/* for dtst in $FS $VOL; do for snap in $TESTSNAP $TESTSNAP1 $TESTSNAP2; do if snapexists $dtst@$snap; then log_must zfs destroy -Rf $dtst@$snap fi done done # Restore original test environment if datasetnonexists $FS ; then log_must zfs create $FS fi if datasetnonexists $VOL ; then if is_global_zone ; then log_must zfs create -V $VOLSIZE $VOL else log_must zfs create $VOL fi fi } # # check if the specified files have specified status. # # $1 expected status # $2-n full file name # If it is true return 0, else return 1 # function file_status { (( $# == 0 )) && \ log_fail "The file name is not defined." typeset opt case $1 in exist) opt="-e" ;; nonexist) opt="! -e" ;; *) log_fail "Unsupported file status." ;; esac shift while (( $# > 0 )); do eval [[ $opt $1 ]] || return 1 shift done return 0 } function files_exist { file_status "exist" $@ } function files_nonexist { file_status "nonexist" $@ } # # According to snapshot check if the file system was recovered to the right # point. # # $1 snapshot. fs@snap or vol@snap # function check_files { typeset dtst=$1 if [[ $(get_prop type $dtst) != snapshot ]]; then log_fail "Parameter must be a snapshot." fi typeset fsvol=${dtst%%@*} typeset snap=${dtst##*@} if [[ $(get_prop type $fsvol) == "filesystem" ]]; then ind="" else ind="1" fi eval typeset file0=\$TESTDIR$ind/\$TESTFILE0 eval typeset file1=\$TESTDIR$ind/\$TESTFILE1 eval typeset file2=\$TESTDIR$ind/\$TESTFILE2 case $snap in $TESTSNAP2) log_must files_exist $file0 $file1 $file2 typeset sum0=$(getsum $file0) typeset sum1=$(getsum $file1) typeset sum2=$(getsum $file2) if [[ $sum0 != $origsum || \ $sum1 != $origsum || sum2 != $origsum ]] then log_fail "After rollback, file sum is changed." fi ;; $TESTSNAP1) log_must files_exist $file0 $file1 log_must files_nonexist $file2 typeset sum0=$(getsum $file0) typeset sum1=$(getsum $file1) if [[ $sum0 != $origsum || $sum1 != $origsum ]] then log_fail "After rollback, file sum is changed." fi ;; $TESTSNAP) log_must files_exist $file0 log_must files_nonexist $file1 $file2 typeset sum0=$(getsum $file0) if [[ $sum0 != $origsum ]]; then log_fail "After rollback, file sum is changed." fi ;; esac } # According to dataset type, write file to different directories. # # $1 dataset # function write_mountpoint_dir { typeset dtst=$1 typeset dir if [[ $dtst == $FS ]]; then dir=$TESTDIR log_must ismounted $dir else dir=$TESTDIR1 log_must ismounted $dir $NEWFS_DEFAULT_FS fi dd if=/dev/urandom of=$dir/$TESTFILE1 & log_must sleep 3 }