xfs/010: test repair for finobt corruption

The finobt creates a duplicate subset of inode allocation metadata from
the inobt. xfs_repair should detect and repair inconsistencies in the
finobt that could be caused by bugs or corruption. This test uses xfs_db
to cause targeted corruptions in the finobt and verify repair detects
and corrects the filesystem.

In particular, the test corrupts individual finobt records to cause
inconsistency between the inode allocation count fields as well as
causing the finobt to contain a record with no free inodes.

Signed-off-by: Brian Foster <bfoster@redhat.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
This commit is contained in:
Brian Foster
2014-05-13 15:27:47 +10:00
committed by Dave Chinner
parent 01fbf447cc
commit d95ecb0354
3 changed files with 191 additions and 0 deletions
Executable
+133
View File
@@ -0,0 +1,133 @@
#!/bin/bash
# FS QA Test No. xfs/010
#
# Test xfs_repair of the free inode btree (finobt). Make a couple targeted
# corruptions and verify that xfs_repair detects and repairs the filesystem to
# a consistent state.
#
#-----------------------------------------------------------------------
# Copyright (c) 2014 Red Hat, 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!
# get standard environment, filters and checks
. ./common/rc
. ./common/filter
. ./common/repair
_cleanup()
{
cd /
umount $SCRATCH_MNT 2>/dev/null
rm -f $tmp.*
}
trap "_cleanup; exit \$status" 0 1 2 3 15
_sparse_inode_populate()
{
dir=$1
count=$2
for i in $(seq 0 $count)
do
touch $dir/$i
done
# Inode chunks are allocated 64 inodes at a time. If we remove 1 out of
# every 32 we allocated above, we'll end up leaving an inode or two free
# in each chunk. This ensures that most records are inserted into the
# finobt.
for i in $(seq 0 32 $count)
do
rm -f $dir/$i
done
}
_filter_dbval()
{
awk '{ print $3 }'
}
_corrupt_finobt_records()
{
dev=$1
# determine the root block of the finobt
free_root=`$XFS_DB_PROG -c "agi 0" -c "p free_root" $dev |
_filter_dbval`
# Corrupt a freecount value. This should never exceed 64.
$XFS_DB_PROG -x -c "fsb $free_root" -c "type inobt" \
-c "write recs[1].freecount 70" $dev
# Create a corrupted non-free record, which should never appear in the
# finobt.
$XFS_DB_PROG -x -c "fsb $free_root" -c "type inobt" \
-c "write recs[2].freecount 0" $dev
$XFS_DB_PROG -x -c "fsb $free_root" -c "type inobt" \
-c "write recs[2].free 0" $dev
}
_corrupt_finobt_root()
{
dev=$1
# nuke the agi finobt root fields
$XFS_DB_PROG -x -c "agi 0" -c "write free_root 0" $dev
$XFS_DB_PROG -x -c "agi 0" -c "write free_level 0" $dev
}
# real QA test starts here
_supported_fs xfs
_supported_os Linux
_require_scratch
_require_xfs_mkfs_finobt
_require_xfs_finobt
rm -f $seqres.full
_scratch_mkfs_xfs "-m crc=1,finobt=1 -d agcount=2" | _filter_mkfs 2>$seqres.full
# sparsely populate the fs such that we create records with free inodes
_scratch_mount
_sparse_inode_populate $SCRATCH_MNT 999
umount $SCRATCH_MNT
# corrupt some finobt records
_corrupt_finobt_records $SCRATCH_DEV
# repair should detect the inconsistencies
_scratch_xfs_repair 2>&1 | _filter_repair
_check_scratch_fs
# nuke the finobt root, repair will have to regenerate from the inobt
_corrupt_finobt_root $SCRATCH_DEV
_scratch_xfs_repair 2>&1 | _filter_repair
_check_scratch_fs
status=0
exit
+57
View File
@@ -0,0 +1,57 @@
QA output created by 010
meta-data=DDEV isize=XXX agcount=N, agsize=XXX blks
data = bsize=XXX blocks=XXX, imaxpct=PCT
= sunit=XXX swidth=XXX, unwritten=X
naming =VERN bsize=XXX
log =LDEV bsize=XXX blocks=XXX
realtime =RDEV extsz=XXX blocks=XXX, rtextents=XXX
recs[1].freecount = 70
recs[2].freecount = 0
recs[2].free = 0
Phase 1 - find and verify superblock...
Phase 2 - using <TYPEOF> log
- zero log...
- scan filesystem freespace and inode maps...
finobt ir_freecount/free mismatch, AGNO/INO, freecount 70 nfree 2
finobt record with no free inodes, AGNO/INO
- found root inode chunk
Phase 3 - for each AG...
- scan and clear agi unlinked lists...
- process known inodes and perform inode discovery...
- process newly discovered inodes...
Phase 4 - check for duplicate blocks...
- setting up duplicate extent list...
- check for inodes claiming duplicate blocks...
Phase 5 - rebuild AG headers and trees...
- reset superblock...
Phase 6 - check inode connectivity...
- resetting contents of realtime bitmap and summary inodes
- traversing filesystem ...
- traversal finished ...
- moving disconnected inodes to lost+found ...
Phase 7 - verify and correct link counts...
done
free_root = 0
free_level = 0
Phase 1 - find and verify superblock...
Phase 2 - using <TYPEOF> log
- zero log...
- scan filesystem freespace and inode maps...
bad agbno AGBNO for finobt root, agno 0
- found root inode chunk
Phase 3 - for each AG...
- scan and clear agi unlinked lists...
- process known inodes and perform inode discovery...
- process newly discovered inodes...
Phase 4 - check for duplicate blocks...
- setting up duplicate extent list...
- check for inodes claiming duplicate blocks...
Phase 5 - rebuild AG headers and trees...
- reset superblock...
Phase 6 - check inode connectivity...
- resetting contents of realtime bitmap and summary inodes
- traversing filesystem ...
- traversal finished ...
- moving disconnected inodes to lost+found ...
Phase 7 - verify and correct link counts...
done
+1
View File
@@ -7,6 +7,7 @@
007 auto quota quick
008 rw ioctl auto quick
009 rw ioctl auto prealloc quick
010 auto quick repair
012 rw auto quick
016 rw auto quick
017 mount auto quick stress