~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/fs/xfs/scrub/agheader.c

Version: ~ [ linux-6.11.5 ] ~ [ linux-6.10.14 ] ~ [ linux-6.9.12 ] ~ [ linux-6.8.12 ] ~ [ linux-6.7.12 ] ~ [ linux-6.6.58 ] ~ [ linux-6.5.13 ] ~ [ linux-6.4.16 ] ~ [ linux-6.3.13 ] ~ [ linux-6.2.16 ] ~ [ linux-6.1.114 ] ~ [ linux-6.0.19 ] ~ [ linux-5.19.17 ] ~ [ linux-5.18.19 ] ~ [ linux-5.17.15 ] ~ [ linux-5.16.20 ] ~ [ linux-5.15.169 ] ~ [ linux-5.14.21 ] ~ [ linux-5.13.19 ] ~ [ linux-5.12.19 ] ~ [ linux-5.11.22 ] ~ [ linux-5.10.228 ] ~ [ linux-5.9.16 ] ~ [ linux-5.8.18 ] ~ [ linux-5.7.19 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.284 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.322 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.336 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.337 ] ~ [ linux-4.4.302 ] ~ [ linux-3.10.108 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.9 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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_sb.h"
 14 #include "xfs_alloc.h"
 15 #include "xfs_ialloc.h"
 16 #include "xfs_rmap.h"
 17 #include "xfs_ag.h"
 18 #include "xfs_inode.h"
 19 #include "scrub/scrub.h"
 20 #include "scrub/common.h"
 21 
 22 int
 23 xchk_setup_agheader(
 24         struct xfs_scrub        *sc)
 25 {
 26         if (xchk_need_intent_drain(sc))
 27                 xchk_fsgates_enable(sc, XCHK_FSGATES_DRAIN);
 28         return xchk_setup_fs(sc);
 29 }
 30 
 31 /* Superblock */
 32 
 33 /* Cross-reference with the other btrees. */
 34 STATIC void
 35 xchk_superblock_xref(
 36         struct xfs_scrub        *sc,
 37         struct xfs_buf          *bp)
 38 {
 39         struct xfs_mount        *mp = sc->mp;
 40         xfs_agnumber_t          agno = sc->sm->sm_agno;
 41         xfs_agblock_t           agbno;
 42         int                     error;
 43 
 44         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
 45                 return;
 46 
 47         agbno = XFS_SB_BLOCK(mp);
 48 
 49         error = xchk_ag_init_existing(sc, agno, &sc->sa);
 50         if (!xchk_xref_process_error(sc, agno, agbno, &error))
 51                 return;
 52 
 53         xchk_xref_is_used_space(sc, agbno, 1);
 54         xchk_xref_is_not_inode_chunk(sc, agbno, 1);
 55         xchk_xref_is_only_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS);
 56         xchk_xref_is_not_shared(sc, agbno, 1);
 57         xchk_xref_is_not_cow_staging(sc, agbno, 1);
 58 
 59         /* scrub teardown will take care of sc->sa for us */
 60 }
 61 
 62 /*
 63  * Scrub the filesystem superblock.
 64  *
 65  * Note: We do /not/ attempt to check AG 0's superblock.  Mount is
 66  * responsible for validating all the geometry information in sb 0, so
 67  * if the filesystem is capable of initiating online scrub, then clearly
 68  * sb 0 is ok and we can use its information to check everything else.
 69  */
 70 int
 71 xchk_superblock(
 72         struct xfs_scrub        *sc)
 73 {
 74         struct xfs_mount        *mp = sc->mp;
 75         struct xfs_buf          *bp;
 76         struct xfs_dsb          *sb;
 77         struct xfs_perag        *pag;
 78         xfs_agnumber_t          agno;
 79         uint32_t                v2_ok;
 80         __be32                  features_mask;
 81         int                     error;
 82         __be16                  vernum_mask;
 83 
 84         agno = sc->sm->sm_agno;
 85         if (agno == 0)
 86                 return 0;
 87 
 88         /*
 89          * Grab an active reference to the perag structure.  If we can't get
 90          * it, we're racing with something that's tearing down the AG, so
 91          * signal that the AG no longer exists.
 92          */
 93         pag = xfs_perag_get(mp, agno);
 94         if (!pag)
 95                 return -ENOENT;
 96 
 97         error = xfs_sb_read_secondary(mp, sc->tp, agno, &bp);
 98         /*
 99          * The superblock verifier can return several different error codes
100          * if it thinks the superblock doesn't look right.  For a mount these
101          * would all get bounced back to userspace, but if we're here then the
102          * fs mounted successfully, which means that this secondary superblock
103          * is simply incorrect.  Treat all these codes the same way we treat
104          * any corruption.
105          */
106         switch (error) {
107         case -EINVAL:   /* also -EWRONGFS */
108         case -ENOSYS:
109         case -EFBIG:
110                 error = -EFSCORRUPTED;
111                 fallthrough;
112         default:
113                 break;
114         }
115         if (!xchk_process_error(sc, agno, XFS_SB_BLOCK(mp), &error))
116                 goto out_pag;
117 
118         sb = bp->b_addr;
119 
120         /*
121          * Verify the geometries match.  Fields that are permanently
122          * set by mkfs are checked; fields that can be updated later
123          * (and are not propagated to backup superblocks) are preen
124          * checked.
125          */
126         if (sb->sb_blocksize != cpu_to_be32(mp->m_sb.sb_blocksize))
127                 xchk_block_set_corrupt(sc, bp);
128 
129         if (sb->sb_dblocks != cpu_to_be64(mp->m_sb.sb_dblocks))
130                 xchk_block_set_corrupt(sc, bp);
131 
132         if (sb->sb_rblocks != cpu_to_be64(mp->m_sb.sb_rblocks))
133                 xchk_block_set_corrupt(sc, bp);
134 
135         if (sb->sb_rextents != cpu_to_be64(mp->m_sb.sb_rextents))
136                 xchk_block_set_corrupt(sc, bp);
137 
138         if (!uuid_equal(&sb->sb_uuid, &mp->m_sb.sb_uuid))
139                 xchk_block_set_preen(sc, bp);
140 
141         if (sb->sb_logstart != cpu_to_be64(mp->m_sb.sb_logstart))
142                 xchk_block_set_corrupt(sc, bp);
143 
144         if (sb->sb_rootino != cpu_to_be64(mp->m_sb.sb_rootino))
145                 xchk_block_set_preen(sc, bp);
146 
147         if (sb->sb_rbmino != cpu_to_be64(mp->m_sb.sb_rbmino))
148                 xchk_block_set_preen(sc, bp);
149 
150         if (sb->sb_rsumino != cpu_to_be64(mp->m_sb.sb_rsumino))
151                 xchk_block_set_preen(sc, bp);
152 
153         if (sb->sb_rextsize != cpu_to_be32(mp->m_sb.sb_rextsize))
154                 xchk_block_set_corrupt(sc, bp);
155 
156         if (sb->sb_agblocks != cpu_to_be32(mp->m_sb.sb_agblocks))
157                 xchk_block_set_corrupt(sc, bp);
158 
159         if (sb->sb_agcount != cpu_to_be32(mp->m_sb.sb_agcount))
160                 xchk_block_set_corrupt(sc, bp);
161 
162         if (sb->sb_rbmblocks != cpu_to_be32(mp->m_sb.sb_rbmblocks))
163                 xchk_block_set_corrupt(sc, bp);
164 
165         if (sb->sb_logblocks != cpu_to_be32(mp->m_sb.sb_logblocks))
166                 xchk_block_set_corrupt(sc, bp);
167 
168         /* Check sb_versionnum bits that are set at mkfs time. */
169         vernum_mask = cpu_to_be16(XFS_SB_VERSION_NUMBITS |
170                                   XFS_SB_VERSION_ALIGNBIT |
171                                   XFS_SB_VERSION_DALIGNBIT |
172                                   XFS_SB_VERSION_SHAREDBIT |
173                                   XFS_SB_VERSION_LOGV2BIT |
174                                   XFS_SB_VERSION_SECTORBIT |
175                                   XFS_SB_VERSION_EXTFLGBIT |
176                                   XFS_SB_VERSION_DIRV2BIT);
177         if ((sb->sb_versionnum & vernum_mask) !=
178             (cpu_to_be16(mp->m_sb.sb_versionnum) & vernum_mask))
179                 xchk_block_set_corrupt(sc, bp);
180 
181         /* Check sb_versionnum bits that can be set after mkfs time. */
182         vernum_mask = cpu_to_be16(XFS_SB_VERSION_ATTRBIT |
183                                   XFS_SB_VERSION_NLINKBIT |
184                                   XFS_SB_VERSION_QUOTABIT);
185         if ((sb->sb_versionnum & vernum_mask) !=
186             (cpu_to_be16(mp->m_sb.sb_versionnum) & vernum_mask))
187                 xchk_block_set_preen(sc, bp);
188 
189         if (sb->sb_sectsize != cpu_to_be16(mp->m_sb.sb_sectsize))
190                 xchk_block_set_corrupt(sc, bp);
191 
192         if (sb->sb_inodesize != cpu_to_be16(mp->m_sb.sb_inodesize))
193                 xchk_block_set_corrupt(sc, bp);
194 
195         if (sb->sb_inopblock != cpu_to_be16(mp->m_sb.sb_inopblock))
196                 xchk_block_set_corrupt(sc, bp);
197 
198         if (memcmp(sb->sb_fname, mp->m_sb.sb_fname, sizeof(sb->sb_fname)))
199                 xchk_block_set_preen(sc, bp);
200 
201         if (sb->sb_blocklog != mp->m_sb.sb_blocklog)
202                 xchk_block_set_corrupt(sc, bp);
203 
204         if (sb->sb_sectlog != mp->m_sb.sb_sectlog)
205                 xchk_block_set_corrupt(sc, bp);
206 
207         if (sb->sb_inodelog != mp->m_sb.sb_inodelog)
208                 xchk_block_set_corrupt(sc, bp);
209 
210         if (sb->sb_inopblog != mp->m_sb.sb_inopblog)
211                 xchk_block_set_corrupt(sc, bp);
212 
213         if (sb->sb_agblklog != mp->m_sb.sb_agblklog)
214                 xchk_block_set_corrupt(sc, bp);
215 
216         if (sb->sb_rextslog != mp->m_sb.sb_rextslog)
217                 xchk_block_set_corrupt(sc, bp);
218 
219         if (sb->sb_imax_pct != mp->m_sb.sb_imax_pct)
220                 xchk_block_set_preen(sc, bp);
221 
222         /*
223          * Skip the summary counters since we track them in memory anyway.
224          * sb_icount, sb_ifree, sb_fdblocks, sb_frexents
225          */
226 
227         if (sb->sb_uquotino != cpu_to_be64(mp->m_sb.sb_uquotino))
228                 xchk_block_set_preen(sc, bp);
229 
230         if (sb->sb_gquotino != cpu_to_be64(mp->m_sb.sb_gquotino))
231                 xchk_block_set_preen(sc, bp);
232 
233         /*
234          * Skip the quota flags since repair will force quotacheck.
235          * sb_qflags
236          */
237 
238         if (sb->sb_flags != mp->m_sb.sb_flags)
239                 xchk_block_set_corrupt(sc, bp);
240 
241         if (sb->sb_shared_vn != mp->m_sb.sb_shared_vn)
242                 xchk_block_set_corrupt(sc, bp);
243 
244         if (sb->sb_inoalignmt != cpu_to_be32(mp->m_sb.sb_inoalignmt))
245                 xchk_block_set_corrupt(sc, bp);
246 
247         if (sb->sb_unit != cpu_to_be32(mp->m_sb.sb_unit))
248                 xchk_block_set_preen(sc, bp);
249 
250         if (sb->sb_width != cpu_to_be32(mp->m_sb.sb_width))
251                 xchk_block_set_preen(sc, bp);
252 
253         if (sb->sb_dirblklog != mp->m_sb.sb_dirblklog)
254                 xchk_block_set_corrupt(sc, bp);
255 
256         if (sb->sb_logsectlog != mp->m_sb.sb_logsectlog)
257                 xchk_block_set_corrupt(sc, bp);
258 
259         if (sb->sb_logsectsize != cpu_to_be16(mp->m_sb.sb_logsectsize))
260                 xchk_block_set_corrupt(sc, bp);
261 
262         if (sb->sb_logsunit != cpu_to_be32(mp->m_sb.sb_logsunit))
263                 xchk_block_set_corrupt(sc, bp);
264 
265         /* Do we see any invalid bits in sb_features2? */
266         if (!xfs_sb_version_hasmorebits(&mp->m_sb)) {
267                 if (sb->sb_features2 != 0)
268                         xchk_block_set_corrupt(sc, bp);
269         } else {
270                 v2_ok = XFS_SB_VERSION2_OKBITS;
271                 if (xfs_sb_is_v5(&mp->m_sb))
272                         v2_ok |= XFS_SB_VERSION2_CRCBIT;
273 
274                 if (!!(sb->sb_features2 & cpu_to_be32(~v2_ok)))
275                         xchk_block_set_corrupt(sc, bp);
276 
277                 if (sb->sb_features2 != sb->sb_bad_features2)
278                         xchk_block_set_preen(sc, bp);
279         }
280 
281         /* Check sb_features2 flags that are set at mkfs time. */
282         features_mask = cpu_to_be32(XFS_SB_VERSION2_LAZYSBCOUNTBIT |
283                                     XFS_SB_VERSION2_PROJID32BIT |
284                                     XFS_SB_VERSION2_CRCBIT |
285                                     XFS_SB_VERSION2_FTYPE);
286         if ((sb->sb_features2 & features_mask) !=
287             (cpu_to_be32(mp->m_sb.sb_features2) & features_mask))
288                 xchk_block_set_corrupt(sc, bp);
289 
290         /* Check sb_features2 flags that can be set after mkfs time. */
291         features_mask = cpu_to_be32(XFS_SB_VERSION2_ATTR2BIT);
292         if ((sb->sb_features2 & features_mask) !=
293             (cpu_to_be32(mp->m_sb.sb_features2) & features_mask))
294                 xchk_block_set_preen(sc, bp);
295 
296         if (!xfs_has_crc(mp)) {
297                 /* all v5 fields must be zero */
298                 if (memchr_inv(&sb->sb_features_compat, 0,
299                                 sizeof(struct xfs_dsb) -
300                                 offsetof(struct xfs_dsb, sb_features_compat)))
301                         xchk_block_set_corrupt(sc, bp);
302         } else {
303                 /* compat features must match */
304                 if (sb->sb_features_compat !=
305                                 cpu_to_be32(mp->m_sb.sb_features_compat))
306                         xchk_block_set_corrupt(sc, bp);
307 
308                 /* ro compat features must match */
309                 if (sb->sb_features_ro_compat !=
310                                 cpu_to_be32(mp->m_sb.sb_features_ro_compat))
311                         xchk_block_set_corrupt(sc, bp);
312 
313                 /*
314                  * NEEDSREPAIR is ignored on a secondary super, so we should
315                  * clear it when we find it, though it's not a corruption.
316                  */
317                 features_mask = cpu_to_be32(XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR);
318                 if ((cpu_to_be32(mp->m_sb.sb_features_incompat) ^
319                                 sb->sb_features_incompat) & features_mask)
320                         xchk_block_set_preen(sc, bp);
321 
322                 /* all other incompat features must match */
323                 if ((cpu_to_be32(mp->m_sb.sb_features_incompat) ^
324                                 sb->sb_features_incompat) & ~features_mask)
325                         xchk_block_set_corrupt(sc, bp);
326 
327                 /*
328                  * log incompat features protect newer log record types from
329                  * older log recovery code.  Log recovery doesn't check the
330                  * secondary supers, so we can clear these if needed.
331                  */
332                 if (sb->sb_features_log_incompat)
333                         xchk_block_set_preen(sc, bp);
334 
335                 /* Don't care about sb_crc */
336 
337                 if (sb->sb_spino_align != cpu_to_be32(mp->m_sb.sb_spino_align))
338                         xchk_block_set_corrupt(sc, bp);
339 
340                 if (sb->sb_pquotino != cpu_to_be64(mp->m_sb.sb_pquotino))
341                         xchk_block_set_preen(sc, bp);
342 
343                 /* Don't care about sb_lsn */
344         }
345 
346         if (xfs_has_metauuid(mp)) {
347                 /* The metadata UUID must be the same for all supers */
348                 if (!uuid_equal(&sb->sb_meta_uuid, &mp->m_sb.sb_meta_uuid))
349                         xchk_block_set_corrupt(sc, bp);
350         }
351 
352         /* Everything else must be zero. */
353         if (memchr_inv(sb + 1, 0,
354                         BBTOB(bp->b_length) - sizeof(struct xfs_dsb)))
355                 xchk_block_set_corrupt(sc, bp);
356 
357         xchk_superblock_xref(sc, bp);
358 out_pag:
359         xfs_perag_put(pag);
360         return error;
361 }
362 
363 /* AGF */
364 
365 /* Tally freespace record lengths. */
366 STATIC int
367 xchk_agf_record_bno_lengths(
368         struct xfs_btree_cur            *cur,
369         const struct xfs_alloc_rec_incore *rec,
370         void                            *priv)
371 {
372         xfs_extlen_t                    *blocks = priv;
373 
374         (*blocks) += rec->ar_blockcount;
375         return 0;
376 }
377 
378 /* Check agf_freeblks */
379 static inline void
380 xchk_agf_xref_freeblks(
381         struct xfs_scrub        *sc)
382 {
383         struct xfs_agf          *agf = sc->sa.agf_bp->b_addr;
384         xfs_extlen_t            blocks = 0;
385         int                     error;
386 
387         if (!sc->sa.bno_cur)
388                 return;
389 
390         error = xfs_alloc_query_all(sc->sa.bno_cur,
391                         xchk_agf_record_bno_lengths, &blocks);
392         if (!xchk_should_check_xref(sc, &error, &sc->sa.bno_cur))
393                 return;
394         if (blocks != be32_to_cpu(agf->agf_freeblks))
395                 xchk_block_xref_set_corrupt(sc, sc->sa.agf_bp);
396 }
397 
398 /* Cross reference the AGF with the cntbt (freespace by length btree) */
399 static inline void
400 xchk_agf_xref_cntbt(
401         struct xfs_scrub        *sc)
402 {
403         struct xfs_agf          *agf = sc->sa.agf_bp->b_addr;
404         xfs_agblock_t           agbno;
405         xfs_extlen_t            blocks;
406         int                     have;
407         int                     error;
408 
409         if (!sc->sa.cnt_cur)
410                 return;
411 
412         /* Any freespace at all? */
413         error = xfs_alloc_lookup_le(sc->sa.cnt_cur, 0, -1U, &have);
414         if (!xchk_should_check_xref(sc, &error, &sc->sa.cnt_cur))
415                 return;
416         if (!have) {
417                 if (agf->agf_freeblks != cpu_to_be32(0))
418                         xchk_block_xref_set_corrupt(sc, sc->sa.agf_bp);
419                 return;
420         }
421 
422         /* Check agf_longest */
423         error = xfs_alloc_get_rec(sc->sa.cnt_cur, &agbno, &blocks, &have);
424         if (!xchk_should_check_xref(sc, &error, &sc->sa.cnt_cur))
425                 return;
426         if (!have || blocks != be32_to_cpu(agf->agf_longest))
427                 xchk_block_xref_set_corrupt(sc, sc->sa.agf_bp);
428 }
429 
430 /* Check the btree block counts in the AGF against the btrees. */
431 STATIC void
432 xchk_agf_xref_btreeblks(
433         struct xfs_scrub        *sc)
434 {
435         struct xfs_agf          *agf = sc->sa.agf_bp->b_addr;
436         struct xfs_mount        *mp = sc->mp;
437         xfs_agblock_t           blocks;
438         xfs_agblock_t           btreeblks;
439         int                     error;
440 
441         /* agf_btreeblks didn't exist before lazysbcount */
442         if (!xfs_has_lazysbcount(sc->mp))
443                 return;
444 
445         /* Check agf_rmap_blocks; set up for agf_btreeblks check */
446         if (sc->sa.rmap_cur) {
447                 error = xfs_btree_count_blocks(sc->sa.rmap_cur, &blocks);
448                 if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
449                         return;
450                 btreeblks = blocks - 1;
451                 if (blocks != be32_to_cpu(agf->agf_rmap_blocks))
452                         xchk_block_xref_set_corrupt(sc, sc->sa.agf_bp);
453         } else {
454                 btreeblks = 0;
455         }
456 
457         /*
458          * No rmap cursor; we can't xref if we have the rmapbt feature.
459          * We also can't do it if we're missing the free space btree cursors.
460          */
461         if ((xfs_has_rmapbt(mp) && !sc->sa.rmap_cur) ||
462             !sc->sa.bno_cur || !sc->sa.cnt_cur)
463                 return;
464 
465         /* Check agf_btreeblks */
466         error = xfs_btree_count_blocks(sc->sa.bno_cur, &blocks);
467         if (!xchk_should_check_xref(sc, &error, &sc->sa.bno_cur))
468                 return;
469         btreeblks += blocks - 1;
470 
471         error = xfs_btree_count_blocks(sc->sa.cnt_cur, &blocks);
472         if (!xchk_should_check_xref(sc, &error, &sc->sa.cnt_cur))
473                 return;
474         btreeblks += blocks - 1;
475 
476         if (btreeblks != be32_to_cpu(agf->agf_btreeblks))
477                 xchk_block_xref_set_corrupt(sc, sc->sa.agf_bp);
478 }
479 
480 /* Check agf_refcount_blocks against tree size */
481 static inline void
482 xchk_agf_xref_refcblks(
483         struct xfs_scrub        *sc)
484 {
485         struct xfs_agf          *agf = sc->sa.agf_bp->b_addr;
486         xfs_agblock_t           blocks;
487         int                     error;
488 
489         if (!sc->sa.refc_cur)
490                 return;
491 
492         error = xfs_btree_count_blocks(sc->sa.refc_cur, &blocks);
493         if (!xchk_should_check_xref(sc, &error, &sc->sa.refc_cur))
494                 return;
495         if (blocks != be32_to_cpu(agf->agf_refcount_blocks))
496                 xchk_block_xref_set_corrupt(sc, sc->sa.agf_bp);
497 }
498 
499 /* Cross-reference with the other btrees. */
500 STATIC void
501 xchk_agf_xref(
502         struct xfs_scrub        *sc)
503 {
504         struct xfs_mount        *mp = sc->mp;
505         xfs_agblock_t           agbno;
506 
507         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
508                 return;
509 
510         agbno = XFS_AGF_BLOCK(mp);
511 
512         xchk_ag_btcur_init(sc, &sc->sa);
513 
514         xchk_xref_is_used_space(sc, agbno, 1);
515         xchk_agf_xref_freeblks(sc);
516         xchk_agf_xref_cntbt(sc);
517         xchk_xref_is_not_inode_chunk(sc, agbno, 1);
518         xchk_xref_is_only_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS);
519         xchk_agf_xref_btreeblks(sc);
520         xchk_xref_is_not_shared(sc, agbno, 1);
521         xchk_xref_is_not_cow_staging(sc, agbno, 1);
522         xchk_agf_xref_refcblks(sc);
523 
524         /* scrub teardown will take care of sc->sa for us */
525 }
526 
527 /* Scrub the AGF. */
528 int
529 xchk_agf(
530         struct xfs_scrub        *sc)
531 {
532         struct xfs_mount        *mp = sc->mp;
533         struct xfs_agf          *agf;
534         struct xfs_perag        *pag;
535         xfs_agnumber_t          agno = sc->sm->sm_agno;
536         xfs_agblock_t           agbno;
537         xfs_agblock_t           eoag;
538         xfs_agblock_t           agfl_first;
539         xfs_agblock_t           agfl_last;
540         xfs_agblock_t           agfl_count;
541         xfs_agblock_t           fl_count;
542         int                     level;
543         int                     error = 0;
544 
545         error = xchk_ag_read_headers(sc, agno, &sc->sa);
546         if (!xchk_process_error(sc, agno, XFS_AGF_BLOCK(sc->mp), &error))
547                 goto out;
548         xchk_buffer_recheck(sc, sc->sa.agf_bp);
549 
550         agf = sc->sa.agf_bp->b_addr;
551         pag = sc->sa.pag;
552 
553         /* Check the AG length */
554         eoag = be32_to_cpu(agf->agf_length);
555         if (eoag != pag->block_count)
556                 xchk_block_set_corrupt(sc, sc->sa.agf_bp);
557 
558         /* Check the AGF btree roots and levels */
559         agbno = be32_to_cpu(agf->agf_bno_root);
560         if (!xfs_verify_agbno(pag, agbno))
561                 xchk_block_set_corrupt(sc, sc->sa.agf_bp);
562 
563         agbno = be32_to_cpu(agf->agf_cnt_root);
564         if (!xfs_verify_agbno(pag, agbno))
565                 xchk_block_set_corrupt(sc, sc->sa.agf_bp);
566 
567         level = be32_to_cpu(agf->agf_bno_level);
568         if (level <= 0 || level > mp->m_alloc_maxlevels)
569                 xchk_block_set_corrupt(sc, sc->sa.agf_bp);
570 
571         level = be32_to_cpu(agf->agf_cnt_level);
572         if (level <= 0 || level > mp->m_alloc_maxlevels)
573                 xchk_block_set_corrupt(sc, sc->sa.agf_bp);
574 
575         if (xfs_has_rmapbt(mp)) {
576                 agbno = be32_to_cpu(agf->agf_rmap_root);
577                 if (!xfs_verify_agbno(pag, agbno))
578                         xchk_block_set_corrupt(sc, sc->sa.agf_bp);
579 
580                 level = be32_to_cpu(agf->agf_rmap_level);
581                 if (level <= 0 || level > mp->m_rmap_maxlevels)
582                         xchk_block_set_corrupt(sc, sc->sa.agf_bp);
583         }
584 
585         if (xfs_has_reflink(mp)) {
586                 agbno = be32_to_cpu(agf->agf_refcount_root);
587                 if (!xfs_verify_agbno(pag, agbno))
588                         xchk_block_set_corrupt(sc, sc->sa.agf_bp);
589 
590                 level = be32_to_cpu(agf->agf_refcount_level);
591                 if (level <= 0 || level > mp->m_refc_maxlevels)
592                         xchk_block_set_corrupt(sc, sc->sa.agf_bp);
593         }
594 
595         /* Check the AGFL counters */
596         agfl_first = be32_to_cpu(agf->agf_flfirst);
597         agfl_last = be32_to_cpu(agf->agf_fllast);
598         agfl_count = be32_to_cpu(agf->agf_flcount);
599         if (agfl_last > agfl_first)
600                 fl_count = agfl_last - agfl_first + 1;
601         else
602                 fl_count = xfs_agfl_size(mp) - agfl_first + agfl_last + 1;
603         if (agfl_count != 0 && fl_count != agfl_count)
604                 xchk_block_set_corrupt(sc, sc->sa.agf_bp);
605 
606         /* Do the incore counters match? */
607         if (pag->pagf_freeblks != be32_to_cpu(agf->agf_freeblks))
608                 xchk_block_set_corrupt(sc, sc->sa.agf_bp);
609         if (pag->pagf_flcount != be32_to_cpu(agf->agf_flcount))
610                 xchk_block_set_corrupt(sc, sc->sa.agf_bp);
611         if (xfs_has_lazysbcount(sc->mp) &&
612             pag->pagf_btreeblks != be32_to_cpu(agf->agf_btreeblks))
613                 xchk_block_set_corrupt(sc, sc->sa.agf_bp);
614 
615         xchk_agf_xref(sc);
616 out:
617         return error;
618 }
619 
620 /* AGFL */
621 
622 struct xchk_agfl_info {
623         /* Number of AGFL entries that the AGF claims are in use. */
624         unsigned int            agflcount;
625 
626         /* Number of AGFL entries that we found. */
627         unsigned int            nr_entries;
628 
629         /* Buffer to hold AGFL entries for extent checking. */
630         xfs_agblock_t           *entries;
631 
632         struct xfs_buf          *agfl_bp;
633         struct xfs_scrub        *sc;
634 };
635 
636 /* Cross-reference with the other btrees. */
637 STATIC void
638 xchk_agfl_block_xref(
639         struct xfs_scrub        *sc,
640         xfs_agblock_t           agbno)
641 {
642         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
643                 return;
644 
645         xchk_xref_is_used_space(sc, agbno, 1);
646         xchk_xref_is_not_inode_chunk(sc, agbno, 1);
647         xchk_xref_is_only_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_AG);
648         xchk_xref_is_not_shared(sc, agbno, 1);
649         xchk_xref_is_not_cow_staging(sc, agbno, 1);
650 }
651 
652 /* Scrub an AGFL block. */
653 STATIC int
654 xchk_agfl_block(
655         struct xfs_mount        *mp,
656         xfs_agblock_t           agbno,
657         void                    *priv)
658 {
659         struct xchk_agfl_info   *sai = priv;
660         struct xfs_scrub        *sc = sai->sc;
661 
662         if (xfs_verify_agbno(sc->sa.pag, agbno) &&
663             sai->nr_entries < sai->agflcount)
664                 sai->entries[sai->nr_entries++] = agbno;
665         else
666                 xchk_block_set_corrupt(sc, sai->agfl_bp);
667 
668         xchk_agfl_block_xref(sc, agbno);
669 
670         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
671                 return -ECANCELED;
672 
673         return 0;
674 }
675 
676 static int
677 xchk_agblock_cmp(
678         const void              *pa,
679         const void              *pb)
680 {
681         const xfs_agblock_t     *a = pa;
682         const xfs_agblock_t     *b = pb;
683 
684         return (int)*a - (int)*b;
685 }
686 
687 /* Cross-reference with the other btrees. */
688 STATIC void
689 xchk_agfl_xref(
690         struct xfs_scrub        *sc)
691 {
692         struct xfs_mount        *mp = sc->mp;
693         xfs_agblock_t           agbno;
694 
695         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
696                 return;
697 
698         agbno = XFS_AGFL_BLOCK(mp);
699 
700         xchk_ag_btcur_init(sc, &sc->sa);
701 
702         xchk_xref_is_used_space(sc, agbno, 1);
703         xchk_xref_is_not_inode_chunk(sc, agbno, 1);
704         xchk_xref_is_only_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS);
705         xchk_xref_is_not_shared(sc, agbno, 1);
706         xchk_xref_is_not_cow_staging(sc, agbno, 1);
707 
708         /*
709          * Scrub teardown will take care of sc->sa for us.  Leave sc->sa
710          * active so that the agfl block xref can use it too.
711          */
712 }
713 
714 /* Scrub the AGFL. */
715 int
716 xchk_agfl(
717         struct xfs_scrub        *sc)
718 {
719         struct xchk_agfl_info   sai = {
720                 .sc             = sc,
721         };
722         struct xfs_agf          *agf;
723         xfs_agnumber_t          agno = sc->sm->sm_agno;
724         unsigned int            i;
725         int                     error;
726 
727         /* Lock the AGF and AGI so that nobody can touch this AG. */
728         error = xchk_ag_read_headers(sc, agno, &sc->sa);
729         if (!xchk_process_error(sc, agno, XFS_AGFL_BLOCK(sc->mp), &error))
730                 return error;
731         if (!sc->sa.agf_bp)
732                 return -EFSCORRUPTED;
733 
734         /* Try to read the AGFL, and verify its structure if we get it. */
735         error = xfs_alloc_read_agfl(sc->sa.pag, sc->tp, &sai.agfl_bp);
736         if (!xchk_process_error(sc, agno, XFS_AGFL_BLOCK(sc->mp), &error))
737                 return error;
738         xchk_buffer_recheck(sc, sai.agfl_bp);
739 
740         xchk_agfl_xref(sc);
741 
742         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
743                 goto out;
744 
745         /* Allocate buffer to ensure uniqueness of AGFL entries. */
746         agf = sc->sa.agf_bp->b_addr;
747         sai.agflcount = be32_to_cpu(agf->agf_flcount);
748         if (sai.agflcount > xfs_agfl_size(sc->mp)) {
749                 xchk_block_set_corrupt(sc, sc->sa.agf_bp);
750                 goto out;
751         }
752         sai.entries = kvcalloc(sai.agflcount, sizeof(xfs_agblock_t),
753                                XCHK_GFP_FLAGS);
754         if (!sai.entries) {
755                 error = -ENOMEM;
756                 goto out;
757         }
758 
759         /* Check the blocks in the AGFL. */
760         error = xfs_agfl_walk(sc->mp, sc->sa.agf_bp->b_addr, sai.agfl_bp,
761                         xchk_agfl_block, &sai);
762         if (error == -ECANCELED) {
763                 error = 0;
764                 goto out_free;
765         }
766         if (error)
767                 goto out_free;
768 
769         if (sai.agflcount != sai.nr_entries) {
770                 xchk_block_set_corrupt(sc, sc->sa.agf_bp);
771                 goto out_free;
772         }
773 
774         /* Sort entries, check for duplicates. */
775         sort(sai.entries, sai.nr_entries, sizeof(sai.entries[0]),
776                         xchk_agblock_cmp, NULL);
777         for (i = 1; i < sai.nr_entries; i++) {
778                 if (sai.entries[i] == sai.entries[i - 1]) {
779                         xchk_block_set_corrupt(sc, sc->sa.agf_bp);
780                         break;
781                 }
782         }
783 
784 out_free:
785         kvfree(sai.entries);
786 out:
787         return error;
788 }
789 
790 /* AGI */
791 
792 /* Check agi_count/agi_freecount */
793 static inline void
794 xchk_agi_xref_icounts(
795         struct xfs_scrub        *sc)
796 {
797         struct xfs_agi          *agi = sc->sa.agi_bp->b_addr;
798         xfs_agino_t             icount;
799         xfs_agino_t             freecount;
800         int                     error;
801 
802         if (!sc->sa.ino_cur)
803                 return;
804 
805         error = xfs_ialloc_count_inodes(sc->sa.ino_cur, &icount, &freecount);
806         if (!xchk_should_check_xref(sc, &error, &sc->sa.ino_cur))
807                 return;
808         if (be32_to_cpu(agi->agi_count) != icount ||
809             be32_to_cpu(agi->agi_freecount) != freecount)
810                 xchk_block_xref_set_corrupt(sc, sc->sa.agi_bp);
811 }
812 
813 /* Check agi_[fi]blocks against tree size */
814 static inline void
815 xchk_agi_xref_fiblocks(
816         struct xfs_scrub        *sc)
817 {
818         struct xfs_agi          *agi = sc->sa.agi_bp->b_addr;
819         xfs_agblock_t           blocks;
820         int                     error = 0;
821 
822         if (!xfs_has_inobtcounts(sc->mp))
823                 return;
824 
825         if (sc->sa.ino_cur) {
826                 error = xfs_btree_count_blocks(sc->sa.ino_cur, &blocks);
827                 if (!xchk_should_check_xref(sc, &error, &sc->sa.ino_cur))
828                         return;
829                 if (blocks != be32_to_cpu(agi->agi_iblocks))
830                         xchk_block_xref_set_corrupt(sc, sc->sa.agi_bp);
831         }
832 
833         if (sc->sa.fino_cur) {
834                 error = xfs_btree_count_blocks(sc->sa.fino_cur, &blocks);
835                 if (!xchk_should_check_xref(sc, &error, &sc->sa.fino_cur))
836                         return;
837                 if (blocks != be32_to_cpu(agi->agi_fblocks))
838                         xchk_block_xref_set_corrupt(sc, sc->sa.agi_bp);
839         }
840 }
841 
842 /* Cross-reference with the other btrees. */
843 STATIC void
844 xchk_agi_xref(
845         struct xfs_scrub        *sc)
846 {
847         struct xfs_mount        *mp = sc->mp;
848         xfs_agblock_t           agbno;
849 
850         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
851                 return;
852 
853         agbno = XFS_AGI_BLOCK(mp);
854 
855         xchk_ag_btcur_init(sc, &sc->sa);
856 
857         xchk_xref_is_used_space(sc, agbno, 1);
858         xchk_xref_is_not_inode_chunk(sc, agbno, 1);
859         xchk_agi_xref_icounts(sc);
860         xchk_xref_is_only_owned_by(sc, agbno, 1, &XFS_RMAP_OINFO_FS);
861         xchk_xref_is_not_shared(sc, agbno, 1);
862         xchk_xref_is_not_cow_staging(sc, agbno, 1);
863         xchk_agi_xref_fiblocks(sc);
864 
865         /* scrub teardown will take care of sc->sa for us */
866 }
867 
868 /*
869  * Check the unlinked buckets for links to bad inodes.  We hold the AGI, so
870  * there cannot be any threads updating unlinked list pointers in this AG.
871  */
872 STATIC void
873 xchk_iunlink(
874         struct xfs_scrub        *sc,
875         struct xfs_agi          *agi)
876 {
877         unsigned int            i;
878         struct xfs_inode        *ip;
879 
880         for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++) {
881                 xfs_agino_t     agino = be32_to_cpu(agi->agi_unlinked[i]);
882 
883                 while (agino != NULLAGINO) {
884                         if (agino % XFS_AGI_UNLINKED_BUCKETS != i) {
885                                 xchk_block_set_corrupt(sc, sc->sa.agi_bp);
886                                 return;
887                         }
888 
889                         ip = xfs_iunlink_lookup(sc->sa.pag, agino);
890                         if (!ip) {
891                                 xchk_block_set_corrupt(sc, sc->sa.agi_bp);
892                                 return;
893                         }
894 
895                         if (!xfs_inode_on_unlinked_list(ip)) {
896                                 xchk_block_set_corrupt(sc, sc->sa.agi_bp);
897                                 return;
898                         }
899 
900                         agino = ip->i_next_unlinked;
901                 }
902         }
903 }
904 
905 /* Scrub the AGI. */
906 int
907 xchk_agi(
908         struct xfs_scrub        *sc)
909 {
910         struct xfs_mount        *mp = sc->mp;
911         struct xfs_agi          *agi;
912         struct xfs_perag        *pag;
913         struct xfs_ino_geometry *igeo = M_IGEO(sc->mp);
914         xfs_agnumber_t          agno = sc->sm->sm_agno;
915         xfs_agblock_t           agbno;
916         xfs_agblock_t           eoag;
917         xfs_agino_t             agino;
918         xfs_agino_t             first_agino;
919         xfs_agino_t             last_agino;
920         xfs_agino_t             icount;
921         int                     i;
922         int                     level;
923         int                     error = 0;
924 
925         error = xchk_ag_read_headers(sc, agno, &sc->sa);
926         if (!xchk_process_error(sc, agno, XFS_AGI_BLOCK(sc->mp), &error))
927                 goto out;
928         xchk_buffer_recheck(sc, sc->sa.agi_bp);
929 
930         agi = sc->sa.agi_bp->b_addr;
931         pag = sc->sa.pag;
932 
933         /* Check the AG length */
934         eoag = be32_to_cpu(agi->agi_length);
935         if (eoag != pag->block_count)
936                 xchk_block_set_corrupt(sc, sc->sa.agi_bp);
937 
938         /* Check btree roots and levels */
939         agbno = be32_to_cpu(agi->agi_root);
940         if (!xfs_verify_agbno(pag, agbno))
941                 xchk_block_set_corrupt(sc, sc->sa.agi_bp);
942 
943         level = be32_to_cpu(agi->agi_level);
944         if (level <= 0 || level > igeo->inobt_maxlevels)
945                 xchk_block_set_corrupt(sc, sc->sa.agi_bp);
946 
947         if (xfs_has_finobt(mp)) {
948                 agbno = be32_to_cpu(agi->agi_free_root);
949                 if (!xfs_verify_agbno(pag, agbno))
950                         xchk_block_set_corrupt(sc, sc->sa.agi_bp);
951 
952                 level = be32_to_cpu(agi->agi_free_level);
953                 if (level <= 0 || level > igeo->inobt_maxlevels)
954                         xchk_block_set_corrupt(sc, sc->sa.agi_bp);
955         }
956 
957         /* Check inode counters */
958         xfs_agino_range(mp, agno, &first_agino, &last_agino);
959         icount = be32_to_cpu(agi->agi_count);
960         if (icount > last_agino - first_agino + 1 ||
961             icount < be32_to_cpu(agi->agi_freecount))
962                 xchk_block_set_corrupt(sc, sc->sa.agi_bp);
963 
964         /* Check inode pointers */
965         agino = be32_to_cpu(agi->agi_newino);
966         if (!xfs_verify_agino_or_null(pag, agino))
967                 xchk_block_set_corrupt(sc, sc->sa.agi_bp);
968 
969         agino = be32_to_cpu(agi->agi_dirino);
970         if (!xfs_verify_agino_or_null(pag, agino))
971                 xchk_block_set_corrupt(sc, sc->sa.agi_bp);
972 
973         /* Check unlinked inode buckets */
974         for (i = 0; i < XFS_AGI_UNLINKED_BUCKETS; i++) {
975                 agino = be32_to_cpu(agi->agi_unlinked[i]);
976                 if (!xfs_verify_agino_or_null(pag, agino))
977                         xchk_block_set_corrupt(sc, sc->sa.agi_bp);
978         }
979 
980         if (agi->agi_pad32 != cpu_to_be32(0))
981                 xchk_block_set_corrupt(sc, sc->sa.agi_bp);
982 
983         /* Do the incore counters match? */
984         if (pag->pagi_count != be32_to_cpu(agi->agi_count))
985                 xchk_block_set_corrupt(sc, sc->sa.agi_bp);
986         if (pag->pagi_freecount != be32_to_cpu(agi->agi_freecount))
987                 xchk_block_set_corrupt(sc, sc->sa.agi_bp);
988 
989         xchk_iunlink(sc, agi);
990 
991         xchk_agi_xref(sc);
992 out:
993         return error;
994 }
995 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

sflogo.php