LCOV - code coverage report
Current view: top level - fs/xfs/scrub - alloc.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-achx @ Mon Jul 31 20:08:12 PDT 2023 Lines: 65 75 86.7 %
Date: 2023-07-31 20:08:12 Functions: 9 9 100.0 %

          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_log_format.h"
      13             : #include "xfs_trans.h"
      14             : #include "xfs_btree.h"
      15             : #include "xfs_alloc.h"
      16             : #include "xfs_rmap.h"
      17             : #include "xfs_ag.h"
      18             : #include "scrub/scrub.h"
      19             : #include "scrub/common.h"
      20             : #include "scrub/btree.h"
      21             : #include "scrub/repair.h"
      22             : 
      23             : /*
      24             :  * Set us up to scrub free space btrees.
      25             :  */
      26             : int
      27      715991 : xchk_setup_ag_allocbt(
      28             :         struct xfs_scrub        *sc)
      29             : {
      30      715991 :         int                     error;
      31             : 
      32      715991 :         if (xchk_need_intent_drain(sc))
      33       12229 :                 xchk_fsgates_enable(sc, XCHK_FSGATES_DRAIN);
      34             : 
      35      715991 :         error = xchk_setup_ag_btree(sc, false);
      36      716831 :         if (error)
      37             :                 return error;
      38             : 
      39     1409986 :         if (xchk_could_repair(sc))
      40       54691 :                 return xrep_setup_ag_allocbt(sc);
      41             : 
      42             :         return 0;
      43             : }
      44             : 
      45             : /* Free space btree scrubber. */
      46             : 
      47             : struct xchk_alloc {
      48             :         /* Previous free space extent. */
      49             :         struct xfs_alloc_rec_incore     prev;
      50             : };
      51             : 
      52             : /*
      53             :  * Ensure there's a corresponding cntbt/bnobt record matching this
      54             :  * bnobt/cntbt record, respectively.
      55             :  */
      56             : STATIC void
      57   444955273 : xchk_allocbt_xref_other(
      58             :         struct xfs_scrub        *sc,
      59             :         xfs_agblock_t           agbno,
      60             :         xfs_extlen_t            len)
      61             : {
      62   444955273 :         struct xfs_btree_cur    **pcur;
      63   444955273 :         xfs_agblock_t           fbno;
      64   444955273 :         xfs_extlen_t            flen;
      65   444955273 :         int                     has_otherrec;
      66   444955273 :         int                     error;
      67             : 
      68   444955273 :         if (sc->sm->sm_type == XFS_SCRUB_TYPE_BNOBT)
      69   241411259 :                 pcur = &sc->sa.cnt_cur;
      70             :         else
      71   203544014 :                 pcur = &sc->sa.bno_cur;
      72   444955273 :         if (!*pcur || xchk_skip_xref(sc->sm))
      73       32471 :                 return;
      74             : 
      75   444922802 :         error = xfs_alloc_lookup_le(*pcur, agbno, len, &has_otherrec);
      76   444932243 :         if (!xchk_should_check_xref(sc, &error, pcur))
      77             :                 return;
      78   444921813 :         if (!has_otherrec) {
      79           0 :                 xchk_btree_xref_set_corrupt(sc, *pcur, 0);
      80           0 :                 return;
      81             :         }
      82             : 
      83   444921813 :         error = xfs_alloc_get_rec(*pcur, &fbno, &flen, &has_otherrec);
      84   444896054 :         if (!xchk_should_check_xref(sc, &error, pcur))
      85             :                 return;
      86   444906299 :         if (!has_otherrec) {
      87           0 :                 xchk_btree_xref_set_corrupt(sc, *pcur, 0);
      88           0 :                 return;
      89             :         }
      90             : 
      91   444906299 :         if (fbno != agbno || flen != len)
      92        1176 :                 xchk_btree_xref_set_corrupt(sc, *pcur, 0);
      93             : }
      94             : 
      95             : /* Cross-reference with the other btrees. */
      96             : STATIC void
      97   444890507 : xchk_allocbt_xref(
      98             :         struct xfs_scrub        *sc,
      99             :         const struct xfs_alloc_rec_incore *irec)
     100             : {
     101   444890507 :         xfs_agblock_t           agbno = irec->ar_startblock;
     102   444890507 :         xfs_extlen_t            len = irec->ar_blockcount;
     103             : 
     104   444890507 :         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     105             :                 return;
     106             : 
     107   444893979 :         xchk_allocbt_xref_other(sc, agbno, len);
     108   444935285 :         xchk_xref_is_not_inode_chunk(sc, agbno, len);
     109   444954120 :         xchk_xref_has_no_owner(sc, agbno, len);
     110   444939143 :         xchk_xref_is_not_shared(sc, agbno, len);
     111   444931338 :         xchk_xref_is_not_cow_staging(sc, agbno, len);
     112             : }
     113             : 
     114             : /* Flag failures for records that could be merged. */
     115             : STATIC void
     116   444905088 : xchk_allocbt_mergeable(
     117             :         struct xchk_btree       *bs,
     118             :         struct xchk_alloc       *ca,
     119             :         const struct xfs_alloc_rec_incore *irec)
     120             : {
     121   444905088 :         if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
     122             :                 return;
     123             : 
     124   444905088 :         if (ca->prev.ar_blockcount > 0 &&
     125   444148047 :             ca->prev.ar_startblock + ca->prev.ar_blockcount == irec->ar_startblock &&
     126           0 :             ca->prev.ar_blockcount + irec->ar_blockcount < (uint32_t)~0U)
     127           0 :                 xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
     128             : 
     129   889810176 :         memcpy(&ca->prev, irec, sizeof(*irec));
     130             : }
     131             : 
     132             : /* Scrub a bnobt/cntbt record. */
     133             : STATIC int
     134   444914416 : xchk_allocbt_rec(
     135             :         struct xchk_btree               *bs,
     136             :         const union xfs_btree_rec       *rec)
     137             : {
     138   444914416 :         struct xfs_alloc_rec_incore     irec;
     139   444914416 :         struct xchk_alloc       *ca = bs->private;
     140             : 
     141   444914416 :         xfs_alloc_btrec_to_irec(rec, &irec);
     142   444872823 :         if (xfs_alloc_check_irec(bs->cur, &irec) != NULL) {
     143           0 :                 xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
     144           0 :                 return 0;
     145             :         }
     146             : 
     147   444888428 :         xchk_allocbt_mergeable(bs, ca, &irec);
     148   444890668 :         xchk_allocbt_xref(bs->sc, &irec);
     149             : 
     150   444890668 :         return 0;
     151             : }
     152             : 
     153             : /* Scrub the freespace btrees for some AG. */
     154             : STATIC int
     155      744058 : xchk_allocbt(
     156             :         struct xfs_scrub        *sc,
     157             :         xfs_btnum_t             which)
     158             : {
     159      744058 :         struct xchk_alloc       ca = { };
     160      744058 :         struct xfs_btree_cur    *cur;
     161             : 
     162      744058 :         cur = which == XFS_BTNUM_BNO ? sc->sa.bno_cur : sc->sa.cnt_cur;
     163      744058 :         return xchk_btree(sc, cur, xchk_allocbt_rec, &XFS_RMAP_OINFO_AG, &ca);
     164             : }
     165             : 
     166             : int
     167      379679 : xchk_bnobt(
     168             :         struct xfs_scrub        *sc)
     169             : {
     170      379679 :         return xchk_allocbt(sc, XFS_BTNUM_BNO);
     171             : }
     172             : 
     173             : int
     174      365207 : xchk_cntbt(
     175             :         struct xfs_scrub        *sc)
     176             : {
     177      365207 :         return xchk_allocbt(sc, XFS_BTNUM_CNT);
     178             : }
     179             : 
     180             : /* xref check that the extent is not free */
     181             : void
     182  1385653425 : xchk_xref_is_used_space(
     183             :         struct xfs_scrub        *sc,
     184             :         xfs_agblock_t           agbno,
     185             :         xfs_extlen_t            len)
     186             : {
     187  1385653425 :         enum xbtree_recpacking  outcome;
     188  1385653425 :         int                     error;
     189             : 
     190  1385653425 :         if (!sc->sa.bno_cur || xchk_skip_xref(sc->sm))
     191           0 :                 return;
     192             : 
     193  1385653425 :         error = xfs_alloc_has_records(sc->sa.bno_cur, agbno, len, &outcome);
     194  1386309786 :         if (!xchk_should_check_xref(sc, &error, &sc->sa.bno_cur))
     195             :                 return;
     196  1384872164 :         if (outcome != XBTREE_RECPACKING_EMPTY)
     197           0 :                 xchk_btree_xref_set_corrupt(sc, sc->sa.bno_cur, 0);
     198             : }

Generated by: LCOV version 1.14