2003-10-06 07:46:19 +00:00
|
|
|
##/bin/sh
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
|
# 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
|
|
|
|
|
# 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/
|
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
|
# common routines for log testing
|
|
|
|
|
# Created by dxm@sgi.com & tes@sgi.com
|
|
|
|
|
#
|
|
|
|
|
|
|
|
|
|
fulldir=$seq.fulldir
|
|
|
|
|
rm -rf $fulldir
|
|
|
|
|
mkdir $fulldir
|
|
|
|
|
|
|
|
|
|
_cleanup_logfiles()
|
|
|
|
|
{
|
|
|
|
|
if [ $status -eq 0 ]; then
|
|
|
|
|
# don't keep these files around unless something went wrong
|
|
|
|
|
rm -rf $fulldir
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_full()
|
|
|
|
|
{
|
|
|
|
|
echo "" >>$seq.full
|
|
|
|
|
echo "*** $* ***" >>$seq.full
|
|
|
|
|
echo "" >>$seq.full
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# Handle the operations which get split over Log Record
|
|
|
|
|
# boundaries.
|
|
|
|
|
# Oper (379)..... flags: CONTINUE
|
|
|
|
|
# ...
|
|
|
|
|
# Oper (0)....... flags: WAS_CONT END
|
|
|
|
|
#
|
|
|
|
|
# or
|
|
|
|
|
#
|
|
|
|
|
# Oper (379)..... flags: none
|
|
|
|
|
# ...
|
|
|
|
|
# Oper (0)....... flags: none
|
|
|
|
|
#
|
|
|
|
|
_filter_opnum()
|
|
|
|
|
{
|
|
|
|
|
$AWK_PROG '
|
|
|
|
|
function extract_opnum(str) {
|
|
|
|
|
# e.g. "(379):" => "379"
|
|
|
|
|
gsub(/[():]/,"",str)
|
|
|
|
|
return str
|
|
|
|
|
}
|
|
|
|
|
BEGIN {
|
|
|
|
|
opnum = -1
|
|
|
|
|
#debug = 1
|
|
|
|
|
}
|
|
|
|
|
/^Oper/ && debug {
|
|
|
|
|
printf "line = %s\n", $0
|
|
|
|
|
}
|
|
|
|
|
/^Oper/ {
|
|
|
|
|
was_cont = 0
|
|
|
|
|
prev_opnum = opnum
|
|
|
|
|
opnum = extract_opnum($2)
|
|
|
|
|
}
|
|
|
|
|
/^Oper/ && /flags: CONTINUE/ {
|
|
|
|
|
$9 = "none" # overwrite CONTINUE flags
|
|
|
|
|
$2 = sprintf("(%d):", remember+opnum)
|
|
|
|
|
remember += opnum
|
|
|
|
|
print
|
|
|
|
|
next
|
|
|
|
|
}
|
|
|
|
|
/^Oper/ && /flags: WAS_CONT END/ {
|
|
|
|
|
# skip over was-continued op
|
|
|
|
|
# we assume there can be only 1
|
|
|
|
|
was_cont = 1
|
|
|
|
|
next
|
|
|
|
|
}
|
|
|
|
|
(was_cont == 1) {
|
|
|
|
|
# skip over any continued op stuff
|
|
|
|
|
next
|
|
|
|
|
}
|
|
|
|
|
/^Oper/ && /UNMOUNT/ {
|
|
|
|
|
remember = 0
|
|
|
|
|
opnum = -1
|
|
|
|
|
print
|
|
|
|
|
next
|
|
|
|
|
}
|
|
|
|
|
/^Oper/ && (opnum == 0) {
|
|
|
|
|
# have operation 0 with NO continued op
|
|
|
|
|
remember += (prev_opnum+1)
|
|
|
|
|
}
|
|
|
|
|
/^Oper/ && debug { printf "line2 = %s, remember = %d, prev_opnum = %d\n", $0, remember, prev_opnum}
|
|
|
|
|
/^Oper/ && (remember > 0) {
|
|
|
|
|
# add in opnum accumulation from previous LRs
|
|
|
|
|
$2 = sprintf("(%d):", remember+opnum)
|
|
|
|
|
print
|
|
|
|
|
next
|
|
|
|
|
}
|
|
|
|
|
{print}
|
|
|
|
|
'
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_filter_logprint()
|
|
|
|
|
{
|
2004-01-21 00:43:00 +00:00
|
|
|
_fix_malloc |\
|
2003-10-06 07:46:19 +00:00
|
|
|
sed '
|
|
|
|
|
s/data device: 0x[0-9a-f][0-9a-f]*/data device: <DEVICE>/;
|
|
|
|
|
s/log device: 0x[0-9a-f][0-9a-f]*/log device: <DEVICE>/;
|
|
|
|
|
s/log file: \".*\"/log device: <DEVICE>/;
|
|
|
|
|
s/daddr: [0-9][0-9]*/daddr: <DADDR>/;
|
|
|
|
|
s/length: [0-9][0-9]*/length: <LENGTH>/;
|
|
|
|
|
s/length: [0-9][0-9]*/length: <LENGTH>/;
|
|
|
|
|
s/^cycle num overwrites: .*$/cycle num overwrites: <TIDS>/;
|
|
|
|
|
s/tid: [0-9a-f][0-9a-f]*/tid: <TID>/;
|
|
|
|
|
s/tid:0x[0-9a-f][0-9a-f]*/tid:<TID>/;
|
|
|
|
|
s/q:0x[0-9a-f][0-9a-f]*/q:<Q>/;
|
|
|
|
|
s/a:0x[0-9a-f][0-9a-f]*/a:<A>/g;
|
|
|
|
|
s/blkno:0x[0-9a-f][0-9a-f]*/blkno:<BLKNO>/g;
|
|
|
|
|
s/blkno: [0-9][0-9]* (0x[0-9a-f]*)/blkno: <BLKNO> (<BLKNO>)/g;
|
|
|
|
|
s/blkno: [0-9][0-9]*/blkno: <BLKNO>/g;
|
|
|
|
|
s/boff: [0-9][0-9]*/boff: <BOFF>/g;
|
|
|
|
|
s/len: *[0-9][0-9]*/len:<LEN>/g;
|
|
|
|
|
/zeroed blocks/s/[0-9][0-9]*/<COUNT>/g;
|
|
|
|
|
/cleared blocks/d;
|
|
|
|
|
/log tail/s/[0-9][0-9]*/<COUNT>/g;
|
|
|
|
|
s/atime:[0-9a-fx]* *mtime:[0-9a-fx]* *ctime:[0-9a-fx]*/atime:<TIME> mtime:<TIME> ctime:<TIME>/;
|
|
|
|
|
s/atime 0x[0-9a-f]* mtime 0x[0-9a-f]* ctime 0x[0-9a-f]*/atime <TIME> mtime <TIME> ctime <TIME>/;
|
|
|
|
|
s/block [0-9][0-9]*/block <BLOCK>/;
|
|
|
|
|
s/icount: *[0-9][0-9]* *ifree: *[0-9][0-9]* *fdblks: *[0-9][0-9]* *frext: *[0-9][0-9]*/icount:<COUNT> ifree:<FREE> fdblks:<BLOCKS> frext:<COUNT>/;
|
|
|
|
|
s/sunit: *[0-9][0-9]* *swidth: *[0-9][0-9]*/sunit:<SUNIT> swidth:<SWIDTH>/;
|
|
|
|
|
s/1st: *[0-9][0-9]* *last: *[0-9][0-9]* *cnt: *[0-9][0-9]* *freeblks: *[0-9][0-9]* *longest: *[0-9][0-9]*/1st:<NUM> last:<NUM> cnt:<COUNT> freeblks:<COUNT> longest:<NUM>/;
|
|
|
|
|
s/^uuid: *[0-9a-f-][0-9a-f-]* *format: *.*$/uuid: <UUID> format: <FORMAT>/;
|
|
|
|
|
/flushiter:/d;
|
|
|
|
|
/version:/,/h_size:/d;
|
|
|
|
|
/override tail/s/[0-9][0-9]*/<TAIL_BLK>/;
|
|
|
|
|
/^---*/d;
|
|
|
|
|
/^===*/d;
|
|
|
|
|
/^~~~*/d;
|
|
|
|
|
/extended-header/d;
|
|
|
|
|
/LOG REC AT LSN/d;
|
|
|
|
|
/^[ ]*$/d;
|
|
|
|
|
s/ */ /g;
|
|
|
|
|
s/ $//;
|
2004-01-21 00:43:00 +00:00
|
|
|
'
|
2003-10-06 07:46:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_check_log()
|
|
|
|
|
{
|
|
|
|
|
_full "clean_log : xfs_logprint"
|
|
|
|
|
_scratch_xfs_logprint -t | tee -a $seq.full \
|
|
|
|
|
| head | grep -q "<CLEAN>" || _fail "DIRTY LOG"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_print_operation()
|
|
|
|
|
{
|
|
|
|
|
raw=$fulldir/op.mnt$mnt.mkfs$mkfs$sync_suffix.raw
|
|
|
|
|
filtered=$fulldir/op.mnt$mnt.mkfs$mkfs$sync_suffix.filtered
|
|
|
|
|
|
|
|
|
|
echo "### xfs_logprint output ###" | tee $raw >$filtered
|
|
|
|
|
_scratch_xfs_logprint -c 2>&1 \
|
|
|
|
|
| tee -a $raw \
|
|
|
|
|
| _filter_logprint \
|
|
|
|
|
| _filter_opnum \
|
|
|
|
|
>>$filtered
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# start at rec#2 "-s 2" so we skip over UMOUNT record which will always
|
|
|
|
|
# be a 512b single header at mkfs time
|
|
|
|
|
# and may not match with the FS mounted at a different LR size
|
|
|
|
|
# => xlog_do_recovery_pass() can not handle the different hdr sizes
|
|
|
|
|
# it assumes them all to be the same between the start..finish
|
|
|
|
|
# NB: On IRIX there is no UMOUNT record and so we could start from -s 0.
|
|
|
|
|
|
|
|
|
|
_print_transaction_inode()
|
|
|
|
|
{
|
|
|
|
|
_start=$1
|
|
|
|
|
raw=$fulldir/trans_inode.mnt$mnt.mkfs$mkfs$sync_suffix.raw
|
|
|
|
|
filtered=$fulldir/trans_inode.mnt$mnt.mkfs$mkfs$sync_suffix.filtered
|
|
|
|
|
|
|
|
|
|
echo "### xfs_logprint -t -i -s START output ###" | tee $raw >$filtered
|
|
|
|
|
_scratch_xfs_logprint -t -i -s $_start 2>&1 \
|
|
|
|
|
| tee -a $raw \
|
|
|
|
|
| _filter_logprint \
|
|
|
|
|
>>$filtered
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_print_transaction_buf()
|
|
|
|
|
{
|
|
|
|
|
_start=$1
|
|
|
|
|
raw=$fulldir/trans_buf.mnt$mnt.mkfs$mkfs$sync_suffix.raw
|
|
|
|
|
filtered=$fulldir/trans_buf.mnt$mnt.mkfs$mkfs$sync_suffix.filtered
|
|
|
|
|
|
|
|
|
|
echo "### xfs_logprint -t -b -s START output ###" | tee $raw >$filtered
|
|
|
|
|
_scratch_xfs_logprint -t -b -s $_start 2>&1 \
|
|
|
|
|
| tee -a $raw \
|
|
|
|
|
| _filter_logprint \
|
|
|
|
|
>>$filtered
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_mkfs_log()
|
|
|
|
|
{
|
|
|
|
|
typeset _mkfs_opts
|
|
|
|
|
_mkfs_opts=$1
|
|
|
|
|
|
|
|
|
|
# create the FS
|
|
|
|
|
_full "mkfs"
|
|
|
|
|
extra_ops="-lsize=2000b $_mkfs_opts"
|
|
|
|
|
_scratch_mkfs_xfs $extra_ops >$tmp.mkfs0 2>&1
|
|
|
|
|
[ $? -ne 0 ] && \
|
|
|
|
|
_notrun "Cannot mkfs for this test using MKFS_OPTIONS specified: $MKFS_OPTIONS $extra_ops"
|
|
|
|
|
cat $tmp.mkfs0 >>$seq.full
|
|
|
|
|
|
|
|
|
|
# check the mkfs settings
|
|
|
|
|
_filter_mkfs <$tmp.mkfs0 2>$tmp.mkfs
|
|
|
|
|
source $tmp.mkfs
|
|
|
|
|
[ $dbsize -eq 4096 ] \
|
|
|
|
|
|| _notrun "Logprint test, tailored to 4K blocks ($dbsize in use)"
|
|
|
|
|
[ $isize -eq 256 ] \
|
|
|
|
|
|| _notrun "Logprint test, tailored to 256b inodes ($isize in use)"
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
|
# mount fs and create some log traffic
|
|
|
|
|
#
|
|
|
|
|
_create_log()
|
|
|
|
|
{
|
|
|
|
|
typeset _mnt_opts
|
|
|
|
|
|
|
|
|
|
_mnt_opts=$1
|
|
|
|
|
|
|
|
|
|
# mount the FS
|
|
|
|
|
_full " mount"
|
|
|
|
|
_scratch_mount $_mnt_opts >>$seq.full 2>&1 \
|
|
|
|
|
|| _fail "mount failed: $_mnt_opts $MOUNT_OPTIONS"
|
|
|
|
|
|
|
|
|
|
# generate some log traffic - but not too much - life gets a little
|
|
|
|
|
# more complicated if the log wraps around. This traffic is
|
|
|
|
|
# pretty much arbitary, but could probably be made better than this.
|
|
|
|
|
touch $SCRATCH_MNT/{0,1,2,3,4,5,6,7,8,9}{0,1,2,3,4,5,6,7,8,9}
|
|
|
|
|
|
|
|
|
|
# unmount the FS
|
|
|
|
|
_full "umount"
|
|
|
|
|
umount $SCRATCH_DEV >>$seq.full 2>&1 \
|
|
|
|
|
|| _fail "umount failed"
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
|
# mount fs and create some log traffic with sync'ing
|
|
|
|
|
#
|
|
|
|
|
_create_log_sync()
|
|
|
|
|
{
|
|
|
|
|
typeset _mnt_opts
|
|
|
|
|
|
|
|
|
|
_mnt_opts=$1
|
|
|
|
|
|
|
|
|
|
# mount the FS
|
|
|
|
|
_full " mount"
|
|
|
|
|
_scratch_mount $_mnt_opts >>$seq.full 2>&1 \
|
|
|
|
|
|| _fail "mount failed: $_mnt_opts $MOUNT_OPTIONS"
|
|
|
|
|
|
|
|
|
|
# generate some log traffic - but not too much
|
|
|
|
|
# add some syncs to get the log flushed to disk
|
|
|
|
|
for file in $SCRATCH_MNT/{0,1,2,3,4,5,6,7,8,9}{0,1,2,3,4,5,6,7,8,9}; do
|
|
|
|
|
touch $file
|
|
|
|
|
sync
|
|
|
|
|
done
|
|
|
|
|
|
|
|
|
|
# unmount the FS
|
|
|
|
|
_full "umount"
|
|
|
|
|
umount $SCRATCH_DEV >>$seq.full 2>&1 \
|
|
|
|
|
|| _fail "umount failed"
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_cmp_output()
|
|
|
|
|
{
|
|
|
|
|
echo "*** compare logprint: $1 with $2"
|
|
|
|
|
if ! diff $1 $2 >/dev/null; then
|
|
|
|
|
echo "FAILED: logprint output $1 differs to $2"
|
|
|
|
|
touch $tmp.error
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_clear_opts()
|
|
|
|
|
{
|
|
|
|
|
# clear opts
|
|
|
|
|
# - remove the log options in mkfs
|
|
|
|
|
# - remove the log options in mount
|
|
|
|
|
# - remove the quota options in mount
|
|
|
|
|
# leave any other options given
|
2004-01-21 00:43:00 +00:00
|
|
|
# fix up removals when remaining -o or comma:
|
|
|
|
|
# "-o blah," -> "-o blah"
|
|
|
|
|
# "-o blah, -x woof" -> "-o blah -x woof"
|
|
|
|
|
# "-x woof -o " -> "-x woof"
|
|
|
|
|
# "-x woof -o -y wow" -> "-x woof -y wow"
|
2003-10-06 07:46:19 +00:00
|
|
|
MKFS_OPTIONS=`echo $MKFS_OPTIONS | sed -e 's/-l[ ]*[^ $]*//g'`
|
|
|
|
|
MOUNT_OPTIONS=`echo $MOUNT_OPTIONS |\
|
|
|
|
|
sed -e 's/logbsize=[^ ,]*,*//g' \
|
|
|
|
|
-e 's/usrquota,*//g' \
|
|
|
|
|
-e 's/grpquota,*//g' \
|
|
|
|
|
-e 's/quota,*//g' \
|
|
|
|
|
-e 's/uqnoenforce,*//g' \
|
|
|
|
|
-e 's/gqnoenforce,*//g' \
|
2004-01-21 00:43:00 +00:00
|
|
|
-e 's/\(-o[^-,]*\), *$/\1/g' \
|
|
|
|
|
-e 's/\(-o[^-,]*\), *-/\1 -/g' \
|
|
|
|
|
-e 's/-o *$//g' \
|
2003-10-06 07:46:19 +00:00
|
|
|
-e 's/-o *-/-/g' \
|
|
|
|
|
`
|
|
|
|
|
|
|
|
|
|
# export opts
|
|
|
|
|
export MKFS_OPTIONS
|
|
|
|
|
export MOUNT_OPTIONS
|
2004-01-21 00:43:00 +00:00
|
|
|
echo "MKFS_OPTIONS = $MKFS_OPTIONS" >>$seq.full
|
|
|
|
|
echo "MOUNT_OPTIONS = $MOUNT_OPTIONS" >>$seq.full
|
|
|
|
|
|
2003-10-06 07:46:19 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#
|
|
|
|
|
# Op data of different Log Record sizes will mean that data is
|
|
|
|
|
# split at different points and in op printing it will not
|
|
|
|
|
# try and decode the data which has been split up.
|
|
|
|
|
# So we do a special diff processing to complain of differences
|
|
|
|
|
# if no split is involved.
|
|
|
|
|
#
|
|
|
|
|
# Example diff with forms of:
|
|
|
|
|
# "Left over region from split log item"
|
|
|
|
|
# "Not printing rest of data"
|
|
|
|
|
#
|
|
|
|
|
# 2149c2149
|
|
|
|
|
# < Left over region from split log item
|
|
|
|
|
# ---
|
|
|
|
|
# > BUF DATA
|
|
|
|
|
# 2888c2888,2889
|
|
|
|
|
# < INODE: #regs: 3 Not printing rest of data
|
|
|
|
|
# ---
|
|
|
|
|
# > INODE: #regs: 3 ino: 0x80 flags: 0x5 dsize: 16
|
|
|
|
|
# > blkno: <BLKNO> len:<LEN> boff: <BOFF>
|
|
|
|
|
#
|
|
|
|
|
_process_op_diff()
|
|
|
|
|
{
|
|
|
|
|
$AWK_PROG <$1 '
|
|
|
|
|
BEGIN { num_splits = 1 }
|
|
|
|
|
/^[0-9]/ {
|
|
|
|
|
|
|
|
|
|
# ensure cmd is a change op
|
|
|
|
|
cmd = $1
|
|
|
|
|
gsub(/[0-9][0-9]*/,"", cmd)
|
|
|
|
|
gsub(/,/,"", cmd)
|
|
|
|
|
if (cmd != "c") {
|
|
|
|
|
print "bad diff cmd: ", $0
|
|
|
|
|
exit 1
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
# ensure a split happened in previous difference
|
|
|
|
|
if (num_splits != 1 && num_splits != 2) {
|
|
|
|
|
print num_splits, " split(s) found prior to diff cmd: ", $0
|
|
|
|
|
num_splits = 1 # shut-up end condition
|
|
|
|
|
exit 1
|
|
|
|
|
}
|
|
|
|
|
num_splits = 0
|
|
|
|
|
|
|
|
|
|
next
|
|
|
|
|
}
|
|
|
|
|
/Left over region/ || /Not printing rest/ {
|
|
|
|
|
num_splits++
|
|
|
|
|
next
|
|
|
|
|
}
|
|
|
|
|
{ next }
|
|
|
|
|
END {
|
|
|
|
|
if (num_splits != 1 && num_splits != 2) {
|
|
|
|
|
print num_splits, " split(s) found prior to diff end"
|
|
|
|
|
exit 1
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
'
|
|
|
|
|
return $?
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
_cmp_op_output()
|
|
|
|
|
{
|
|
|
|
|
echo "*** compare logprint: $1 with $2"
|
|
|
|
|
|
|
|
|
|
diff $1 $2 >$filtered.diff
|
|
|
|
|
if ! _process_op_diff $filtered.diff
|
|
|
|
|
then
|
|
|
|
|
echo "FAILED: logprint output $1 differs to $2 considering splits"
|
|
|
|
|
touch $tmp.error
|
|
|
|
|
fi
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# make sure this script returns success
|
|
|
|
|
/bin/true
|