xfs/010,030: filter AG header CRC error warnings
[xfstests-dev.git] / tests / xfs / 010
1 #!/bin/bash
2 # SPDX-License-Identifier: GPL-2.0
3 # Copyright (c) 2014 Red Hat, Inc.  All Rights Reserved.
4 #
5 # FS QA Test No. xfs/010
6 #
7 # Test xfs_repair of the free inode btree (finobt). Make a couple targeted
8 # corruptions and verify that xfs_repair detects and repairs the filesystem to
9 # a consistent state.
10 #
11 seq=`basename $0`
12 seqres=$RESULT_DIR/$seq
13 echo "QA output created by $seq"
14
15 here=`pwd`
16 tmp=/tmp/$$
17 status=1        # failure is the default!
18
19 # get standard environment, filters and checks
20 . ./common/rc
21 . ./common/filter
22 . ./common/repair
23
24 _cleanup()
25 {
26         cd /
27         _scratch_unmount 2>/dev/null
28         rm -f $tmp.*
29 }
30 trap "_cleanup; exit \$status" 0 1 2 3 15
31
32 _sparse_inode_populate()
33 {
34         dir=$1
35         count=$2
36
37         for i in $(seq 0 $count)
38         do
39                 touch $dir/$i
40         done
41
42         # Inode chunks are allocated 64 inodes at a time. If we remove 1 out of
43         # every 32 we allocated above, we'll end up leaving an inode or two free
44         # in each chunk. This ensures that most records are inserted into the
45         # finobt.
46         for i in $(seq 0 32 $count)
47         do
48                 rm -f $dir/$i
49         done
50 }
51
52 _filter_dbval()
53 {
54         awk '{ print $3 }'
55 }
56
57 _corrupt_finobt_records()
58 {
59         dev=$1
60
61         # determine the root block of the finobt
62         free_root=`$XFS_DB_PROG -c "agi 0" -c "p free_root" $dev |
63                         _filter_dbval`
64
65         # Corrupt a freecount value. This should never exceed 64.
66         $XFS_DB_PROG -x -c "fsb $free_root" -c "type finobt" \
67                 -c "write recs[1].freecount 70" $dev
68
69         # Create a corrupted non-free record, which should never appear in the
70         # finobt.
71         $XFS_DB_PROG -x -c "fsb $free_root" -c "type finobt" \
72                  -c "write recs[2].freecount 0" $dev
73         $XFS_DB_PROG -x -c "fsb $free_root" -c "type finobt" \
74                 -c "write recs[2].free 0" $dev
75 }
76
77 _corrupt_finobt_root()
78 {
79         dev=$1
80
81         # nuke the agi finobt root fields
82         $XFS_DB_PROG -x                         \
83                 -c "agi 0"                      \
84                 -c "write -c free_root 0"       \
85                 -c "write -c free_level 0"      \
86                 $dev | grep -v "Allowing write of corrupted"
87 }
88
89 # real QA test starts here
90 _supported_fs xfs
91 _supported_os Linux
92
93 _require_scratch
94 _require_xfs_mkfs_finobt
95 _require_xfs_finobt
96
97 rm -f $seqres.full
98
99 _scratch_mkfs_xfs "-m crc=1,finobt=1 -d agcount=2" | _filter_mkfs 2>$seqres.full
100
101 # sparsely populate the fs such that we create records with free inodes
102 _scratch_mount
103 _sparse_inode_populate $SCRATCH_MNT 999
104 _scratch_unmount
105
106 # corrupt some finobt records
107 _corrupt_finobt_records $SCRATCH_DEV
108
109 # repair should detect the inconsistencies
110 _scratch_xfs_repair 2>&1 | _filter_repair
111 _check_scratch_fs
112
113 # nuke the finobt root, repair will have to regenerate from the inobt
114 _corrupt_finobt_root $SCRATCH_DEV
115
116 filter_finobt_repair() {
117         sed -e '/^agi has bad CRC/d' | \
118                 _filter_repair_lostblocks
119 }
120
121 _scratch_xfs_repair 2>&1 | filter_finobt_repair
122
123 status=0
124 exit