misc: move exit status into trap handler
[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
92 _require_scratch
93 _require_xfs_mkfs_finobt
94 _require_xfs_finobt
95
96 rm -f $seqres.full
97
98 _scratch_mkfs_xfs "-m crc=1,finobt=1 -d agcount=2" | _filter_mkfs 2>$seqres.full
99
100 # sparsely populate the fs such that we create records with free inodes
101 _scratch_mount
102 _sparse_inode_populate $SCRATCH_MNT 999
103 _scratch_unmount
104
105 # corrupt some finobt records
106 _corrupt_finobt_records $SCRATCH_DEV
107
108 # repair should detect the inconsistencies
109 _scratch_xfs_repair 2>&1 | _filter_repair
110 _check_scratch_fs
111
112 # nuke the finobt root, repair will have to regenerate from the inobt
113 _corrupt_finobt_root $SCRATCH_DEV
114
115 filter_finobt_repair() {
116         sed -e '/^agi has bad CRC/d' \
117             -e '/^bad levels/d' \
118             -e '/^bad finobt block/d' | \
119                 _filter_repair_lostblocks
120 }
121
122 _scratch_xfs_repair 2>&1 | filter_finobt_repair
123
124 status=0
125 exit