1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include "xfs.h"
21#include "xfs_fs.h"
22#include "xfs_shared.h"
23#include "xfs_format.h"
24#include "xfs_trans_resv.h"
25#include "xfs_mount.h"
26#include "xfs_defer.h"
27#include "xfs_btree.h"
28#include "xfs_bit.h"
29#include "xfs_log_format.h"
30#include "xfs_trans.h"
31#include "xfs_sb.h"
32#include "xfs_inode.h"
33#include "xfs_alloc.h"
34#include "xfs_ialloc.h"
35#include "xfs_rmap.h"
36#include "scrub/xfs_scrub.h"
37#include "scrub/scrub.h"
38#include "scrub/common.h"
39#include "scrub/trace.h"
40
41
42
43
44
45int
46xfs_scrub_walk_agfl(
47 struct xfs_scrub_context *sc,
48 int (*fn)(struct xfs_scrub_context *,
49 xfs_agblock_t bno, void *),
50 void *priv)
51{
52 struct xfs_agf *agf;
53 __be32 *agfl_bno;
54 struct xfs_mount *mp = sc->mp;
55 unsigned int flfirst;
56 unsigned int fllast;
57 int i;
58 int error;
59
60 agf = XFS_BUF_TO_AGF(sc->sa.agf_bp);
61 agfl_bno = XFS_BUF_TO_AGFL_BNO(mp, sc->sa.agfl_bp);
62 flfirst = be32_to_cpu(agf->agf_flfirst);
63 fllast = be32_to_cpu(agf->agf_fllast);
64
65
66 if (agf->agf_flcount == cpu_to_be32(0))
67 return 0;
68
69
70 if (fllast >= flfirst) {
71 for (i = flfirst; i <= fllast; i++) {
72 error = fn(sc, be32_to_cpu(agfl_bno[i]), priv);
73 if (error)
74 return error;
75 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
76 return error;
77 }
78
79 return 0;
80 }
81
82
83 for (i = flfirst; i < XFS_AGFL_SIZE(mp); i++) {
84 error = fn(sc, be32_to_cpu(agfl_bno[i]), priv);
85 if (error)
86 return error;
87 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
88 return error;
89 }
90
91
92 for (i = 0; i <= fllast; i++) {
93 error = fn(sc, be32_to_cpu(agfl_bno[i]), priv);
94 if (error)
95 return error;
96 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
97 return error;
98 }
99
100 return 0;
101}
102
103
104
105
106STATIC void
107xfs_scrub_superblock_xref(
108 struct xfs_scrub_context *sc,
109 struct xfs_buf *bp)
110{
111 struct xfs_owner_info oinfo;
112 struct xfs_mount *mp = sc->mp;
113 xfs_agnumber_t agno = sc->sm->sm_agno;
114 xfs_agblock_t agbno;
115 int error;
116
117 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
118 return;
119
120 agbno = XFS_SB_BLOCK(mp);
121
122 error = xfs_scrub_ag_init(sc, agno, &sc->sa);
123 if (!xfs_scrub_xref_process_error(sc, agno, agbno, &error))
124 return;
125
126 xfs_scrub_xref_is_used_space(sc, agbno, 1);
127 xfs_scrub_xref_is_not_inode_chunk(sc, agbno, 1);
128 xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_FS);
129 xfs_scrub_xref_is_owned_by(sc, agbno, 1, &oinfo);
130 xfs_scrub_xref_is_not_shared(sc, agbno, 1);
131
132
133}
134
135
136
137
138
139
140
141
142
143int
144xfs_scrub_superblock(
145 struct xfs_scrub_context *sc)
146{
147 struct xfs_mount *mp = sc->mp;
148 struct xfs_buf *bp;
149 struct xfs_dsb *sb;
150 xfs_agnumber_t agno;
151 uint32_t v2_ok;
152 __be32 features_mask;
153 int error;
154 __be16 vernum_mask;
155
156 agno = sc->sm->sm_agno;
157 if (agno == 0)
158 return 0;
159
160 error = xfs_trans_read_buf(mp, sc->tp, mp->m_ddev_targp,
161 XFS_AGB_TO_DADDR(mp, agno, XFS_SB_BLOCK(mp)),
162 XFS_FSS_TO_BB(mp, 1), 0, &bp, &xfs_sb_buf_ops);
163
164
165
166
167
168
169
170
171 switch (error) {
172 case -EINVAL:
173 case -ENOSYS:
174 case -EFBIG:
175 error = -EFSCORRUPTED;
176 default:
177 break;
178 }
179 if (!xfs_scrub_process_error(sc, agno, XFS_SB_BLOCK(mp), &error))
180 return error;
181
182 sb = XFS_BUF_TO_SBP(bp);
183
184
185
186
187
188
189
190 if (sb->sb_blocksize != cpu_to_be32(mp->m_sb.sb_blocksize))
191 xfs_scrub_block_set_corrupt(sc, bp);
192
193 if (sb->sb_dblocks != cpu_to_be64(mp->m_sb.sb_dblocks))
194 xfs_scrub_block_set_corrupt(sc, bp);
195
196 if (sb->sb_rblocks != cpu_to_be64(mp->m_sb.sb_rblocks))
197 xfs_scrub_block_set_corrupt(sc, bp);
198
199 if (sb->sb_rextents != cpu_to_be64(mp->m_sb.sb_rextents))
200 xfs_scrub_block_set_corrupt(sc, bp);
201
202 if (!uuid_equal(&sb->sb_uuid, &mp->m_sb.sb_uuid))
203 xfs_scrub_block_set_preen(sc, bp);
204
205 if (sb->sb_logstart != cpu_to_be64(mp->m_sb.sb_logstart))
206 xfs_scrub_block_set_corrupt(sc, bp);
207
208 if (sb->sb_rootino != cpu_to_be64(mp->m_sb.sb_rootino))
209 xfs_scrub_block_set_preen(sc, bp);
210
211 if (sb->sb_rbmino != cpu_to_be64(mp->m_sb.sb_rbmino))
212 xfs_scrub_block_set_preen(sc, bp);
213
214 if (sb->sb_rsumino != cpu_to_be64(mp->m_sb.sb_rsumino))
215 xfs_scrub_block_set_preen(sc, bp);
216
217 if (sb->sb_rextsize != cpu_to_be32(mp->m_sb.sb_rextsize))
218 xfs_scrub_block_set_corrupt(sc, bp);
219
220 if (sb->sb_agblocks != cpu_to_be32(mp->m_sb.sb_agblocks))
221 xfs_scrub_block_set_corrupt(sc, bp);
222
223 if (sb->sb_agcount != cpu_to_be32(mp->m_sb.sb_agcount))
224 xfs_scrub_block_set_corrupt(sc, bp);
225
226 if (sb->sb_rbmblocks != cpu_to_be32(mp->m_sb.sb_rbmblocks))
227 xfs_scrub_block_set_corrupt(sc, bp);
228
229 if (sb->sb_logblocks != cpu_to_be32(mp->m_sb.sb_logblocks))
230 xfs_scrub_block_set_corrupt(sc, bp);
231
232
233 vernum_mask = cpu_to_be16(~XFS_SB_VERSION_OKBITS |
234 XFS_SB_VERSION_NUMBITS |
235 XFS_SB_VERSION_ALIGNBIT |
236 XFS_SB_VERSION_DALIGNBIT |
237 XFS_SB_VERSION_SHAREDBIT |
238 XFS_SB_VERSION_LOGV2BIT |
239 XFS_SB_VERSION_SECTORBIT |
240 XFS_SB_VERSION_EXTFLGBIT |
241 XFS_SB_VERSION_DIRV2BIT);
242 if ((sb->sb_versionnum & vernum_mask) !=
243 (cpu_to_be16(mp->m_sb.sb_versionnum) & vernum_mask))
244 xfs_scrub_block_set_corrupt(sc, bp);
245
246
247 vernum_mask = cpu_to_be16(XFS_SB_VERSION_ATTRBIT |
248 XFS_SB_VERSION_NLINKBIT |
249 XFS_SB_VERSION_QUOTABIT);
250 if ((sb->sb_versionnum & vernum_mask) !=
251 (cpu_to_be16(mp->m_sb.sb_versionnum) & vernum_mask))
252 xfs_scrub_block_set_preen(sc, bp);
253
254 if (sb->sb_sectsize != cpu_to_be16(mp->m_sb.sb_sectsize))
255 xfs_scrub_block_set_corrupt(sc, bp);
256
257 if (sb->sb_inodesize != cpu_to_be16(mp->m_sb.sb_inodesize))
258 xfs_scrub_block_set_corrupt(sc, bp);
259
260 if (sb->sb_inopblock != cpu_to_be16(mp->m_sb.sb_inopblock))
261 xfs_scrub_block_set_corrupt(sc, bp);
262
263 if (memcmp(sb->sb_fname, mp->m_sb.sb_fname, sizeof(sb->sb_fname)))
264 xfs_scrub_block_set_preen(sc, bp);
265
266 if (sb->sb_blocklog != mp->m_sb.sb_blocklog)
267 xfs_scrub_block_set_corrupt(sc, bp);
268
269 if (sb->sb_sectlog != mp->m_sb.sb_sectlog)
270 xfs_scrub_block_set_corrupt(sc, bp);
271
272 if (sb->sb_inodelog != mp->m_sb.sb_inodelog)
273 xfs_scrub_block_set_corrupt(sc, bp);
274
275 if (sb->sb_inopblog != mp->m_sb.sb_inopblog)
276 xfs_scrub_block_set_corrupt(sc, bp);
277
278 if (sb->sb_agblklog != mp->m_sb.sb_agblklog)
279 xfs_scrub_block_set_corrupt(sc, bp);
280
281 if (sb->sb_rextslog != mp->m_sb.sb_rextslog)
282 xfs_scrub_block_set_corrupt(sc, bp);
283
284 if (sb->sb_imax_pct != mp->m_sb.sb_imax_pct)
285 xfs_scrub_block_set_preen(sc, bp);
286
287
288
289
290
291
292 if (sb->sb_uquotino != cpu_to_be64(mp->m_sb.sb_uquotino))
293 xfs_scrub_block_set_preen(sc, bp);
294
295 if (sb->sb_gquotino != cpu_to_be64(mp->m_sb.sb_gquotino))
296 xfs_scrub_block_set_preen(sc, bp);
297
298
299
300
301
302
303 if (sb->sb_flags != mp->m_sb.sb_flags)
304 xfs_scrub_block_set_corrupt(sc, bp);
305
306 if (sb->sb_shared_vn != mp->m_sb.sb_shared_vn)
307 xfs_scrub_block_set_corrupt(sc, bp);
308
309 if (sb->sb_inoalignmt != cpu_to_be32(mp->m_sb.sb_inoalignmt))
310 xfs_scrub_block_set_corrupt(sc, bp);
311
312 if (sb->sb_unit != cpu_to_be32(mp->m_sb.sb_unit))
313 xfs_scrub_block_set_preen(sc, bp);
314
315 if (sb->sb_width != cpu_to_be32(mp->m_sb.sb_width))
316 xfs_scrub_block_set_preen(sc, bp);
317
318 if (sb->sb_dirblklog != mp->m_sb.sb_dirblklog)
319 xfs_scrub_block_set_corrupt(sc, bp);
320
321 if (sb->sb_logsectlog != mp->m_sb.sb_logsectlog)
322 xfs_scrub_block_set_corrupt(sc, bp);
323
324 if (sb->sb_logsectsize != cpu_to_be16(mp->m_sb.sb_logsectsize))
325 xfs_scrub_block_set_corrupt(sc, bp);
326
327 if (sb->sb_logsunit != cpu_to_be32(mp->m_sb.sb_logsunit))
328 xfs_scrub_block_set_corrupt(sc, bp);
329
330
331 if (!xfs_sb_version_hasmorebits(&mp->m_sb)) {
332 if (sb->sb_features2 != 0)
333 xfs_scrub_block_set_corrupt(sc, bp);
334 } else {
335 v2_ok = XFS_SB_VERSION2_OKBITS;
336 if (XFS_SB_VERSION_NUM(&mp->m_sb) >= XFS_SB_VERSION_5)
337 v2_ok |= XFS_SB_VERSION2_CRCBIT;
338
339 if (!!(sb->sb_features2 & cpu_to_be32(~v2_ok)))
340 xfs_scrub_block_set_corrupt(sc, bp);
341
342 if (sb->sb_features2 != sb->sb_bad_features2)
343 xfs_scrub_block_set_preen(sc, bp);
344 }
345
346
347 features_mask = cpu_to_be32(XFS_SB_VERSION2_LAZYSBCOUNTBIT |
348 XFS_SB_VERSION2_PROJID32BIT |
349 XFS_SB_VERSION2_CRCBIT |
350 XFS_SB_VERSION2_FTYPE);
351 if ((sb->sb_features2 & features_mask) !=
352 (cpu_to_be32(mp->m_sb.sb_features2) & features_mask))
353 xfs_scrub_block_set_corrupt(sc, bp);
354
355
356 features_mask = cpu_to_be32(XFS_SB_VERSION2_ATTR2BIT);
357 if ((sb->sb_features2 & features_mask) !=
358 (cpu_to_be32(mp->m_sb.sb_features2) & features_mask))
359 xfs_scrub_block_set_corrupt(sc, bp);
360
361 if (!xfs_sb_version_hascrc(&mp->m_sb)) {
362
363 if (memchr_inv(&sb->sb_features_compat, 0,
364 sizeof(struct xfs_dsb) -
365 offsetof(struct xfs_dsb, sb_features_compat)))
366 xfs_scrub_block_set_corrupt(sc, bp);
367 } else {
368
369 features_mask = cpu_to_be32(XFS_SB_FEAT_COMPAT_UNKNOWN);
370 if ((sb->sb_features_compat & features_mask) !=
371 (cpu_to_be32(mp->m_sb.sb_features_compat) & features_mask))
372 xfs_scrub_block_set_corrupt(sc, bp);
373
374
375 features_mask = cpu_to_be32(XFS_SB_FEAT_RO_COMPAT_UNKNOWN |
376 XFS_SB_FEAT_RO_COMPAT_FINOBT |
377 XFS_SB_FEAT_RO_COMPAT_RMAPBT |
378 XFS_SB_FEAT_RO_COMPAT_REFLINK);
379 if ((sb->sb_features_ro_compat & features_mask) !=
380 (cpu_to_be32(mp->m_sb.sb_features_ro_compat) &
381 features_mask))
382 xfs_scrub_block_set_corrupt(sc, bp);
383
384
385 features_mask = cpu_to_be32(XFS_SB_FEAT_INCOMPAT_UNKNOWN |
386 XFS_SB_FEAT_INCOMPAT_FTYPE |
387 XFS_SB_FEAT_INCOMPAT_SPINODES |
388 XFS_SB_FEAT_INCOMPAT_META_UUID);
389 if ((sb->sb_features_incompat & features_mask) !=
390 (cpu_to_be32(mp->m_sb.sb_features_incompat) &
391 features_mask))
392 xfs_scrub_block_set_corrupt(sc, bp);
393
394
395 features_mask = cpu_to_be32(XFS_SB_FEAT_INCOMPAT_LOG_UNKNOWN);
396 if ((sb->sb_features_log_incompat & features_mask) !=
397 (cpu_to_be32(mp->m_sb.sb_features_log_incompat) &
398 features_mask))
399 xfs_scrub_block_set_corrupt(sc, bp);
400
401
402
403 if (sb->sb_spino_align != cpu_to_be32(mp->m_sb.sb_spino_align))
404 xfs_scrub_block_set_corrupt(sc, bp);
405
406 if (sb->sb_pquotino != cpu_to_be64(mp->m_sb.sb_pquotino))
407 xfs_scrub_block_set_preen(sc, bp);
408
409
410 }
411
412 if (xfs_sb_version_hasmetauuid(&mp->m_sb)) {
413
414 if (!uuid_equal(&sb->sb_meta_uuid, &mp->m_sb.sb_meta_uuid))
415 xfs_scrub_block_set_corrupt(sc, bp);
416 }
417
418
419 if (memchr_inv(sb + 1, 0,
420 BBTOB(bp->b_length) - sizeof(struct xfs_dsb)))
421 xfs_scrub_block_set_corrupt(sc, bp);
422
423 xfs_scrub_superblock_xref(sc, bp);
424
425 return error;
426}
427
428
429
430
431STATIC int
432xfs_scrub_agf_record_bno_lengths(
433 struct xfs_btree_cur *cur,
434 struct xfs_alloc_rec_incore *rec,
435 void *priv)
436{
437 xfs_extlen_t *blocks = priv;
438
439 (*blocks) += rec->ar_blockcount;
440 return 0;
441}
442
443
444static inline void
445xfs_scrub_agf_xref_freeblks(
446 struct xfs_scrub_context *sc)
447{
448 struct xfs_agf *agf = XFS_BUF_TO_AGF(sc->sa.agf_bp);
449 xfs_extlen_t blocks = 0;
450 int error;
451
452 if (!sc->sa.bno_cur)
453 return;
454
455 error = xfs_alloc_query_all(sc->sa.bno_cur,
456 xfs_scrub_agf_record_bno_lengths, &blocks);
457 if (!xfs_scrub_should_check_xref(sc, &error, &sc->sa.bno_cur))
458 return;
459 if (blocks != be32_to_cpu(agf->agf_freeblks))
460 xfs_scrub_block_xref_set_corrupt(sc, sc->sa.agf_bp);
461}
462
463
464static inline void
465xfs_scrub_agf_xref_cntbt(
466 struct xfs_scrub_context *sc)
467{
468 struct xfs_agf *agf = XFS_BUF_TO_AGF(sc->sa.agf_bp);
469 xfs_agblock_t agbno;
470 xfs_extlen_t blocks;
471 int have;
472 int error;
473
474 if (!sc->sa.cnt_cur)
475 return;
476
477
478 error = xfs_alloc_lookup_le(sc->sa.cnt_cur, 0, -1U, &have);
479 if (!xfs_scrub_should_check_xref(sc, &error, &sc->sa.cnt_cur))
480 return;
481 if (!have) {
482 if (agf->agf_freeblks != be32_to_cpu(0))
483 xfs_scrub_block_xref_set_corrupt(sc, sc->sa.agf_bp);
484 return;
485 }
486
487
488 error = xfs_alloc_get_rec(sc->sa.cnt_cur, &agbno, &blocks, &have);
489 if (!xfs_scrub_should_check_xref(sc, &error, &sc->sa.cnt_cur))
490 return;
491 if (!have || blocks != be32_to_cpu(agf->agf_longest))
492 xfs_scrub_block_xref_set_corrupt(sc, sc->sa.agf_bp);
493}
494
495
496STATIC void
497xfs_scrub_agf_xref_btreeblks(
498 struct xfs_scrub_context *sc)
499{
500 struct xfs_agf *agf = XFS_BUF_TO_AGF(sc->sa.agf_bp);
501 struct xfs_mount *mp = sc->mp;
502 xfs_agblock_t blocks;
503 xfs_agblock_t btreeblks;
504 int error;
505
506
507 if (sc->sa.rmap_cur) {
508 error = xfs_btree_count_blocks(sc->sa.rmap_cur, &blocks);
509 if (!xfs_scrub_should_check_xref(sc, &error, &sc->sa.rmap_cur))
510 return;
511 btreeblks = blocks - 1;
512 if (blocks != be32_to_cpu(agf->agf_rmap_blocks))
513 xfs_scrub_block_xref_set_corrupt(sc, sc->sa.agf_bp);
514 } else {
515 btreeblks = 0;
516 }
517
518
519
520
521
522 if ((xfs_sb_version_hasrmapbt(&mp->m_sb) && !sc->sa.rmap_cur) ||
523 !sc->sa.bno_cur || !sc->sa.cnt_cur)
524 return;
525
526
527 error = xfs_btree_count_blocks(sc->sa.bno_cur, &blocks);
528 if (!xfs_scrub_should_check_xref(sc, &error, &sc->sa.bno_cur))
529 return;
530 btreeblks += blocks - 1;
531
532 error = xfs_btree_count_blocks(sc->sa.cnt_cur, &blocks);
533 if (!xfs_scrub_should_check_xref(sc, &error, &sc->sa.cnt_cur))
534 return;
535 btreeblks += blocks - 1;
536
537 if (btreeblks != be32_to_cpu(agf->agf_btreeblks))
538 xfs_scrub_block_xref_set_corrupt(sc, sc->sa.agf_bp);
539}
540
541
542static inline void
543xfs_scrub_agf_xref_refcblks(
544 struct xfs_scrub_context *sc)
545{
546 struct xfs_agf *agf = XFS_BUF_TO_AGF(sc->sa.agf_bp);
547 xfs_agblock_t blocks;
548 int error;
549
550 if (!sc->sa.refc_cur)
551 return;
552
553 error = xfs_btree_count_blocks(sc->sa.refc_cur, &blocks);
554 if (!xfs_scrub_should_check_xref(sc, &error, &sc->sa.refc_cur))
555 return;
556 if (blocks != be32_to_cpu(agf->agf_refcount_blocks))
557 xfs_scrub_block_xref_set_corrupt(sc, sc->sa.agf_bp);
558}
559
560
561STATIC void
562xfs_scrub_agf_xref(
563 struct xfs_scrub_context *sc)
564{
565 struct xfs_owner_info oinfo;
566 struct xfs_mount *mp = sc->mp;
567 xfs_agblock_t agbno;
568 int error;
569
570 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
571 return;
572
573 agbno = XFS_AGF_BLOCK(mp);
574
575 error = xfs_scrub_ag_btcur_init(sc, &sc->sa);
576 if (error)
577 return;
578
579 xfs_scrub_xref_is_used_space(sc, agbno, 1);
580 xfs_scrub_agf_xref_freeblks(sc);
581 xfs_scrub_agf_xref_cntbt(sc);
582 xfs_scrub_xref_is_not_inode_chunk(sc, agbno, 1);
583 xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_FS);
584 xfs_scrub_xref_is_owned_by(sc, agbno, 1, &oinfo);
585 xfs_scrub_agf_xref_btreeblks(sc);
586 xfs_scrub_xref_is_not_shared(sc, agbno, 1);
587 xfs_scrub_agf_xref_refcblks(sc);
588
589
590}
591
592
593int
594xfs_scrub_agf(
595 struct xfs_scrub_context *sc)
596{
597 struct xfs_mount *mp = sc->mp;
598 struct xfs_agf *agf;
599 xfs_agnumber_t agno;
600 xfs_agblock_t agbno;
601 xfs_agblock_t eoag;
602 xfs_agblock_t agfl_first;
603 xfs_agblock_t agfl_last;
604 xfs_agblock_t agfl_count;
605 xfs_agblock_t fl_count;
606 int level;
607 int error = 0;
608
609 agno = sc->sa.agno = sc->sm->sm_agno;
610 error = xfs_scrub_ag_read_headers(sc, agno, &sc->sa.agi_bp,
611 &sc->sa.agf_bp, &sc->sa.agfl_bp);
612 if (!xfs_scrub_process_error(sc, agno, XFS_AGF_BLOCK(sc->mp), &error))
613 goto out;
614 xfs_scrub_buffer_recheck(sc, sc->sa.agf_bp);
615
616 agf = XFS_BUF_TO_AGF(sc->sa.agf_bp);
617
618
619 eoag = be32_to_cpu(agf->agf_length);
620 if (eoag != xfs_ag_block_count(mp, agno))
621 xfs_scrub_block_set_corrupt(sc, sc->sa.agf_bp);
622
623
624 agbno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_BNO]);
625 if (!xfs_verify_agbno(mp, agno, agbno))
626 xfs_scrub_block_set_corrupt(sc, sc->sa.agf_bp);
627
628 agbno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_CNT]);
629 if (!xfs_verify_agbno(mp, agno, agbno))
630 xfs_scrub_block_set_corrupt(sc, sc->sa.agf_bp);
631
632 level = be32_to_cpu(agf->agf_levels[XFS_BTNUM_BNO]);
633 if (level <= 0 || level > XFS_BTREE_MAXLEVELS)
634 xfs_scrub_block_set_corrupt(sc, sc->sa.agf_bp);
635
636 level = be32_to_cpu(agf->agf_levels[XFS_BTNUM_CNT]);
637 if (level <= 0 || level > XFS_BTREE_MAXLEVELS)
638 xfs_scrub_block_set_corrupt(sc, sc->sa.agf_bp);
639
640 if (xfs_sb_version_hasrmapbt(&mp->m_sb)) {
641 agbno = be32_to_cpu(agf->agf_roots[XFS_BTNUM_RMAP]);
642 if (!xfs_verify_agbno(mp, agno, agbno))
643 xfs_scrub_block_set_corrupt(sc, sc->sa.agf_bp);
644
645 level = be32_to_cpu(agf->agf_levels[XFS_BTNUM_RMAP]);
646 if (level <= 0 || level > XFS_BTREE_MAXLEVELS)
647 xfs_scrub_block_set_corrupt(sc, sc->sa.agf_bp);
648 }
649
650 if (xfs_sb_version_hasreflink(&mp->m_sb)) {
651 agbno = be32_to_cpu(agf->agf_refcount_root);
652 if (!xfs_verify_agbno(mp, agno, agbno))
653 xfs_scrub_block_set_corrupt(sc, sc->sa.agf_bp);
654
655 level = be32_to_cpu(agf->agf_refcount_level);
656 if (level <= 0 || level > XFS_BTREE_MAXLEVELS)
657 xfs_scrub_block_set_corrupt(sc, sc->sa.agf_bp);
658 }
659
660
661 agfl_first = be32_to_cpu(agf->agf_flfirst);
662 agfl_last = be32_to_cpu(agf->agf_fllast);
663 agfl_count = be32_to_cpu(agf->agf_flcount);
664 if (agfl_last > agfl_first)
665 fl_count = agfl_last - agfl_first + 1;
666 else
667 fl_count = XFS_AGFL_SIZE(mp) - agfl_first + agfl_last + 1;
668 if (agfl_count != 0 && fl_count != agfl_count)
669 xfs_scrub_block_set_corrupt(sc, sc->sa.agf_bp);
670
671 xfs_scrub_agf_xref(sc);
672out:
673 return error;
674}
675
676
677
678struct xfs_scrub_agfl_info {
679 struct xfs_owner_info oinfo;
680 unsigned int sz_entries;
681 unsigned int nr_entries;
682 xfs_agblock_t *entries;
683};
684
685
686STATIC void
687xfs_scrub_agfl_block_xref(
688 struct xfs_scrub_context *sc,
689 xfs_agblock_t agbno,
690 struct xfs_owner_info *oinfo)
691{
692 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
693 return;
694
695 xfs_scrub_xref_is_used_space(sc, agbno, 1);
696 xfs_scrub_xref_is_not_inode_chunk(sc, agbno, 1);
697 xfs_scrub_xref_is_owned_by(sc, agbno, 1, oinfo);
698 xfs_scrub_xref_is_not_shared(sc, agbno, 1);
699}
700
701
702STATIC int
703xfs_scrub_agfl_block(
704 struct xfs_scrub_context *sc,
705 xfs_agblock_t agbno,
706 void *priv)
707{
708 struct xfs_mount *mp = sc->mp;
709 struct xfs_scrub_agfl_info *sai = priv;
710 xfs_agnumber_t agno = sc->sa.agno;
711
712 if (xfs_verify_agbno(mp, agno, agbno) &&
713 sai->nr_entries < sai->sz_entries)
714 sai->entries[sai->nr_entries++] = agbno;
715 else
716 xfs_scrub_block_set_corrupt(sc, sc->sa.agfl_bp);
717
718 xfs_scrub_agfl_block_xref(sc, agbno, priv);
719
720 return 0;
721}
722
723static int
724xfs_scrub_agblock_cmp(
725 const void *pa,
726 const void *pb)
727{
728 const xfs_agblock_t *a = pa;
729 const xfs_agblock_t *b = pb;
730
731 return (int)*a - (int)*b;
732}
733
734
735STATIC void
736xfs_scrub_agfl_xref(
737 struct xfs_scrub_context *sc)
738{
739 struct xfs_owner_info oinfo;
740 struct xfs_mount *mp = sc->mp;
741 xfs_agblock_t agbno;
742 int error;
743
744 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
745 return;
746
747 agbno = XFS_AGFL_BLOCK(mp);
748
749 error = xfs_scrub_ag_btcur_init(sc, &sc->sa);
750 if (error)
751 return;
752
753 xfs_scrub_xref_is_used_space(sc, agbno, 1);
754 xfs_scrub_xref_is_not_inode_chunk(sc, agbno, 1);
755 xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_FS);
756 xfs_scrub_xref_is_owned_by(sc, agbno, 1, &oinfo);
757 xfs_scrub_xref_is_not_shared(sc, agbno, 1);
758
759
760
761
762
763}
764
765
766int
767xfs_scrub_agfl(
768 struct xfs_scrub_context *sc)
769{
770 struct xfs_scrub_agfl_info sai;
771 struct xfs_agf *agf;
772 xfs_agnumber_t agno;
773 unsigned int agflcount;
774 unsigned int i;
775 int error;
776
777 agno = sc->sa.agno = sc->sm->sm_agno;
778 error = xfs_scrub_ag_read_headers(sc, agno, &sc->sa.agi_bp,
779 &sc->sa.agf_bp, &sc->sa.agfl_bp);
780 if (!xfs_scrub_process_error(sc, agno, XFS_AGFL_BLOCK(sc->mp), &error))
781 goto out;
782 if (!sc->sa.agf_bp)
783 return -EFSCORRUPTED;
784 xfs_scrub_buffer_recheck(sc, sc->sa.agfl_bp);
785
786 xfs_scrub_agfl_xref(sc);
787
788 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
789 goto out;
790
791
792 agf = XFS_BUF_TO_AGF(sc->sa.agf_bp);
793 agflcount = be32_to_cpu(agf->agf_flcount);
794 if (agflcount > XFS_AGFL_SIZE(sc->mp)) {
795 xfs_scrub_block_set_corrupt(sc, sc->sa.agf_bp);
796 goto out;
797 }
798 memset(&sai, 0, sizeof(sai));
799 sai.sz_entries = agflcount;
800 sai.entries = kmem_zalloc(sizeof(xfs_agblock_t) * agflcount, KM_NOFS);
801 if (!sai.entries) {
802 error = -ENOMEM;
803 goto out;
804 }
805
806
807 xfs_rmap_ag_owner(&sai.oinfo, XFS_RMAP_OWN_AG);
808 error = xfs_scrub_walk_agfl(sc, xfs_scrub_agfl_block, &sai);
809 if (error)
810 goto out_free;
811
812 if (agflcount != sai.nr_entries) {
813 xfs_scrub_block_set_corrupt(sc, sc->sa.agf_bp);
814 goto out_free;
815 }
816
817
818 sort(sai.entries, sai.nr_entries, sizeof(sai.entries[0]),
819 xfs_scrub_agblock_cmp, NULL);
820 for (i = 1; i < sai.nr_entries; i++) {
821 if (sai.entries[i] == sai.entries[i - 1]) {
822 xfs_scrub_block_set_corrupt(sc, sc->sa.agf_bp);
823 break;
824 }
825 }
826
827out_free:
828 kmem_free(sai.entries);
829out:
830 return error;
831}
832
833
834
835
836static inline void
837xfs_scrub_agi_xref_icounts(
838 struct xfs_scrub_context *sc)
839{
840 struct xfs_agi *agi = XFS_BUF_TO_AGI(sc->sa.agi_bp);
841 xfs_agino_t icount;
842 xfs_agino_t freecount;
843 int error;
844
845 if (!sc->sa.ino_cur)
846 return;
847
848 error = xfs_ialloc_count_inodes(sc->sa.ino_cur, &icount, &freecount);
849 if (!xfs_scrub_should_check_xref(sc, &error, &sc->sa.ino_cur))
850 return;
851 if (be32_to_cpu(agi->agi_count) != icount ||
852 be32_to_cpu(agi->agi_freecount) != freecount)
853 xfs_scrub_block_xref_set_corrupt(sc, sc->sa.agi_bp);
854}
855
856
857STATIC void
858xfs_scrub_agi_xref(
859 struct xfs_scrub_context *sc)
860{
861 struct xfs_owner_info oinfo;
862 struct xfs_mount *mp = sc->mp;
863 xfs_agblock_t agbno;
864 int error;
865
866 if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
867 return;
868
869 agbno = XFS_AGI_BLOCK(mp);
870
871 error = xfs_scrub_ag_btcur_init(sc, &sc->sa);
872 if (error)
873 return;
874
875 xfs_scrub_xref_is_used_space(sc, agbno, 1);
876 xfs_scrub_xref_is_not_inode_chunk(sc, agbno, 1);
877 xfs_scrub_agi_xref_icounts(sc);
878 xfs_rmap_ag_owner(&oinfo, XFS_RMAP_OWN_FS);
879 xfs_scrub_xref_is_owned_by(sc, agbno, 1, &oinfo);
880 xfs_scrub_xref_is_not_shared(sc, agbno, 1);
881
882
883}
884
885
886int
887xfs_scrub_agi(
888 struct xfs_scrub_context *sc)
889{
890 struct xfs_mount *mp = sc->mp;
891 struct xfs_agi *agi;
892 xfs_agnumber_t agno;
893 xfs_agblock_t agbno;
894 xfs_agblock_t eoag;
895 xfs_agino_t agino;
896 xfs_agino_t first_agino;
897 xfs_agino_t last_agino;
898 xfs_agino_t icount;
899 int i;
900 int level;
901 int error = 0;
902
903 agno = sc->sa.agno = sc->sm->sm_agno;
904 error = xfs_scrub_ag_read_headers(sc, agno, &sc->sa.agi_bp,
905 &sc->sa.agf_bp, &sc->sa.agfl_bp);
906 if (!xfs_scrub_process_error(sc, agno, XFS_AGI_BLOCK(sc->mp), &error))
907 goto out;
908 xfs_scrub_buffer_recheck(sc, sc->sa.agi_bp);
909
910 agi = XFS_BUF_TO_AGI(sc->sa.agi_bp);
911
912
913 eoag = be32_to_cpu(agi->agi_length);
914 if (eoag != xfs_ag_block_count(mp, agno))
915 xfs_scrub_block_set_corrupt(sc, sc->sa.agi_bp);
916
917
918 agbno = be32_to_cpu(agi->agi_root);
919 if (!xfs_verify_agbno(mp, agno, agbno))
920 xfs_scrub_block_set_corrupt(sc, sc->sa.agi_bp);
921
922 level = be32_to_cpu(agi->agi_level);
923 if (level <= 0 || level > XFS_BTREE_MAXLEVELS)
924 xfs_scrub_block_set_corrupt(sc, sc->sa.agi_bp);
925
926 if (xfs_sb_version_hasfinobt(&mp->m_sb)) {
927 agbno = be32_to_cpu(agi->agi_free_root);
928 if (!xfs_verify_agbno(mp, agno, agbno))
929 xfs_scrub_block_set_corrupt(sc, sc->sa.agi_bp);
930
931 level = be32_to_cpu(agi->agi_free_level);
932 if (level <= 0 || level > XFS_BTREE_MAXLEVELS)
933 xfs_scrub_block_set_corrupt(sc, sc->sa.agi_bp);
934 }
935
936
937 xfs_ialloc_agino_range(mp, agno, &first_agino, &last_agino);
938 icount = be32_to_cpu(agi->agi_count);
939 if (icount > last_agino - first_agino + 1 ||
940 icount < be32_to_cpu(agi->agi_freecount))
941 xfs_scrub_block_set_corrupt(sc, sc->sa.agi_bp);
942
943
944 agino = be32_to_cpu(agi->agi_newino);
945 if (agino != NULLAGINO && !xfs_verify_agino(mp, agno, agino))
946 xfs_scrub_block_set_corrupt(sc, sc->sa.agi_bp);
947
948 agino = be32_to_cpu(agi->agi_dirino);
949 if (agino != NULLAGINO && !xfs_verify_agino(mp, agno, agino))
950 xfs_scrub_block_set_corrupt(sc, sc->sa.agi_bp);
951
952
953 for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++) {
954 agino = be32_to_cpu(agi->agi_unlinked[i]);
955 if (agino == NULLAGINO)
956 continue;
957 if (!xfs_verify_agino(mp, agno, agino))
958 xfs_scrub_block_set_corrupt(sc, sc->sa.agi_bp);
959 }
960
961 if (agi->agi_pad32 != cpu_to_be32(0))
962 xfs_scrub_block_set_corrupt(sc, sc->sa.agi_bp);
963
964 xfs_scrub_agi_xref(sc);
965out:
966 return error;
967}
968