blob: 16c08b8522eedddb90dab36048450fde1ea670b4 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
#!/bin/bash
# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2014 Red Hat, Inc. All Rights Reserved.
#
# 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.
#
. ./common/preamble
_begin_fstest auto quick repair
# Import common functions.
. ./common/filter
. ./common/repair
# Override the default cleanup function.
_cleanup()
{
cd /
_scratch_unmount 2>/dev/null
rm -f $tmp.*
}
_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 finobt" \
-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 finobt" \
-c "write recs[2].freecount 0" $dev
$XFS_DB_PROG -x -c "fsb $free_root" -c "type finobt" \
-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 -c free_root 0" \
-c "write -c free_level 0" \
$dev | grep -v "Allowing write of corrupted"
}
# real QA test starts here
_supported_fs xfs
_require_scratch
_require_xfs_mkfs_finobt
_require_xfs_finobt
_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
_scratch_unmount
# 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
filter_finobt_repair() {
sed -e '/^agi has bad CRC/d' \
-e '/^bad levels/d' \
-e '/^bad finobt block/d' | \
_filter_repair_lostblocks
}
_scratch_xfs_repair 2>&1 | filter_finobt_repair
status=0
exit
|