mirror of
https://github.com/linux-apfs/apfstests.git
synced 2026-05-01 15:01:44 -07:00
69eb6281a9
Previously _scratch_mount didn't check the mount status and most tests continue to run even if the mount failed (unless test checks for the mount status explicitly). This would result in running tests on the underlying filesystem (usually rootfs) and implicit test failures, and such failures can be annoying and are usually hard to debug. Now _fail test by default if _scratch_mount failed and introduce _try_scratch_mount for tests that need to check mount results themselves. Suggested-by: Andreas Gruenbacher <agruenba@redhat.com> Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> Reviewed-by: Andreas Gruenbacher <agruenba@redhat.com> Signed-off-by: Eryu Guan <eguan@redhat.com>
249 lines
6.5 KiB
Bash
Executable File
249 lines
6.5 KiB
Bash
Executable File
#! /bin/bash
|
|
# FS QA Test No. 016
|
|
#
|
|
# test end of log overwrite bug #796141
|
|
#
|
|
#-----------------------------------------------------------------------
|
|
# Copyright (c) 2000-2003 Silicon Graphics, Inc. All Rights Reserved.
|
|
#
|
|
# This program is free software; you can redistribute it and/or
|
|
# modify it under the terms of the GNU General Public License as
|
|
# published by the Free Software Foundation.
|
|
#
|
|
# This program is distributed in the hope that it would be useful,
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
# GNU General Public License for more details.
|
|
#
|
|
# You should have received a copy of the GNU General Public License
|
|
# along with this program; if not, write the Free Software Foundation,
|
|
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
#
|
|
#-----------------------------------------------------------------------
|
|
#
|
|
|
|
#
|
|
# pv 796141
|
|
#
|
|
# create a new FS, mostly fill the log. Then wrap the log back to the
|
|
# start bit by bit to force wiping of stale blocks near the end of the
|
|
# log. Check the block after the log ends to check for corruption
|
|
#
|
|
# assumptions :
|
|
# - given we're only touching a single inode, the block after the
|
|
# log which is in the middle ag should never be touched.
|
|
# if it changes, we assume the log is writing over it
|
|
#
|
|
|
|
seq=`basename $0`
|
|
seqres=$RESULT_DIR/$seq
|
|
echo "QA output created by $seq"
|
|
|
|
here=`pwd`
|
|
tmp=/tmp/$$
|
|
status=1
|
|
|
|
trap "_cleanup; exit \$status" 0 1 2 3 15
|
|
|
|
_cleanup()
|
|
{
|
|
cd /
|
|
rm -f $tmp.*
|
|
echo "*** unmount"
|
|
_scratch_unmount 2>/dev/null
|
|
}
|
|
|
|
_block_filter()
|
|
{
|
|
sed -e 's/[0-9][0-9]*\.\.[0-9][0-9]*/BLOCKRANGE/g'
|
|
}
|
|
|
|
_init()
|
|
{
|
|
echo "*** reset partition"
|
|
$here/src/devzero -b 2048 -n 50 -v 198 $SCRATCH_DEV
|
|
echo "*** mkfs"
|
|
force_opts="-dsize=50m -lsize=$log_size"
|
|
#
|
|
# Do not discard blocks as we check for patterns in free space.
|
|
#
|
|
# First, make sure that mkfs supports '-K' option by using its
|
|
# dry run (-N option) and then add it to the force_opts.
|
|
#
|
|
if _scratch_mkfs_xfs -N -K $force_opts >/dev/null 2>&1; then
|
|
force_opts="-K $force_opts"
|
|
fi
|
|
echo mkfs_xfs $force_opts $SCRATCH_DEV >>$seqres.full
|
|
_scratch_mkfs_xfs $force_opts >$tmp.mkfs0 2>&1
|
|
[ $? -ne 0 ] && \
|
|
_notrun "Cannot mkfs for this test using MKFS_OPTIONS specified"
|
|
_filter_mkfs <$tmp.mkfs0 >/dev/null 2>$tmp.mkfs
|
|
. $tmp.mkfs
|
|
[ $logsunit -ne 0 ] && \
|
|
_notrun "Cannot run this test using log MKFS_OPTIONS specified"
|
|
}
|
|
|
|
_log_traffic()
|
|
{
|
|
count=$1
|
|
echo "*** generate log traffic"
|
|
|
|
out=$SCRATCH_MNT/$$.tmp
|
|
|
|
echo " *** mount"
|
|
if ! _try_scratch_mount
|
|
then
|
|
echo "failed to mount $SCRATCH_DEV"
|
|
exit 1
|
|
fi
|
|
|
|
# having any quota enabled (acct/enfd) means extra log traffic - evil!
|
|
$here/src/feature -U $SCRATCH_DEV && \
|
|
_notrun "UQuota are enabled, test needs controlled log traffic"
|
|
$here/src/feature -G $SCRATCH_DEV && \
|
|
_notrun "GQuota are enabled, test needs controlled log traffic"
|
|
$here/src/feature -P $SCRATCH_DEV && \
|
|
_notrun "PQuota are enabled, test needs controlled log traffic"
|
|
|
|
echo " *** fiddle"
|
|
while [ $count -ge 0 ]
|
|
do
|
|
touch $out
|
|
sync
|
|
rm $out
|
|
sync
|
|
let "count = count - 1"
|
|
done
|
|
|
|
echo " *** unmount"
|
|
if ! _scratch_unmount
|
|
then
|
|
echo "failed to unmount $SCRATCH_DEV"
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
_log_size()
|
|
{
|
|
_scratch_xfs_logprint -tb | $AWK_PROG '
|
|
/log file: / || /log device: / { print $7}
|
|
'
|
|
}
|
|
|
|
_log_head()
|
|
{
|
|
_scratch_xfs_logprint -tb | $AWK_PROG '
|
|
/head:/ { print $5 }
|
|
'
|
|
}
|
|
|
|
# Get log stripe unit for v2 logs; if none specified,
|
|
# (or v1 log) just return "1" block
|
|
|
|
_log_sunit()
|
|
{
|
|
if [ ${lsunit:-0} -eq 0 ]; then
|
|
echo $dbsize
|
|
else
|
|
expr $lsunit \* $dbsize
|
|
fi
|
|
}
|
|
|
|
_after_log()
|
|
{
|
|
xfs_db -r $1 -c "sb" -c "print" | $AWK_PROG '
|
|
/logstart/ { logstart = $3 }
|
|
/logblocks/ { logblocks = $3 }
|
|
END {
|
|
print logstart + logblocks
|
|
}
|
|
'
|
|
}
|
|
|
|
_check_corrupt()
|
|
{
|
|
f="c6c6c6c6"
|
|
echo "*** check for corruption"
|
|
echo "expect $f..." >>$seqres.full
|
|
xfs_db -r -c "fsblock $2" -c "print" $1 | head | tee -a $seqres.full | \
|
|
grep -q -v "$f $f $f $f $f $f $f $f" && \
|
|
_fail "!!! block $2 corrupted!"
|
|
}
|
|
|
|
# get standard environment, filters and checks
|
|
. ./common/rc
|
|
. ./common/filter
|
|
|
|
# real QA test starts here
|
|
_supported_fs xfs
|
|
_supported_os Linux
|
|
|
|
rm -f $seqres.full
|
|
|
|
# mkfs sizes
|
|
log_size=3493888
|
|
log_size_bb=`expr $log_size / 512`
|
|
|
|
_require_scratch
|
|
_init
|
|
|
|
block=`_after_log $SCRATCH_DEV`
|
|
echo "fsblock after log = $block" >>$seqres.full
|
|
_check_corrupt $SCRATCH_DEV $block
|
|
|
|
actual_log_size=`_log_size`
|
|
echo "log size = $actual_log_size BB" >>$seqres.full
|
|
head=`_log_head`
|
|
echo "log position = $head" >>$seqres.full
|
|
lsunit=`_log_sunit`
|
|
echo "log sunit = $lsunit" >>$seqres.full
|
|
|
|
# sanity checks
|
|
[ $actual_log_size -eq $log_size_bb ] || \
|
|
_fail "!!! unexpected log size $size"
|
|
[ $head -eq 2 -o $head -eq $((lsunit/512)) ] || \
|
|
_fail "!!! unexpected initial log position $head vs. $((lsunit/512))"
|
|
|
|
# find how how many blocks per op for 100 ops
|
|
# ignore the fact that it will also include an unmount record etc...
|
|
# this should be small overall
|
|
echo " lots of traffic for sampling" >>$seqres.full
|
|
sample_size_ops=100
|
|
_log_traffic $sample_size_ops
|
|
head1=`_log_head`
|
|
num_blocks=`expr $head1 - $head`
|
|
blocks_per_op=`echo "scale=3; $num_blocks / $sample_size_ops" | bc`
|
|
echo "blocks_per_op = $blocks_per_op" >>$seqres.full
|
|
num_expected_ops=`echo "$log_size_bb / $blocks_per_op" | bc`
|
|
echo "num_expected_ops = $num_expected_ops" >>$seqres.full
|
|
num_expected_to_go=`echo "$num_expected_ops - $sample_size_ops" | bc`
|
|
echo "num_expected_to_go = $num_expected_to_go" >>$seqres.full
|
|
|
|
echo " lots more traffic" >>$seqres.full
|
|
_log_traffic $num_expected_to_go
|
|
head=`_log_head`
|
|
echo "log position = $head" >>$seqres.full
|
|
|
|
# e.g. 3891
|
|
near_end_min=`echo "0.95 * $log_size_bb" | bc | sed 's/\..*//'`
|
|
echo "near_end_min = $near_end_min" >>$seqres.full
|
|
|
|
[ $head -gt $near_end_min -a $head -lt $log_size_bb ] || \
|
|
_fail "!!! unexpected near end log position $head"
|
|
|
|
for c in `seq 0 20`
|
|
do
|
|
echo " little traffic" >>$seqres.full
|
|
_log_traffic 2
|
|
head=`_log_head`
|
|
echo "log position = $head" >>$seqres.full
|
|
_check_corrupt $SCRATCH_DEV $block
|
|
done
|
|
|
|
[ $head -lt 1000 ] || \
|
|
_fail "!!! unexpected wrapped log position $head"
|
|
|
|
# success, all done
|
|
status=0
|
|
exit
|