Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0-or-later
2 : /*
3 : * Copyright (C) 2017-2023 Oracle. All Rights Reserved.
4 : * Author: Darrick J. Wong <djwong@kernel.org>
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_btree.h"
13 : #include "xfs_log_format.h"
14 : #include "xfs_trans.h"
15 : #include "xfs_inode.h"
16 : #include "xfs_ialloc.h"
17 : #include "xfs_ialloc_btree.h"
18 : #include "xfs_icache.h"
19 : #include "xfs_rmap.h"
20 : #include "scrub/scrub.h"
21 : #include "scrub/common.h"
22 : #include "scrub/btree.h"
23 : #include "scrub/trace.h"
24 : #include "xfs_ag.h"
25 :
26 : /*
27 : * Set us up to scrub inode btrees.
28 : * If we detect a discrepancy between the inobt and the inode,
29 : * try again after forcing logged inode cores out to disk.
30 : */
31 : int
32 314384 : xchk_setup_ag_iallocbt(
33 : struct xfs_scrub *sc)
34 : {
35 314384 : if (xchk_need_intent_drain(sc))
36 5200 : xchk_fsgates_enable(sc, XCHK_FSGATES_DRAIN);
37 314384 : return xchk_setup_ag_btree(sc, sc->flags & XCHK_TRY_HARDER);
38 : }
39 :
40 : /* Inode btree scrubber. */
41 :
42 : struct xchk_iallocbt {
43 : /* Number of inodes we see while scanning inobt. */
44 : unsigned long long inodes;
45 :
46 : /* Expected next startino, for big block filesystems. */
47 : xfs_agino_t next_startino;
48 :
49 : /* Expected end of the current inode cluster. */
50 : xfs_agino_t next_cluster_ino;
51 : };
52 :
53 : /*
54 : * Does the finobt have a record for this inode with the same hole/free state?
55 : * This is a bit complicated because of the following:
56 : *
57 : * - The finobt need not have a record if all inodes in the inobt record are
58 : * allocated.
59 : * - The finobt need not have a record if all inodes in the inobt record are
60 : * free.
61 : * - The finobt need not have a record if the inobt record says this is a hole.
62 : * This likely doesn't happen in practice.
63 : */
64 : STATIC int
65 2883535273 : xchk_inobt_xref_finobt(
66 : struct xfs_scrub *sc,
67 : struct xfs_inobt_rec_incore *irec,
68 : xfs_agino_t agino,
69 : bool free,
70 : bool hole)
71 : {
72 2883535273 : struct xfs_inobt_rec_incore frec;
73 2883535273 : struct xfs_btree_cur *cur = sc->sa.fino_cur;
74 2883535273 : bool ffree, fhole;
75 2883535273 : unsigned int frec_idx, fhole_idx;
76 2883535273 : int has_record;
77 2883535273 : int error;
78 :
79 2883535273 : ASSERT(cur->bc_btnum == XFS_BTNUM_FINO);
80 :
81 2883535273 : error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &has_record);
82 2883659561 : if (error)
83 : return error;
84 2883659561 : if (!has_record)
85 2244969945 : goto no_record;
86 :
87 638689616 : error = xfs_inobt_get_rec(cur, &frec, &has_record);
88 638679344 : if (!has_record)
89 : return -EFSCORRUPTED;
90 :
91 638679344 : if (frec.ir_startino + XFS_INODES_PER_CHUNK <= agino)
92 627923688 : goto no_record;
93 :
94 : /* There's a finobt record; free and hole status must match. */
95 10755656 : frec_idx = agino - frec.ir_startino;
96 10755656 : ffree = frec.ir_free & (1ULL << frec_idx);
97 10755656 : fhole_idx = frec_idx / XFS_INODES_PER_HOLEMASK_BIT;
98 10755656 : fhole = frec.ir_holemask & (1U << fhole_idx);
99 :
100 10755656 : if (ffree != free)
101 0 : xchk_btree_xref_set_corrupt(sc, cur, 0);
102 10755656 : if (fhole != hole)
103 0 : xchk_btree_xref_set_corrupt(sc, cur, 0);
104 : return 0;
105 :
106 2872893633 : no_record:
107 : /* inobt record is fully allocated */
108 2872893633 : if (irec->ir_free == 0)
109 : return 0;
110 :
111 : /* inobt record is totally unallocated */
112 871700697 : if (irec->ir_free == XFS_INOBT_ALL_FREE)
113 : return 0;
114 :
115 : /* inobt record says this is a hole */
116 871700697 : if (hole)
117 : return 0;
118 :
119 : /* finobt doesn't care about allocated inodes */
120 871700697 : if (!free)
121 : return 0;
122 :
123 0 : xchk_btree_xref_set_corrupt(sc, cur, 0);
124 0 : return 0;
125 : }
126 :
127 : /*
128 : * Make sure that each inode of this part of an inobt record has the same
129 : * sparse and free status as the finobt.
130 : */
131 : STATIC void
132 249767583 : xchk_inobt_chunk_xref_finobt(
133 : struct xfs_scrub *sc,
134 : struct xfs_inobt_rec_incore *irec,
135 : xfs_agino_t agino,
136 : unsigned int nr_inodes)
137 : {
138 249767583 : xfs_agino_t i;
139 249767583 : unsigned int rec_idx;
140 249767583 : int error;
141 :
142 249767583 : ASSERT(sc->sm->sm_type == XFS_SCRUB_TYPE_INOBT);
143 :
144 249767583 : if (!sc->sa.fino_cur || xchk_skip_xref(sc->sm))
145 2 : return;
146 :
147 249767581 : for (i = agino, rec_idx = agino - irec->ir_startino;
148 3133362831 : i < agino + nr_inodes;
149 2883595250 : i++, rec_idx++) {
150 2883595832 : bool free, hole;
151 2883595832 : unsigned int hole_idx;
152 :
153 2883595832 : free = irec->ir_free & (1ULL << rec_idx);
154 2883595832 : hole_idx = rec_idx / XFS_INODES_PER_HOLEMASK_BIT;
155 2883595832 : hole = irec->ir_holemask & (1U << hole_idx);
156 :
157 2883595832 : error = xchk_inobt_xref_finobt(sc, irec, i, free, hole);
158 2883562527 : if (!xchk_should_check_xref(sc, &error, &sc->sa.fino_cur))
159 : return;
160 : }
161 : }
162 :
163 : /*
164 : * Does the inobt have a record for this inode with the same hole/free state?
165 : * The inobt must always have a record if there's a finobt record.
166 : */
167 : STATIC int
168 13535974 : xchk_finobt_xref_inobt(
169 : struct xfs_scrub *sc,
170 : struct xfs_inobt_rec_incore *frec,
171 : xfs_agino_t agino,
172 : bool ffree,
173 : bool fhole)
174 : {
175 13535974 : struct xfs_inobt_rec_incore irec;
176 13535974 : struct xfs_btree_cur *cur = sc->sa.ino_cur;
177 13535974 : bool free, hole;
178 13535974 : unsigned int rec_idx, hole_idx;
179 13535974 : int has_record;
180 13535974 : int error;
181 :
182 13535974 : ASSERT(cur->bc_btnum == XFS_BTNUM_INO);
183 :
184 13535974 : error = xfs_inobt_lookup(cur, agino, XFS_LOOKUP_LE, &has_record);
185 13536005 : if (error)
186 : return error;
187 13536005 : if (!has_record)
188 0 : goto no_record;
189 :
190 13536005 : error = xfs_inobt_get_rec(cur, &irec, &has_record);
191 13535942 : if (!has_record)
192 : return -EFSCORRUPTED;
193 :
194 13535942 : if (irec.ir_startino + XFS_INODES_PER_CHUNK <= agino)
195 0 : goto no_record;
196 :
197 : /* There's an inobt record; free and hole status must match. */
198 13535942 : rec_idx = agino - irec.ir_startino;
199 13535942 : free = irec.ir_free & (1ULL << rec_idx);
200 13535942 : hole_idx = rec_idx / XFS_INODES_PER_HOLEMASK_BIT;
201 13535942 : hole = irec.ir_holemask & (1U << hole_idx);
202 :
203 13535942 : if (ffree != free)
204 0 : xchk_btree_xref_set_corrupt(sc, cur, 0);
205 13535942 : if (fhole != hole)
206 0 : xchk_btree_xref_set_corrupt(sc, cur, 0);
207 : return 0;
208 :
209 0 : no_record:
210 : /* finobt should never have a record for which the inobt does not */
211 0 : xchk_btree_xref_set_corrupt(sc, cur, 0);
212 0 : return 0;
213 : }
214 :
215 : /*
216 : * Make sure that each inode of this part of an finobt record has the same
217 : * sparse and free status as the inobt.
218 : */
219 : STATIC void
220 722018 : xchk_finobt_chunk_xref_inobt(
221 : struct xfs_scrub *sc,
222 : struct xfs_inobt_rec_incore *frec,
223 : xfs_agino_t agino,
224 : unsigned int nr_inodes)
225 : {
226 722018 : xfs_agino_t i;
227 722018 : unsigned int rec_idx;
228 722018 : int error;
229 :
230 722018 : ASSERT(sc->sm->sm_type == XFS_SCRUB_TYPE_FINOBT);
231 :
232 722018 : if (!sc->sa.ino_cur || xchk_skip_xref(sc->sm))
233 0 : return;
234 :
235 722018 : for (i = agino, rec_idx = agino - frec->ir_startino;
236 14258027 : i < agino + nr_inodes;
237 13536009 : i++, rec_idx++) {
238 13536009 : bool ffree, fhole;
239 13536009 : unsigned int hole_idx;
240 :
241 13536009 : ffree = frec->ir_free & (1ULL << rec_idx);
242 13536009 : hole_idx = rec_idx / XFS_INODES_PER_HOLEMASK_BIT;
243 13536009 : fhole = frec->ir_holemask & (1U << hole_idx);
244 :
245 13536009 : error = xchk_finobt_xref_inobt(sc, frec, i, ffree, fhole);
246 13535964 : if (!xchk_should_check_xref(sc, &error, &sc->sa.ino_cur))
247 : return;
248 : }
249 : }
250 :
251 : /* Is this chunk worth checking and cross-referencing? */
252 : STATIC bool
253 250487580 : xchk_iallocbt_chunk(
254 : struct xchk_btree *bs,
255 : struct xfs_inobt_rec_incore *irec,
256 : xfs_agino_t agino,
257 : unsigned int nr_inodes)
258 : {
259 250487580 : struct xfs_scrub *sc = bs->sc;
260 250487580 : struct xfs_mount *mp = bs->cur->bc_mp;
261 250487580 : struct xfs_perag *pag = bs->cur->bc_ag.pag;
262 250487580 : xfs_agblock_t agbno;
263 250487580 : xfs_extlen_t len;
264 :
265 250487580 : agbno = XFS_AGINO_TO_AGBNO(mp, agino);
266 250487580 : len = XFS_B_TO_FSB(mp, nr_inodes * mp->m_sb.sb_inodesize);
267 :
268 250487580 : if (!xfs_verify_agbext(pag, agbno, len))
269 0 : xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
270 :
271 250487580 : if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
272 : return false;
273 :
274 250487672 : xchk_xref_is_used_space(sc, agbno, len);
275 250489652 : if (sc->sm->sm_type == XFS_SCRUB_TYPE_INOBT)
276 249767634 : xchk_inobt_chunk_xref_finobt(sc, irec, agino, nr_inodes);
277 : else
278 722018 : xchk_finobt_chunk_xref_inobt(sc, irec, agino, nr_inodes);
279 250489033 : xchk_xref_is_only_owned_by(sc, agbno, len, &XFS_RMAP_OINFO_INODES);
280 250489689 : xchk_xref_is_not_shared(sc, agbno, len);
281 250489952 : xchk_xref_is_not_cow_staging(sc, agbno, len);
282 250489952 : return true;
283 : }
284 :
285 : /*
286 : * Check that an inode's allocation status matches ir_free in the inobt
287 : * record. First we try querying the in-core inode state, and if the inode
288 : * isn't loaded we examine the on-disk inode directly.
289 : *
290 : * Since there can be 1:M and M:1 mappings between inobt records and inode
291 : * clusters, we pass in the inode location information as an inobt record;
292 : * the index of an inode cluster within the inobt record (as well as the
293 : * cluster buffer itself); and the index of the inode within the cluster.
294 : *
295 : * @irec is the inobt record.
296 : * @irec_ino is the inode offset from the start of the record.
297 : * @dip is the on-disk inode.
298 : */
299 : STATIC int
300 2897118577 : xchk_iallocbt_check_cluster_ifree(
301 : struct xchk_btree *bs,
302 : struct xfs_inobt_rec_incore *irec,
303 : unsigned int irec_ino,
304 : struct xfs_dinode *dip)
305 : {
306 2897118577 : struct xfs_mount *mp = bs->cur->bc_mp;
307 2897118577 : xfs_ino_t fsino;
308 2897118577 : xfs_agino_t agino;
309 2897118577 : bool irec_free;
310 2897118577 : bool ino_inuse;
311 2897118577 : bool freemask_ok;
312 2897118577 : int error = 0;
313 :
314 2897118577 : if (xchk_should_terminate(bs->sc, &error))
315 1 : return error;
316 :
317 : /*
318 : * Given an inobt record and the offset of an inode from the start of
319 : * the record, compute which fs inode we're talking about.
320 : */
321 2896941858 : agino = irec->ir_startino + irec_ino;
322 2896941858 : fsino = XFS_AGINO_TO_INO(mp, bs->cur->bc_ag.pag->pag_agno, agino);
323 2896941858 : irec_free = (irec->ir_free & XFS_INOBT_MASK(irec_ino));
324 :
325 2896941858 : if (be16_to_cpu(dip->di_magic) != XFS_DINODE_MAGIC ||
326 2896695189 : (dip->di_version >= 3 && be64_to_cpu(dip->di_ino) != fsino)) {
327 246669 : xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
328 0 : goto out;
329 : }
330 :
331 2896695189 : error = xchk_inode_is_allocated(bs->sc, agino, &ino_inuse);
332 2897104416 : if (error == -ENODATA) {
333 : /* Not cached, just read the disk buffer */
334 19873068 : freemask_ok = irec_free ^ !!(dip->di_mode);
335 19873068 : if (!(bs->sc->flags & XCHK_TRY_HARDER) && !freemask_ok)
336 : return -EDEADLOCK;
337 2877231348 : } else if (error < 0) {
338 : /*
339 : * Inode is only half assembled, or there was an IO error,
340 : * or the verifier failed, so don't bother trying to check.
341 : * The inode scrubber can deal with this.
342 : */
343 0 : goto out;
344 : } else {
345 : /* Inode is all there. */
346 2877231348 : freemask_ok = irec_free ^ ino_inuse;
347 : }
348 2897104416 : if (!freemask_ok)
349 0 : xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
350 2897104416 : out:
351 : return 0;
352 : }
353 :
354 : /*
355 : * Check that the holemask and freemask of a hypothetical inode cluster match
356 : * what's actually on disk. If sparse inodes are enabled, the cluster does
357 : * not actually have to map to inodes if the corresponding holemask bit is set.
358 : *
359 : * @cluster_base is the first inode in the cluster within the @irec.
360 : */
361 : STATIC int
362 117903609 : xchk_iallocbt_check_cluster(
363 : struct xchk_btree *bs,
364 : struct xfs_inobt_rec_incore *irec,
365 : unsigned int cluster_base)
366 : {
367 117903609 : struct xfs_imap imap;
368 117903609 : struct xfs_mount *mp = bs->cur->bc_mp;
369 117903609 : struct xfs_buf *cluster_bp;
370 117903609 : unsigned int nr_inodes;
371 117903609 : xfs_agnumber_t agno = bs->cur->bc_ag.pag->pag_agno;
372 117903609 : xfs_agblock_t agbno;
373 117903609 : unsigned int cluster_index;
374 117903609 : uint16_t cluster_mask = 0;
375 117903609 : uint16_t ir_holemask;
376 117903609 : int error = 0;
377 :
378 117903609 : nr_inodes = min_t(unsigned int, XFS_INODES_PER_CHUNK,
379 : M_IGEO(mp)->inodes_per_cluster);
380 :
381 : /* Map this inode cluster */
382 117903609 : agbno = XFS_AGINO_TO_AGBNO(mp, irec->ir_startino + cluster_base);
383 :
384 : /* Compute a bitmask for this cluster that can be used for holemask. */
385 117903609 : for (cluster_index = 0;
386 1061130185 : cluster_index < nr_inodes;
387 943226576 : cluster_index += XFS_INODES_PER_HOLEMASK_BIT)
388 943226576 : cluster_mask |= XFS_INOBT_MASK((cluster_base + cluster_index) /
389 : XFS_INODES_PER_HOLEMASK_BIT);
390 :
391 : /*
392 : * Map the first inode of this cluster to a buffer and offset.
393 : * Be careful about inobt records that don't align with the start of
394 : * the inode buffer when block sizes are large enough to hold multiple
395 : * inode chunks. When this happens, cluster_base will be zero but
396 : * ir_startino can be large enough to make im_boffset nonzero.
397 : */
398 117903609 : ir_holemask = (irec->ir_holemask & cluster_mask);
399 117903609 : imap.im_blkno = XFS_AGB_TO_DADDR(mp, agno, agbno);
400 117903609 : imap.im_len = XFS_FSB_TO_BB(mp, M_IGEO(mp)->blocks_per_cluster);
401 117903609 : imap.im_boffset = XFS_INO_TO_OFFSET(mp, irec->ir_startino) <<
402 117903609 : mp->m_sb.sb_inodelog;
403 :
404 117903609 : if (imap.im_boffset != 0 && cluster_base != 0) {
405 0 : ASSERT(imap.im_boffset == 0 || cluster_base == 0);
406 0 : xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
407 0 : return 0;
408 : }
409 :
410 117903609 : trace_xchk_iallocbt_check_cluster(mp, agno, irec->ir_startino,
411 : imap.im_blkno, imap.im_len, cluster_base, nr_inodes,
412 : cluster_mask, ir_holemask,
413 : XFS_INO_TO_OFFSET(mp, irec->ir_startino +
414 : cluster_base));
415 :
416 : /* The whole cluster must be a hole or not a hole. */
417 117903792 : if (ir_holemask != cluster_mask && ir_holemask != 0) {
418 0 : xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
419 0 : return 0;
420 : }
421 :
422 : /* If any part of this is a hole, skip it. */
423 117903792 : if (ir_holemask) {
424 27362563 : xchk_xref_is_not_owned_by(bs->sc, agbno,
425 : M_IGEO(mp)->blocks_per_cluster,
426 : &XFS_RMAP_OINFO_INODES);
427 27362563 : return 0;
428 : }
429 :
430 90541229 : xchk_xref_is_only_owned_by(bs->sc, agbno, M_IGEO(mp)->blocks_per_cluster,
431 : &XFS_RMAP_OINFO_INODES);
432 :
433 : /* Grab the inode cluster buffer. */
434 90541540 : error = xfs_imap_to_bp(mp, bs->cur->bc_tp, &imap, &cluster_bp);
435 90541538 : if (!xchk_btree_xref_process_error(bs->sc, bs->cur, 0, &error))
436 0 : return error;
437 :
438 : /* Check free status of each inode within this cluster. */
439 2987725122 : for (cluster_index = 0; cluster_index < nr_inodes; cluster_index++) {
440 2897183606 : struct xfs_dinode *dip;
441 :
442 2897183606 : if (imap.im_boffset >= BBTOB(cluster_bp->b_length)) {
443 0 : xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
444 0 : break;
445 : }
446 :
447 2897183606 : dip = xfs_buf_offset(cluster_bp, imap.im_boffset);
448 2897128517 : error = xchk_iallocbt_check_cluster_ifree(bs, irec,
449 : cluster_base + cluster_index, dip);
450 2897183562 : if (error)
451 : break;
452 2897183561 : imap.im_boffset += mp->m_sb.sb_inodesize;
453 : }
454 :
455 90541517 : xfs_trans_brelse(bs->cur->bc_tp, cluster_bp);
456 90541614 : return error;
457 : }
458 :
459 : /*
460 : * For all the inode clusters that could map to this inobt record, make sure
461 : * that the holemask makes sense and that the allocation status of each inode
462 : * matches the freemask.
463 : */
464 : STATIC int
465 58952101 : xchk_iallocbt_check_clusters(
466 : struct xchk_btree *bs,
467 : struct xfs_inobt_rec_incore *irec)
468 : {
469 58952101 : unsigned int cluster_base;
470 58952101 : int error = 0;
471 :
472 : /*
473 : * For the common case where this inobt record maps to multiple inode
474 : * clusters this will call _check_cluster for each cluster.
475 : *
476 : * For the case that multiple inobt records map to a single cluster,
477 : * this will call _check_cluster once.
478 : */
479 58952101 : for (cluster_base = 0;
480 176855655 : cluster_base < XFS_INODES_PER_CHUNK;
481 117903554 : cluster_base += M_IGEO(bs->sc->mp)->inodes_per_cluster) {
482 117903665 : error = xchk_iallocbt_check_cluster(bs, irec, cluster_base);
483 117903555 : if (error)
484 : break;
485 : }
486 :
487 58951991 : return error;
488 : }
489 :
490 : /*
491 : * Make sure this inode btree record is aligned properly. Because a fs block
492 : * contains multiple inodes, we check that the inobt record is aligned to the
493 : * correct inode, not just the correct block on disk. This results in a finer
494 : * grained corruption check.
495 : */
496 : STATIC void
497 58952019 : xchk_iallocbt_rec_alignment(
498 : struct xchk_btree *bs,
499 : struct xfs_inobt_rec_incore *irec)
500 : {
501 58952019 : struct xfs_mount *mp = bs->sc->mp;
502 58952019 : struct xchk_iallocbt *iabt = bs->private;
503 58952019 : struct xfs_ino_geometry *igeo = M_IGEO(mp);
504 :
505 : /*
506 : * finobt records have different positioning requirements than inobt
507 : * records: each finobt record must have a corresponding inobt record.
508 : * That is checked in the xref function, so for now we only catch the
509 : * obvious case where the record isn't at all aligned properly.
510 : *
511 : * Note that if a fs block contains more than a single chunk of inodes,
512 : * we will have finobt records only for those chunks containing free
513 : * inodes, and therefore expect chunk alignment of finobt records.
514 : * Otherwise, we expect that the finobt record is aligned to the
515 : * cluster alignment as told by the superblock.
516 : */
517 58952019 : if (bs->cur->bc_btnum == XFS_BTNUM_FINO) {
518 245535 : unsigned int imask;
519 :
520 245535 : imask = min_t(unsigned int, XFS_INODES_PER_CHUNK,
521 : igeo->cluster_align_inodes) - 1;
522 245535 : if (irec->ir_startino & imask)
523 0 : xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
524 245535 : return;
525 : }
526 :
527 58706484 : if (iabt->next_startino != NULLAGINO) {
528 : /*
529 : * We're midway through a cluster of inodes that is mapped by
530 : * multiple inobt records. Did we get the record for the next
531 : * irec in the sequence?
532 : */
533 2 : if (irec->ir_startino != iabt->next_startino) {
534 0 : xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
535 0 : return;
536 : }
537 :
538 2 : iabt->next_startino += XFS_INODES_PER_CHUNK;
539 :
540 : /* Are we done with the cluster? */
541 2 : if (iabt->next_startino >= iabt->next_cluster_ino) {
542 2 : iabt->next_startino = NULLAGINO;
543 2 : iabt->next_cluster_ino = NULLAGINO;
544 : }
545 2 : return;
546 : }
547 :
548 : /* inobt records must be aligned to cluster and inoalignmnt size. */
549 58706482 : if (irec->ir_startino & (igeo->cluster_align_inodes - 1)) {
550 0 : xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
551 0 : return;
552 : }
553 :
554 58706482 : if (irec->ir_startino & (igeo->inodes_per_cluster - 1)) {
555 0 : xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
556 0 : return;
557 : }
558 :
559 58706482 : if (igeo->inodes_per_cluster <= XFS_INODES_PER_CHUNK)
560 : return;
561 :
562 : /*
563 : * If this is the start of an inode cluster that can be mapped by
564 : * multiple inobt records, the next inobt record must follow exactly
565 : * after this one.
566 : */
567 2 : iabt->next_startino = irec->ir_startino + XFS_INODES_PER_CHUNK;
568 2 : iabt->next_cluster_ino = irec->ir_startino + igeo->inodes_per_cluster;
569 : }
570 :
571 : /* Scrub an inobt/finobt record. */
572 : STATIC int
573 58951986 : xchk_iallocbt_rec(
574 : struct xchk_btree *bs,
575 : const union xfs_btree_rec *rec)
576 : {
577 58951986 : struct xfs_mount *mp = bs->cur->bc_mp;
578 58951986 : struct xchk_iallocbt *iabt = bs->private;
579 58951986 : struct xfs_inobt_rec_incore irec;
580 58951986 : uint64_t holes;
581 58951986 : xfs_agino_t agino;
582 58951986 : int holecount;
583 58951986 : int i;
584 58951986 : int error = 0;
585 58951986 : uint16_t holemask;
586 :
587 58951986 : xfs_inobt_btrec_to_irec(mp, rec, &irec);
588 58952042 : if (xfs_inobt_check_irec(bs->cur, &irec) != NULL) {
589 0 : xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
590 0 : return 0;
591 : }
592 :
593 58951980 : agino = irec.ir_startino;
594 :
595 58951980 : xchk_iallocbt_rec_alignment(bs, &irec);
596 58952079 : if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
597 0 : goto out;
598 :
599 58952079 : iabt->inodes += irec.ir_count;
600 :
601 : /* Handle non-sparse inodes */
602 58952079 : if (!xfs_inobt_issparse(irec.ir_holemask)) {
603 31589508 : if (irec.ir_count != XFS_INODES_PER_CHUNK)
604 0 : xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
605 :
606 31589508 : if (!xchk_iallocbt_chunk(bs, &irec, agino,
607 : XFS_INODES_PER_CHUNK))
608 0 : goto out;
609 31589531 : goto check_clusters;
610 : }
611 :
612 : /* Check each chunk of a sparse inode cluster. */
613 27362571 : holemask = irec.ir_holemask;
614 27362571 : holecount = 0;
615 27362571 : holes = ~xfs_inobt_irec_to_allocmask(&irec);
616 27362571 : if ((holes & irec.ir_free) != holes ||
617 27362571 : irec.ir_freecount > irec.ir_count)
618 0 : xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
619 :
620 465162502 : for (i = 0; i < XFS_INOBT_HOLEMASK_BITS; i++) {
621 437799928 : if (holemask & 1)
622 218900304 : holecount += XFS_INODES_PER_HOLEMASK_BIT;
623 218899624 : else if (!xchk_iallocbt_chunk(bs, &irec, agino,
624 : XFS_INODES_PER_HOLEMASK_BIT))
625 0 : goto out;
626 437799931 : holemask >>= 1;
627 437799931 : agino += XFS_INODES_PER_HOLEMASK_BIT;
628 : }
629 :
630 27362574 : if (holecount > XFS_INODES_PER_CHUNK ||
631 27362574 : holecount + irec.ir_count != XFS_INODES_PER_CHUNK)
632 0 : xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
633 :
634 27362575 : check_clusters:
635 58952102 : if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
636 0 : goto out;
637 :
638 58952102 : error = xchk_iallocbt_check_clusters(bs, &irec);
639 58951974 : if (error)
640 1 : goto out;
641 :
642 58951973 : out:
643 : return error;
644 : }
645 :
646 : /*
647 : * Make sure the inode btrees are as large as the rmap thinks they are.
648 : * Don't bother if we're missing btree cursors, as we're already corrupt.
649 : */
650 : STATIC void
651 366313 : xchk_iallocbt_xref_rmap_btreeblks(
652 : struct xfs_scrub *sc,
653 : int which)
654 : {
655 366313 : xfs_filblks_t blocks;
656 366313 : xfs_extlen_t inobt_blocks = 0;
657 366313 : xfs_extlen_t finobt_blocks = 0;
658 366313 : int error;
659 :
660 366313 : if (!sc->sa.ino_cur || !sc->sa.rmap_cur ||
661 366277 : (xfs_has_finobt(sc->mp) && !sc->sa.fino_cur) ||
662 366277 : xchk_skip_xref(sc->sm))
663 36 : return;
664 :
665 : /* Check that we saw as many inobt blocks as the rmap says. */
666 366277 : error = xfs_btree_count_blocks(sc->sa.ino_cur, &inobt_blocks);
667 366276 : if (!xchk_process_error(sc, 0, 0, &error))
668 : return;
669 :
670 366269 : if (sc->sa.fino_cur) {
671 366269 : error = xfs_btree_count_blocks(sc->sa.fino_cur, &finobt_blocks);
672 366289 : if (!xchk_process_error(sc, 0, 0, &error))
673 : return;
674 : }
675 :
676 366291 : error = xchk_count_rmap_ownedby_ag(sc, sc->sa.rmap_cur,
677 : &XFS_RMAP_OINFO_INOBT, &blocks);
678 366288 : if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
679 : return;
680 366288 : if (blocks != inobt_blocks + finobt_blocks)
681 0 : xchk_btree_set_corrupt(sc, sc->sa.ino_cur, 0);
682 : }
683 :
684 : /*
685 : * Make sure that the inobt records point to the same number of blocks as
686 : * the rmap says are owned by inodes.
687 : */
688 : STATIC void
689 174266 : xchk_iallocbt_xref_rmap_inodes(
690 : struct xfs_scrub *sc,
691 : int which,
692 : unsigned long long inodes)
693 : {
694 174266 : xfs_filblks_t blocks;
695 174266 : xfs_filblks_t inode_blocks;
696 174266 : int error;
697 :
698 174266 : if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm))
699 20 : return;
700 :
701 : /* Check that we saw as many inode blocks as the rmap knows about. */
702 174246 : error = xchk_count_rmap_ownedby_ag(sc, sc->sa.rmap_cur,
703 : &XFS_RMAP_OINFO_INODES, &blocks);
704 174248 : if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
705 : return;
706 174248 : inode_blocks = XFS_B_TO_FSB(sc->mp, inodes * sc->mp->m_sb.sb_inodesize);
707 174248 : if (blocks != inode_blocks)
708 0 : xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
709 : }
710 :
711 : /* Scrub the inode btrees for some AG. */
712 : STATIC int
713 366297 : xchk_iallocbt(
714 : struct xfs_scrub *sc,
715 : xfs_btnum_t which)
716 : {
717 366297 : struct xfs_btree_cur *cur;
718 366297 : struct xchk_iallocbt iabt = {
719 : .inodes = 0,
720 : .next_startino = NULLAGINO,
721 : .next_cluster_ino = NULLAGINO,
722 : };
723 366297 : int error;
724 :
725 366297 : cur = which == XFS_BTNUM_INO ? sc->sa.ino_cur : sc->sa.fino_cur;
726 366297 : error = xchk_btree(sc, cur, xchk_iallocbt_rec, &XFS_RMAP_OINFO_INOBT,
727 : &iabt);
728 366326 : if (error)
729 : return error;
730 :
731 366320 : xchk_iallocbt_xref_rmap_btreeblks(sc, which);
732 :
733 : /*
734 : * If we're scrubbing the inode btree, inode_blocks is the number of
735 : * blocks pointed to by all the inode chunk records. Therefore, we
736 : * should compare to the number of inode chunk blocks that the rmap
737 : * knows about. We can't do this for the finobt since it only points
738 : * to inode chunks with free inodes.
739 : */
740 366327 : if (which == XFS_BTNUM_INO)
741 174268 : xchk_iallocbt_xref_rmap_inodes(sc, which, iabt.inodes);
742 :
743 : return error;
744 : }
745 :
746 : int
747 174250 : xchk_inobt(
748 : struct xfs_scrub *sc)
749 : {
750 174250 : return xchk_iallocbt(sc, XFS_BTNUM_INO);
751 : }
752 :
753 : int
754 192059 : xchk_finobt(
755 : struct xfs_scrub *sc)
756 : {
757 192059 : return xchk_iallocbt(sc, XFS_BTNUM_FINO);
758 : }
759 :
760 : /* See if an inode btree has (or doesn't have) an inode chunk record. */
761 : static inline void
762 3592567443 : xchk_xref_inode_check(
763 : struct xfs_scrub *sc,
764 : xfs_agblock_t agbno,
765 : xfs_extlen_t len,
766 : struct xfs_btree_cur **icur,
767 : enum xbtree_recpacking expected)
768 : {
769 3592567443 : enum xbtree_recpacking outcome;
770 3592567443 : int error;
771 :
772 3592567443 : if (!(*icur) || xchk_skip_xref(sc->sm))
773 38 : return;
774 :
775 3592567405 : error = xfs_ialloc_has_inodes_at_extent(*icur, agbno, len, &outcome);
776 3592340177 : if (!xchk_should_check_xref(sc, &error, icur))
777 : return;
778 3592348463 : if (outcome != expected)
779 0 : xchk_btree_xref_set_corrupt(sc, *icur, 0);
780 : }
781 :
782 : /* xref check that the extent is not covered by inodes */
783 : void
784 1788415292 : xchk_xref_is_not_inode_chunk(
785 : struct xfs_scrub *sc,
786 : xfs_agblock_t agbno,
787 : xfs_extlen_t len)
788 : {
789 1788415292 : xchk_xref_inode_check(sc, agbno, len, &sc->sa.ino_cur,
790 : XBTREE_RECPACKING_EMPTY);
791 1788415896 : xchk_xref_inode_check(sc, agbno, len, &sc->sa.fino_cur,
792 : XBTREE_RECPACKING_EMPTY);
793 1788351846 : }
794 :
795 : /* xref check that the extent is covered by inodes */
796 : void
797 15979655 : xchk_xref_is_inode_chunk(
798 : struct xfs_scrub *sc,
799 : xfs_agblock_t agbno,
800 : xfs_extlen_t len)
801 : {
802 15979655 : xchk_xref_inode_check(sc, agbno, len, &sc->sa.ino_cur,
803 : XBTREE_RECPACKING_FULL);
804 15979654 : }
|