mirror of
https://github.com/linux-apfs/apfstests.git
synced 2026-05-01 15:01:44 -07:00
b748511b81
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>
250 lines
6.4 KiB
Bash
Executable File
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
|