#! /bin/bash
# FS QA Test No. 114
#
# Test some parent ptr stuff
#
#-----------------------------------------------------------------------
# Copyright (c) 2005 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
#
#-----------------------------------------------------------------------
#

seq=`basename $0`
seqres=$RESULT_DIR/$seq
echo "QA output created by $seq"

here=`pwd`
tmp=/tmp/$$
status=1	# failure is the default!
trap "_cleanup; exit \$status" 0 1 2 3 15

_cleanup()
{
    cd /
    rm -f $tmp.*
}

_check_paths()
{
	_path=$1 # might want to only check this path

	sync; sleep 1
	echo ""
	echo "Check parent"
	if ! $XFS_IO_PROG -x -c 'parent -c' $SCRATCH_MNT | _filter_num; then
		exit 1
	fi
}

_print_names()
{
	echo ""
	echo "Print out hardlink names for given path, $1"
	echo ""

	$XFS_IO_PROG -x -c parent $1 | awk '/p_ino.*=/ {$3 = "inodeXXX"; print; next} {print}'
}

_test_create()
{
	echo ""
	echo "Testing create"
	echo ""

	# Test out some creations
	cd $SCRATCH_MNT
	touch file1

	mkdir dir2
	touch dir2/file2

	mkdir dir2/dir3
	touch dir2/dir3/file3

	mkdir dir2/dir3/dir4

	p=dir2/dir3/dir4/file4
	touch $p

	#_print_names $p >>$seqres.full
	_print_names $p | tee -a $seqres.full

	_check_paths $SCRATCH_MNT/$p
}

_test_symlink()
{
	echo ""
	echo "Testing symlink"
	echo ""

	d=sym1/sym2/sym3
	f=$d/sym4_f

	mkdir -p $d
        ln -s $f symlink1
	ln symlink1 hlink1
	ln symlink1 hlink2
	ln symlink1 hlink3
	_check_paths $SCRATCH_MNT/symlink1
	_check_paths $SCRATCH_MNT/hlink1
	_check_paths $SCRATCH_MNT/hlink2
	_check_paths $SCRATCH_MNT/hlink3
}

#
# create hardlinks from the same dir
# and some from different dirs
#
# test out removing hardlinks too
#
_test_hardlink()
{
	echo ""
	echo "Testing hardlink"
	echo ""

	d=dir2/dir3/dir4
	d2=dir2/dir5/dir6
	mkdir -p $d
	mkdir -p $d2
	p=$d/file4
	touch $p

	# create hardlinks
	paths="$d/l1 $d/l2 $d/l3 $d2/l4 $d2/l5 $d2/l6"
	for x in $paths; do
		ln $p $x
	done

	_print_names $p >>$seqres.full

	echo ""
	echo "print out names and check after created hardlinks"
	echo ""
	for x in $paths; do
		_print_names $x | tee -a $seqres.full
		_check_paths $SCRATCH_MNT/$x
	done

	echo ""
	echo "now try removing half of the hardlinks"
	echo ""
	paths="$d/l1 $d/l2 $d/l3 $d2/l4 $d2/l5 $d2/l6"
	i=0
	for x in $paths; do
		let i=$i+1
		let j=$i%2
		if [ $j -eq 0 ]; then
			echo "rm'ing $x"
			rm $x
		fi
	done

	echo ""
	echo "print out names and check after removed hardlinks"
	echo ""
	for x in $paths; do
		if [ -e $x ]; then 
			_print_names $x | tee -a $seqres.full
			_check_paths $SCRATCH_MNT/$x
		fi
	done

}

#
# in dir, file1 to file2 where file2 does not exist
# in dir, file1 to file2 where file2 does exist 
# dir/file1 to dir2/file2 where file2 does not exist
# dir/file1 to dir2/file2 where file2 does exist
# dir to dir2 where dir2 does not exist
# dir to dir/dir3 - not allowed
#
_test_rename()
{
	echo ""
	echo "Testing rename"
	echo ""

	echo ""
	echo "1. in dir, file1 to file2 where file2 does not exist" 
	echo ""
	d1=$SCRATCH_MNT/ren1/ren2/ren3/ren4
	mkdir -p $d1
	p1=$d1/f1
	p2=$d1/f2
	touch $p1
	mv $p1 $p2
	_check_paths $p2

	echo ""
	echo "2. in dir, file1 to file2 where file2 does exist" 
	echo ""
	touch $p1
	mv $p1 $p2
	_check_paths $p2

	echo ""
	echo "3. dir/file1 to dir2/file2 where file2 does not exist"
	echo ""
	d2=$SCRATCH_MNT/ren1/ren2/ren3/ren5
	mkdir -p $d2
	p3=$d2/f3
	touch $p1
	mv $p1 $p3
	_check_paths $p3

	echo ""
	echo "4. dir/file1 to dir2/file2 where file2 does exist"
	echo ""
	d2=$SCRATCH_MNT/ren1/ren2/ren3/ren5
	p3=$d2/f3
	touch $p1
	mv $p1 $p3
	_check_paths $p3

	echo ""
	echo "5. dir to dir2 where dir2 does not exist"
	echo ""
	d3=$SCRATCH_MNT/ren1/ren2/ren3/ren6
	mv $d1 $d3
	_check_paths $d3
}

_filter_num()
{
	tee -a $seqres.full |\
	sed -e 's/[0-9][0-9]* inodes/I inodes/g' \
	    -e 's/[0-9][0-9]* paths/P paths/g' \
	    -e 's/seed = [0-9][0-9]*/seed = S/'
}

_test_fsstress()
{
	echo ""
	echo "Testing fsstress"
	echo ""

	out=$SCRATCH_MNT/fsstress.$$
	count=1000
	args=`_scale_fsstress_args -z \
-f rmdir=10 -f link=10 -f creat=10 \
-f mkdir=10 -f rename=30 -f unlink=10 \
-f symlink=10 \
-n $count -d $out -p 3`

	echo "fsstress $args" | sed -e "s#$out#outdir#"
	if ! $FSSTRESS_PROG $args | _filter_num
	then
		echo "    fsstress $args returned $?"
		cat $tmp.out | tee -a $seqres.full
		status=1
	fi

	_check_paths
}

_test_dirstress()
{
	echo ""
	echo "Testing dirstress"
	echo ""

	out=$SCRATCH_MNT/dirstress.$$
	count=1000

	if ! mkdir $out
	then
	    echo "!! couldn't mkdir $out"
	    status=1
	    exit
	fi

	args="-d $out -f $count -k -p 3 -n 1"
	echo "dirstress $args" | sed -e "s#$out#outdir#"
	if ! $here/src/dirstress $args >$tmp.out 2>&1 | _filter_num
	then
		echo "    dirstress failed"
		echo "*** dirstress $args" | tee -a $seqres.full
		cat $tmp.out >>$seqres.full
		status=1
		exit
	fi

	args="-d $out -f $count -k -p 3 -n 5"
	echo "dirstress $args" | sed -e "s#$out#outdir#"
	if ! $here/src/dirstress $args >$tmp.out 2>&1 | _filter_num
	then
		echo "    dirstress failed"
		echo "*** dirstress $args" | tee -a $seqres.full
		cat $tmp.out >>$seqres.full
		status=1
		exit
	fi

	_check_paths
}

# get standard environment, filters and checks
. ./common/rc
. ./common/filter
. ./common/attr

_supported_fs xfs
_supported_os IRIX

_require_scratch
_require_attrs

rm -f $seqres.full

echo "mkfs"
_scratch_mkfs_xfs >>$seqres.full 2>&1 \
    || _fail "mkfs scratch failed"
_scratch_mkfs_xfs -i parent=1 >>$seqres.full 2>&1 \
    || _notrun "parent inodes not supported"

echo "mount"
_scratch_mount >>$seqres.full 2>&1 \
    || _fail "mount failed: $MOUNT_OPTIONS"

# real QA test starts here

verbose=false

_test_create
_test_hardlink
_test_rename
_test_symlink

# stress testing with verification by parent checking programs
_test_fsstress
_test_dirstress

# success, all done
status=0
exit
