-#! /bin/sh
-# XFS QA Test No. 016
-# $Id: 1.1 $
+#! /bin/bash
+# FS QA Test No. 016
#
# test end of log overwrite bug #796141
#
#-----------------------------------------------------------------------
-# Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
-#
-# This program is free software; you can redistribute it and/or modify it
-# under the terms of version 2 of the GNU General Public License as
+# 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.
-#
-# Further, this software is distributed without any warranty that it is
-# free of the rightful claim of any third person regarding infringement
-# or the like. Any license provided herein, whether implied or
-# otherwise, applies only to this software file. Patent licenses, if
-# any, provided herein do not apply to combinations of this program with
-# other software, or any other product whatsoever.
-#
-# You should have received a copy of the GNU General Public License along
-# with this program; if not, write the Free Software Foundation, Inc., 59
-# Temple Place - Suite 330, Boston MA 02111-1307, USA.
-#
-# Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
-# Mountain View, CA 94043, or:
-#
-# http://www.sgi.com
-#
-# For further information regarding this notice, see:
-#
-# http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
+#
+# 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
# 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 :
+# 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
_cleanup()
{
+ cd /
rm -f $tmp.*
echo "*** unmount"
umount $SCRATCH_MNT 2>/dev/null
echo "*** reset partition"
$here/src/devzero -b 2048 -n 50 -v 198 $SCRATCH_DEV
echo "*** mkfs"
- lsize=2097152
- dsize=50m
- echo mkfs_xfs -dsize=$dsize -lsize=$lsize $SCRATCH_DEV >>$seq.full
- if ! mkfs_xfs -dsize=$dsize -lsize=$lsize $SCRATCH_DEV >>$seq.full 2>&1
- then
- echo "failed to mkfs $SCRATCH_DEV" >>$seq.full
- _notrun "mkfs cannot create scratch fs, probably too small log"
- exit 1
+ 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 ! mount -t xfs $SCRATCH_DEV $SCRATCH_MNT
+ if ! _scratch_mount
then
echo "failed to mount $SCRATCH_DEV"
exit 1
# having any quota enabled (acct/enfd) means extra log traffic - evil!
$here/src/feature -U $SCRATCH_DEV && \
- _notrun "Quota are enabled, test needs controlled log traffic"
+ _notrun "UQuota are enabled, test needs controlled log traffic"
$here/src/feature -G $SCRATCH_DEV && \
- _notrun "Quota are enabled, test needs controlled log traffic"
-
+ _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
- rm $out
- let "count = count - 1"
+ touch $out
+ sync
+ rm $out
+ sync
+ let "count = count - 1"
done
-
+
echo " *** unmount"
if ! umount $SCRATCH_DEV
then
_log_size()
{
- xfs_logprint -tb $SCRATCH_DEV | $AWK_PROG '
- /log device/ { print $7}
+ _scratch_xfs_logprint -tb | $AWK_PROG '
+ /log file: / || /log device: / { print $7}
'
}
_log_head()
{
- xfs_logprint -tb $SCRATCH_DEV | $AWK_PROG '
+ _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"
+# (or v1 log) just return "1" block
_log_sunit()
{
- echo $MKFS_OPTIONS | (grep sunit || echo "sunit=1") \
- | sed "s/.*sunit=\(.*\).*/\1/"
-}
+ if [ ${lsunit:-0} -eq 0 ]; then
+ echo $dbsize
+ else
+ expr $lsunit \* $dbsize
+ fi
+}
_after_log()
{
f="c6c6c6c6"
echo "*** check for corruption"
echo "expect $f..." >>$seq.full
- xfs_db -r $1 -c "fsblock $2" -c "print" | head | tee -a $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!"
}
. ./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
echo "fsblock after log = $block" >>$seq.full
_check_corrupt $SCRATCH_DEV $block
-size=`_log_size`
-echo "log size = $size BB" >>$seq.full
+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
-[ $size -eq 4096 ] || \
+# 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"
-
-echo " lots of traffic" >>$seq.full
-_log_traffic 850
+ _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
-[ $head -gt 3850 -a $head -lt 4050 ] || \
- _fail "!!! unexpected log position $head"
+# 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 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
+for c in `seq 0 20`
do
echo " little traffic" >>$seq.full
_log_traffic 2
done
[ $head -lt 1000 ] || \
- _fail "!!! unexpected log position $head"
+ _fail "!!! unexpected wrapped log position $head"
# success, all done
status=0