This source file includes following definitions.
- xchk_fscount_warmup
- xchk_setup_fscounters
- xchk_fscount_aggregate_agcounts
- xchk_fscount_within_range
- xchk_fscounters
1
2
3
4
5
6 #include "xfs.h"
7 #include "xfs_fs.h"
8 #include "xfs_shared.h"
9 #include "xfs_format.h"
10 #include "xfs_trans_resv.h"
11 #include "xfs_mount.h"
12 #include "xfs_sb.h"
13 #include "xfs_alloc.h"
14 #include "xfs_ialloc.h"
15 #include "xfs_health.h"
16 #include "scrub/scrub.h"
17 #include "scrub/common.h"
18 #include "scrub/trace.h"
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 #define XCHK_FSCOUNT_MIN_VARIANCE (512)
51
52
53
54
55
56
57
58
59
60
61
62 STATIC int
63 xchk_fscount_warmup(
64 struct xfs_scrub *sc)
65 {
66 struct xfs_mount *mp = sc->mp;
67 struct xfs_buf *agi_bp = NULL;
68 struct xfs_buf *agf_bp = NULL;
69 struct xfs_perag *pag = NULL;
70 xfs_agnumber_t agno;
71 int error = 0;
72
73 for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
74 pag = xfs_perag_get(mp, agno);
75
76 if (pag->pagi_init && pag->pagf_init)
77 goto next_loop_perag;
78
79
80 error = xfs_ialloc_read_agi(mp, sc->tp, agno, &agi_bp);
81 if (error)
82 break;
83 error = xfs_alloc_read_agf(mp, sc->tp, agno, 0, &agf_bp);
84 if (error)
85 break;
86 error = -ENOMEM;
87 if (!agf_bp || !agi_bp)
88 break;
89
90
91
92
93
94 error = -EFSCORRUPTED;
95 if (!pag->pagi_init || !pag->pagf_init)
96 break;
97
98 xfs_buf_relse(agf_bp);
99 agf_bp = NULL;
100 xfs_buf_relse(agi_bp);
101 agi_bp = NULL;
102 next_loop_perag:
103 xfs_perag_put(pag);
104 pag = NULL;
105 error = 0;
106
107 if (fatal_signal_pending(current))
108 break;
109 }
110
111 if (agf_bp)
112 xfs_buf_relse(agf_bp);
113 if (agi_bp)
114 xfs_buf_relse(agi_bp);
115 if (pag)
116 xfs_perag_put(pag);
117 return error;
118 }
119
120 int
121 xchk_setup_fscounters(
122 struct xfs_scrub *sc,
123 struct xfs_inode *ip)
124 {
125 struct xchk_fscounters *fsc;
126 int error;
127
128 sc->buf = kmem_zalloc(sizeof(struct xchk_fscounters), 0);
129 if (!sc->buf)
130 return -ENOMEM;
131 fsc = sc->buf;
132
133 xfs_icount_range(sc->mp, &fsc->icount_min, &fsc->icount_max);
134
135
136 error = xchk_fscount_warmup(sc);
137 if (error)
138 return error;
139
140
141
142
143
144
145 xchk_stop_reaping(sc);
146
147 return xchk_trans_alloc(sc, 0);
148 }
149
150
151
152
153
154
155
156 STATIC int
157 xchk_fscount_aggregate_agcounts(
158 struct xfs_scrub *sc,
159 struct xchk_fscounters *fsc)
160 {
161 struct xfs_mount *mp = sc->mp;
162 struct xfs_perag *pag;
163 uint64_t delayed;
164 xfs_agnumber_t agno;
165 int tries = 8;
166
167 retry:
168 fsc->icount = 0;
169 fsc->ifree = 0;
170 fsc->fdblocks = 0;
171
172 for (agno = 0; agno < mp->m_sb.sb_agcount; agno++) {
173 pag = xfs_perag_get(mp, agno);
174
175
176 if (!pag->pagi_init || !pag->pagf_init) {
177 xfs_perag_put(pag);
178 return -EFSCORRUPTED;
179 }
180
181
182 fsc->icount += pag->pagi_count;
183 fsc->ifree += pag->pagi_freecount;
184
185
186 fsc->fdblocks += pag->pagf_freeblks;
187 fsc->fdblocks += pag->pagf_flcount;
188 fsc->fdblocks += pag->pagf_btreeblks;
189
190
191
192
193
194 fsc->fdblocks -= pag->pag_meta_resv.ar_reserved;
195 fsc->fdblocks -= pag->pag_rmapbt_resv.ar_orig_reserved;
196
197 xfs_perag_put(pag);
198
199 if (fatal_signal_pending(current))
200 break;
201 }
202
203
204
205
206
207 fsc->fdblocks -= mp->m_resblks_avail;
208
209
210
211
212
213
214 delayed = percpu_counter_sum(&mp->m_delalloc_blks);
215 fsc->fdblocks -= delayed;
216
217 trace_xchk_fscounters_calc(mp, fsc->icount, fsc->ifree, fsc->fdblocks,
218 delayed);
219
220
221
222 if (fsc->icount < fsc->icount_min || fsc->icount > fsc->icount_max ||
223 fsc->fdblocks > mp->m_sb.sb_dblocks ||
224 fsc->ifree > fsc->icount_max)
225 return -EFSCORRUPTED;
226
227
228
229
230
231
232 if (fsc->ifree > fsc->icount) {
233 if (tries--)
234 goto retry;
235 xchk_set_incomplete(sc);
236 return 0;
237 }
238
239 return 0;
240 }
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255 static inline bool
256 xchk_fscount_within_range(
257 struct xfs_scrub *sc,
258 const int64_t old_value,
259 struct percpu_counter *counter,
260 uint64_t expected)
261 {
262 int64_t min_value, max_value;
263 int64_t curr_value = percpu_counter_sum(counter);
264
265 trace_xchk_fscounters_within_range(sc->mp, expected, curr_value,
266 old_value);
267
268
269 if (curr_value < 0)
270 return false;
271
272
273 if (curr_value == expected)
274 return true;
275
276 min_value = min(old_value, curr_value);
277 max_value = max(old_value, curr_value);
278
279
280 if (expected >= min_value && expected <= max_value)
281 return true;
282
283
284
285
286
287
288
289
290
291
292
293 if (max_value - min_value >= XCHK_FSCOUNT_MIN_VARIANCE) {
294 xchk_set_incomplete(sc);
295 return true;
296 }
297
298 return false;
299 }
300
301
302 int
303 xchk_fscounters(
304 struct xfs_scrub *sc)
305 {
306 struct xfs_mount *mp = sc->mp;
307 struct xchk_fscounters *fsc = sc->buf;
308 int64_t icount, ifree, fdblocks;
309 int error;
310
311
312 icount = percpu_counter_sum(&mp->m_icount);
313 ifree = percpu_counter_sum(&mp->m_ifree);
314 fdblocks = percpu_counter_sum(&mp->m_fdblocks);
315
316
317 if (icount < 0 || ifree < 0 || fdblocks < 0)
318 xchk_set_corrupt(sc);
319
320
321 if (icount < fsc->icount_min || icount > fsc->icount_max)
322 xchk_set_corrupt(sc);
323
324
325 if (fdblocks > mp->m_sb.sb_dblocks)
326 xchk_set_corrupt(sc);
327
328
329
330
331
332 if (ifree > icount && ifree - icount > XCHK_FSCOUNT_MIN_VARIANCE)
333 xchk_set_corrupt(sc);
334
335
336 error = xchk_fscount_aggregate_agcounts(sc, fsc);
337 if (!xchk_process_error(sc, 0, XFS_SB_BLOCK(mp), &error))
338 return error;
339 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_INCOMPLETE)
340 return 0;
341
342
343 if (!xchk_fscount_within_range(sc, icount, &mp->m_icount, fsc->icount))
344 xchk_set_corrupt(sc);
345
346 if (!xchk_fscount_within_range(sc, ifree, &mp->m_ifree, fsc->ifree))
347 xchk_set_corrupt(sc);
348
349 if (!xchk_fscount_within_range(sc, fdblocks, &mp->m_fdblocks,
350 fsc->fdblocks))
351 xchk_set_corrupt(sc);
352
353 return 0;
354 }