| #! /bin/bash |
| # FSQA Test No. 348 |
| # |
| # Test handling of invalid inode modes |
| # |
| # Set all possible file type values for different types of files |
| # and verify that xfs_repair detects the correct errors. |
| # |
| #----------------------------------------------------------------------- |
| # |
| # Copyright (C) 2016 CTERA Networks. All Rights Reserved. |
| # Author: Amir Goldstein <amir73il@gmail.com> |
| # |
| # 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" |
| |
| tmp=/tmp/$$ |
| status=1 # failure is the default! |
| trap "_cleanup; exit \$status" 0 1 2 3 15 |
| |
| _cleanup() |
| { |
| rm -f $tmp.* |
| } |
| |
| # get standard environment, filters and checks |
| . ./common/rc |
| . ./common/filter |
| . ./common/repair |
| |
| # real QA test starts here |
| _supported_fs xfs |
| _supported_os Linux |
| _require_scratch |
| |
| # This test will corrupt fs intentionally, so there will be WARNINGs |
| # in dmesg as expected |
| _disable_dmesg_check |
| |
| rm -f $seqres.full |
| |
| _scratch_mkfs >>$seqres.full 2>&1 |
| |
| _scratch_mount |
| |
| # Create our test files. |
| testdir=$SCRATCH_MNT/test |
| mkdir -p $testdir |
| mkdir $testdir/DIR |
| echo 123 > $testdir/DATA |
| touch $testdir/EMPTY |
| ln -s $testdir/DATA $testdir/SYMLINK |
| mknod $testdir/CHRDEV c 1 1 |
| mknod $testdir/BLKDEV b 1 1 |
| mknod $testdir/FIFO p |
| |
| xfs_info $SCRATCH_MNT | grep -q "ftype=1" && FTYPE_FEATURE=1 |
| |
| # Record test dir inode for xfs_repair filter |
| inode_filter=$tmp.sed |
| rm -f $inode_filter |
| pino=$(ls -id $testdir | awk '{print $1}') |
| echo "s/inode $pino/PARENT_INO/" >> $inode_filter |
| echo "s/directory $pino/directory PARENT_INO/" >> $inode_filter |
| |
| inodes="" |
| # Record inode numbers for xfs_db commands and xfs_repair filter |
| for f in DIR DATA EMPTY SYMLINK CHRDEV BLKDEV FIFO; do |
| ino=$(ls -id $testdir/$f | awk '{print $1}') |
| inodes="$inodes $ino" |
| echo "s/inode $ino/${f}_INO/" >> $inode_filter |
| done |
| |
| _scratch_unmount |
| |
| # Possible mode file type values (mode & S_IFMT) >> 12 |
| dtypes="0 1 2 3 4 5 6 7 10 11 12 13 14 15 16 17" |
| echo "===== Find inode by file type:" |
| for dt in $dtypes; do |
| # Set all our test files to dt value |
| for ino in $inodes; do |
| _scratch_xfs_db -c "inode $ino" -c "print core.mode" | \ |
| grep -q "0${dt}0...$" && \ |
| (echo "dt=$dt => inode $ino" | sed -f $inode_filter) |
| done |
| done |
| for dt in $dtypes; do |
| echo |
| echo "===== Setting dt=$dt to all files:" |
| # Set all our test files to dt value |
| for ino in $inodes; do |
| _scratch_xfs_db -x -c "inode $ino" -c "write core.mode 0${dt}0644" |
| done |
| # Repair should detect the inconsistencies |
| # For invalid dt values, all files would have been junked. |
| # For valid dt values, one test file is expected to be valid. |
| # The rest would either have wrong format or non matching dir ftype. |
| _scratch_xfs_repair -n 2>&1 | tee -a $seqres.full | \ |
| _filter_repair | grep "^would have junked" | sed -f $inode_filter | sort -u |
| # If ftype feature is enabled, when setting file type to one of the |
| # special types (i.e. FIFO(1), CHRDEV(2),BLKDEV(6),SOCKET(14)), |
| # xfs_repair is expected to detect ftype mismatch error. Otherewise, |
| # xfs_repair is not expected to detect ftype mismatch error. |
| if [ "$FTYPE_FEATURE" = 1 ] && (echo ':1:2:6:14:' | grep -q ":$dt:"); then |
| _scratch_xfs_repair -n 2>&1 | grep -q "^would fix ftype mismatch" || \ |
| echo "xfs_repair should fix ftype mismatch" |
| else |
| _scratch_xfs_repair -n 2>&1 | grep -q -v "^would fix ftype mismatch" || \ |
| echo "xfs_repair should not fix ftype mismatch" |
| fi |
| |
| _scratch_mount |
| for file in DIR DATA EMPTY SYMLINK CHRDEV BLKDEV FIFO; do |
| rm -f $tmp.stat.err |
| ftype=$(stat --printf=%F $testdir/$file 2>$tmp.stat.err) |
| if [ -s $tmp.stat.err ]; then |
| cat $tmp.stat.err |
| else |
| echo "stat: '$testdir/$file' is a $ftype" |
| # Verify that readlink of a file posing as a symlink |
| # and ls of a file posing as a directory does not blow up. |
| # NOTE that ls DOES ASSERT with kernel 4.9 and XFS_DEBUG=y |
| # on malformed directory |
| if [ -d $testdir/$file ]; then |
| ls $testdir/$file &> /dev/null |
| elif [ -h $testdir/$file ]; then |
| readlink $testdir/$file &> /dev/null |
| fi |
| fi | _filter_scratch |
| done |
| _scratch_unmount |
| done |
| |
| # Repair should detect and junk all test files |
| _scratch_xfs_repair 2>&1 >> $seqres.full 2>&1 || _fail "xfs_repair should not fail" |
| |
| status=0 |
| exit |