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

TOMOYO Linux Cross Reference
Linux/fs/xfs/scrub/alloc.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_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 xchk_setup_ag_allocbt(
 28         struct xfs_scrub        *sc)
 29 {
 30         int                     error;
 31 
 32         if (xchk_need_intent_drain(sc))
 33                 xchk_fsgates_enable(sc, XCHK_FSGATES_DRAIN);
 34 
 35         error = xchk_setup_ag_btree(sc, false);
 36         if (error)
 37                 return error;
 38 
 39         if (xchk_could_repair(sc))
 40                 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 xchk_allocbt_xref_other(
 58         struct xfs_scrub        *sc,
 59         xfs_agblock_t           agbno,
 60         xfs_extlen_t            len)
 61 {
 62         struct xfs_btree_cur    **pcur;
 63         xfs_agblock_t           fbno;
 64         xfs_extlen_t            flen;
 65         int                     has_otherrec;
 66         int                     error;
 67 
 68         if (sc->sm->sm_type == XFS_SCRUB_TYPE_BNOBT)
 69                 pcur = &sc->sa.cnt_cur;
 70         else
 71                 pcur = &sc->sa.bno_cur;
 72         if (!*pcur || xchk_skip_xref(sc->sm))
 73                 return;
 74 
 75         error = xfs_alloc_lookup_le(*pcur, agbno, len, &has_otherrec);
 76         if (!xchk_should_check_xref(sc, &error, pcur))
 77                 return;
 78         if (!has_otherrec) {
 79                 xchk_btree_xref_set_corrupt(sc, *pcur, 0);
 80                 return;
 81         }
 82 
 83         error = xfs_alloc_get_rec(*pcur, &fbno, &flen, &has_otherrec);
 84         if (!xchk_should_check_xref(sc, &error, pcur))
 85                 return;
 86         if (!has_otherrec) {
 87                 xchk_btree_xref_set_corrupt(sc, *pcur, 0);
 88                 return;
 89         }
 90 
 91         if (fbno != agbno || flen != len)
 92                 xchk_btree_xref_set_corrupt(sc, *pcur, 0);
 93 }
 94 
 95 /* Cross-reference with the other btrees. */
 96 STATIC void
 97 xchk_allocbt_xref(
 98         struct xfs_scrub        *sc,
 99         const struct xfs_alloc_rec_incore *irec)
100 {
101         xfs_agblock_t           agbno = irec->ar_startblock;
102         xfs_extlen_t            len = irec->ar_blockcount;
103 
104         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
105                 return;
106 
107         xchk_allocbt_xref_other(sc, agbno, len);
108         xchk_xref_is_not_inode_chunk(sc, agbno, len);
109         xchk_xref_has_no_owner(sc, agbno, len);
110         xchk_xref_is_not_shared(sc, agbno, len);
111         xchk_xref_is_not_cow_staging(sc, agbno, len);
112 }
113 
114 /* Flag failures for records that could be merged. */
115 STATIC void
116 xchk_allocbt_mergeable(
117         struct xchk_btree       *bs,
118         struct xchk_alloc       *ca,
119         const struct xfs_alloc_rec_incore *irec)
120 {
121         if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
122                 return;
123 
124         if (ca->prev.ar_blockcount > 0 &&
125             ca->prev.ar_startblock + ca->prev.ar_blockcount == irec->ar_startblock &&
126             ca->prev.ar_blockcount + irec->ar_blockcount < (uint32_t)~0U)
127                 xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
128 
129         memcpy(&ca->prev, irec, sizeof(*irec));
130 }
131 
132 /* Scrub a bnobt/cntbt record. */
133 STATIC int
134 xchk_allocbt_rec(
135         struct xchk_btree               *bs,
136         const union xfs_btree_rec       *rec)
137 {
138         struct xfs_alloc_rec_incore     irec;
139         struct xchk_alloc       *ca = bs->private;
140 
141         xfs_alloc_btrec_to_irec(rec, &irec);
142         if (xfs_alloc_check_irec(bs->cur->bc_ag.pag, &irec) != NULL) {
143                 xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
144                 return 0;
145         }
146 
147         xchk_allocbt_mergeable(bs, ca, &irec);
148         xchk_allocbt_xref(bs->sc, &irec);
149 
150         return 0;
151 }
152 
153 /* Scrub one of the freespace btrees for some AG. */
154 int
155 xchk_allocbt(
156         struct xfs_scrub        *sc)
157 {
158         struct xchk_alloc       ca = { };
159         struct xfs_btree_cur    *cur;
160 
161         switch (sc->sm->sm_type) {
162         case XFS_SCRUB_TYPE_BNOBT:
163                 cur = sc->sa.bno_cur;
164                 break;
165         case XFS_SCRUB_TYPE_CNTBT:
166                 cur = sc->sa.cnt_cur;
167                 break;
168         default:
169                 ASSERT(0);
170                 return -EIO;
171         }
172 
173         return xchk_btree(sc, cur, xchk_allocbt_rec, &XFS_RMAP_OINFO_AG, &ca);
174 }
175 
176 /* xref check that the extent is not free */
177 void
178 xchk_xref_is_used_space(
179         struct xfs_scrub        *sc,
180         xfs_agblock_t           agbno,
181         xfs_extlen_t            len)
182 {
183         enum xbtree_recpacking  outcome;
184         int                     error;
185 
186         if (!sc->sa.bno_cur || xchk_skip_xref(sc->sm))
187                 return;
188 
189         error = xfs_alloc_has_records(sc->sa.bno_cur, agbno, len, &outcome);
190         if (!xchk_should_check_xref(sc, &error, &sc->sa.bno_cur))
191                 return;
192         if (outcome != XBTREE_RECPACKING_EMPTY)
193                 xchk_btree_xref_set_corrupt(sc, sc->sa.bno_cur, 0);
194 }
195 

~ [ 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