blob: 433f240675f3b567a56c4b0555325f83940db79e [file] [log] [blame]
#
# 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
snapexists $dtst@$snap && destroy_dataset $dtst@$snap -Rf
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
}