Files
apfstests/016
T
Boris Ranto b748511b81 016: Do not discard blocks at mkfs time
The test 016 fills scratch device with some data and then creates xfs fs
on the scratch device. Later, the test assumes that the previously
written data are still written there and checks for them at specific
locations. On ssd drive this will lead to a failure since the blocks are
discarded by default when the mkfs command is run.
This is a more verbose version of the previous patch.
This simple patch that adds -K to stop the discarding (if the mkfs
command supports it) fixed the issue for me:

Signed-off-by: Boris Ranto <branto@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Eric Sandeen <sandeen@redhat.com>
2012-05-30 17:39:29 -05:00

250 lines
6.4 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"
#
# 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 >>$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