mirror of
https://github.com/linux-apfs/apfstests.git
synced 2026-05-01 15:01:44 -07:00
2a0cb69ee7
Test 016 fails with delaylog because it measures log traffic to disk and delaylog writes almost nothing to the log for the given test. TO make it work, add sync calls to the work loop to cause the log to be flushed reliably for both delaylog and nodelaylog and hence contain the same number of log records. As a result, the log space consumed by the test is not changed by the delaylog option and the test passes. The test is not significantly slowed down by the addition of the sync calls (takes 15s to run on a single SATA drive). Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Alex Elder <aelder@sgi.com> Reviewed-by: Christoph Hellwig <hch@lst.de>
241 lines
6.1 KiB
Bash
Executable File
241 lines
6.1 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
|
|
#
|
|
#-----------------------------------------------------------------------
|
|
#
|
|
# creator
|
|
owner=dxm@sgi.com
|
|
|
|
#
|
|
# 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`
|
|
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"
|
|
umount $SCRATCH_MNT 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"
|
|
echo mkfs_xfs $force_opts $SCRATCH_DEV >>$seq.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 ! _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 ! umount $SCRATCH_DEV
|
|
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..." >>$seq.full
|
|
xfs_db -r -c "fsblock $2" -c "print" $1 | head | tee -a $seq.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 $seq.full
|
|
|
|
# mkfs sizes
|
|
log_size=2097152
|
|
log_size_bb=`expr $log_size / 512`
|
|
|
|
_require_scratch
|
|
_init
|
|
|
|
block=`_after_log $SCRATCH_DEV`
|
|
echo "fsblock after log = $block" >>$seq.full
|
|
_check_corrupt $SCRATCH_DEV $block
|
|
|
|
actual_log_size=`_log_size`
|
|
echo "log size = $actual_log_size BB" >>$seq.full
|
|
head=`_log_head`
|
|
echo "log position = $head" >>$seq.full
|
|
lsunit=`_log_sunit`
|
|
echo "log sunit = $lsunit" >>$seq.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" >>$seq.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" >>$seq.full
|
|
num_expected_ops=`echo "$log_size_bb / $blocks_per_op" | bc`
|
|
echo "num_expected_ops = $num_expected_ops" >>$seq.full
|
|
num_expected_to_go=`echo "$num_expected_ops - $sample_size_ops" | bc`
|
|
echo "num_expected_to_go = $num_expected_to_go" >>$seq.full
|
|
|
|
echo " lots more traffic" >>$seq.full
|
|
_log_traffic $num_expected_to_go
|
|
head=`_log_head`
|
|
echo "log position = $head" >>$seq.full
|
|
|
|
# e.g. 3891
|
|
near_end_min=`echo "0.95 * $log_size_bb" | bc | sed 's/\..*//'`
|
|
echo "near_end_min = $near_end_min" >>$seq.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" >>$seq.full
|
|
_log_traffic 2
|
|
head=`_log_head`
|
|
echo "log position = $head" >>$seq.full
|
|
_check_corrupt $SCRATCH_DEV $block
|
|
done
|
|
|
|
[ $head -lt 1000 ] || \
|
|
_fail "!!! unexpected wrapped log position $head"
|
|
|
|
# success, all done
|
|
status=0
|
|
exit
|