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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
##/bin/bash
# SPDX-License-Identifier: GPL-2.0
# Copyright (c) 2000-2002 Silicon Graphics, Inc. All Rights Reserved.
#
# Functions useful for xfs_repair tests
_zero_position()
{
value=$1
struct="$2"
# set values for off/len variables provided by db
eval `_scratch_xfs_db -r -c "$struct" -c stack | perl -ne '
if (/byte offset (\d+), length (\d+)/) {
print "offset=$1\nlength=$2\n"; exit
}'`
if [ -z "$offset" -o -z "$length" ]; then
echo "cannot calculate offset ($offset) or length ($length)"
exit
fi
length=`expr $length / 512`
$here/src/devzero -v $value -b 1 -n $length -o $offset $SCRATCH_DEV \
| perl -npe 's/\d\.\d\dKb/X.XXKb/g'
}
_filter_repair()
{
perl -ne '
# for sb
/- agno = / && next; # remove each AG line (variable number)
s/(pointer to) (\d+)/\1 INO/;
# Changed inode output in 5.5.0
s/sb root inode value /sb root inode /;
s/realtime bitmap inode value /realtime bitmap inode /;
s/realtime summary inode value /realtime summary inode /;
s/ino pointer to /inode pointer to /;
#
s/(sb root inode) (\d+)( \(NULLFSINO\))?/\1 INO/;
s/(realtime bitmap inode) (\d+)( \(NULLFSINO\))?/\1 INO/;
s/(realtime summary inode) (\d+)( \(NULLFSINO\))?/\1 INO/;
s/(inconsistent with calculated value) (\d+)/\1 INO/;
s/\.+(found)/\1/g; # remove "searching" output
# for agf + agi
s/(bad length -{0,1}\d+ for ag. 0, should be) (\d+)/\1 LENGTH/;
s/(bad length # -{0,1}\d+ for ag. 0, should be) (\d+)/\1 LENGTH/;
s/(bad agbno) (\d+)/\1 AGBNO/g;
s/(max =) (\d+)/\1 MAX/g;
s/(bad levels) (\d+) (for [a-z]* root, agno) (\d+)/\1 LEVELS \3 AGNO/;
# for root inos
s/(on inode) (\d+)/\1 INO/g;
s/(imap claims a free inode) (\d+)/\1 INO/;
s/(imap claims in-use inode) (\d+)/\1 INO/;
s/(cleared root inode) (\d+)/\1 INO/;
s/(resetting inode) (\d+)/\1 INO/;
s/(disconnected dir inode) (\d+)/\1 INO/;
# for log
s/internal log/<TYPEOF> log/g;
s/external log on \S+/<TYPEOF> log/g;
# realtime subvol - remove this whole line if it appears
s/ - generate realtime summary info and bitmap...\n//g;
#
# new xfs repair output filters
#
s/\s+- creating \d+ worker thread\(s\)\n//g;
s/\s+- reporting progress in intervals of \d+ minutes\n//g;
s/\s+- \d+:\d\d:\d\d:.*\n//g;
# 3.1.0 extra accounting output
/^agf_/ && next; # remove agf counts
/^agi_/ && next; # remove agi counts
/^sb_/ && next; # remove sb counts
/^agi unlinked/ && next; # remove agi unlinked bucket warning
# crc enabled filesystem output
/XFS_CORRUPTION_ERROR/ && next;
/^bad uuid/ && next;
/^Metadata corruption detected/ && next;
/^Metadata CRC error detected/ && next;
/^agfl has bad CRC/ && next;
/^bad CRC for inode/ && next;
# finobt enabled filesystem output
s/(inode chunk) (\d+)\/(\d+)/AGNO\/INO/;
# sunit/swidth reset messages
s/^(Note - .*) were copied.*/\1 fields have been reset./;
s/^(Please) reset (with .*) if necessary/\1 set \2/;
# remove new unlinked inode test
/^bad next_unlinked/ && next;
# And make them generic so we dont depend on geometry
s/(stripe unit) \(.*\) (and width) \(.*\)/\1 (SU) \2 (SW)/;
# corrupt sb messages
s/(superblock) (\d+)/\1 AGNO/;
s/(AG \#)(\d+)/\1AGNO/;
s/(reset bad sb for ag) (\d+)/\1 AGNO/;
s/(unknown block state, ag )(\d+)(, blocks? )(\d+)/\1AGNO\3AGBNO/;
s/^Superblock has (bad magic number) 0x.*/\1/;
/^Note - quota info will be regenerated on next quota mount.$/ && next;
print;'
}
# Filter out unknown block state messages that appear when rmap is enabled
# and we erase a btree root pointer (such that repair never finds the
# tree and fails to reconcile the metadata reverse mappings against the
# metadata).
_filter_repair_lostblocks() {
_filter_repair | sed -e '/unknown block state, ag AGNO, blocks* AGBNO/d'
}
_filter_dd()
{
grep -F -v records # lose records in/out lines
}
# do some controlled corrupting & ensure repair recovers us
#
_check_repair()
{
value=$1
structure="$2"
#ensure the filesystem has been dirtied since last repair
_scratch_mount
POSIXLY_CORRECT=yes \
dd if=/bin/bash of=$SCRATCH_MNT/sh 2>&1 |_filter_dd
sync
rm -f $SCRATCH_MNT/sh
_scratch_unmount
_zero_position $value "$structure"
_scratch_xfs_repair 2>&1 | _filter_repair
# some basic sanity checks...
_check_scratch_fs
_scratch_mount #mount
POSIXLY_CORRECT=yes \
dd if=/bin/bash of=$SCRATCH_MNT/sh 2>&1 |_filter_dd #open,write
POSIXLY_CORRECT=yes \
dd if=$SCRATCH_MNT/sh of=/dev/null 2>&1 |_filter_dd #read
rm -f $SCRATCH_MNT/sh #unlink
_scratch_unmount #umount
}
# make sure this script returns success
/bin/true
|