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

TOMOYO Linux Cross Reference
Linux/fs/xfs/scrub/rmap.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_log_format.h"
 11 #include "xfs_trans_resv.h"
 12 #include "xfs_mount.h"
 13 #include "xfs_trans.h"
 14 #include "xfs_btree.h"
 15 #include "xfs_rmap.h"
 16 #include "xfs_refcount.h"
 17 #include "xfs_ag.h"
 18 #include "xfs_bit.h"
 19 #include "xfs_alloc.h"
 20 #include "xfs_alloc_btree.h"
 21 #include "xfs_ialloc_btree.h"
 22 #include "xfs_refcount_btree.h"
 23 #include "scrub/scrub.h"
 24 #include "scrub/common.h"
 25 #include "scrub/btree.h"
 26 #include "scrub/bitmap.h"
 27 #include "scrub/agb_bitmap.h"
 28 #include "scrub/repair.h"
 29 
 30 /*
 31  * Set us up to scrub reverse mapping btrees.
 32  */
 33 int
 34 xchk_setup_ag_rmapbt(
 35         struct xfs_scrub        *sc)
 36 {
 37         if (xchk_need_intent_drain(sc))
 38                 xchk_fsgates_enable(sc, XCHK_FSGATES_DRAIN);
 39 
 40         if (xchk_could_repair(sc)) {
 41                 int             error;
 42 
 43                 error = xrep_setup_ag_rmapbt(sc);
 44                 if (error)
 45                         return error;
 46         }
 47 
 48         return xchk_setup_ag_btree(sc, false);
 49 }
 50 
 51 /* Reverse-mapping scrubber. */
 52 
 53 struct xchk_rmap {
 54         /*
 55          * The furthest-reaching of the rmapbt records that we've already
 56          * processed.  This enables us to detect overlapping records for space
 57          * allocations that cannot be shared.
 58          */
 59         struct xfs_rmap_irec    overlap_rec;
 60 
 61         /*
 62          * The previous rmapbt record, so that we can check for two records
 63          * that could be one.
 64          */
 65         struct xfs_rmap_irec    prev_rec;
 66 
 67         /* Bitmaps containing all blocks for each type of AG metadata. */
 68         struct xagb_bitmap      fs_owned;
 69         struct xagb_bitmap      log_owned;
 70         struct xagb_bitmap      ag_owned;
 71         struct xagb_bitmap      inobt_owned;
 72         struct xagb_bitmap      refcbt_owned;
 73 
 74         /* Did we complete the AG space metadata bitmaps? */
 75         bool                    bitmaps_complete;
 76 };
 77 
 78 /* Cross-reference a rmap against the refcount btree. */
 79 STATIC void
 80 xchk_rmapbt_xref_refc(
 81         struct xfs_scrub        *sc,
 82         struct xfs_rmap_irec    *irec)
 83 {
 84         xfs_agblock_t           fbno;
 85         xfs_extlen_t            flen;
 86         bool                    non_inode;
 87         bool                    is_bmbt;
 88         bool                    is_attr;
 89         bool                    is_unwritten;
 90         int                     error;
 91 
 92         if (!sc->sa.refc_cur || xchk_skip_xref(sc->sm))
 93                 return;
 94 
 95         non_inode = XFS_RMAP_NON_INODE_OWNER(irec->rm_owner);
 96         is_bmbt = irec->rm_flags & XFS_RMAP_BMBT_BLOCK;
 97         is_attr = irec->rm_flags & XFS_RMAP_ATTR_FORK;
 98         is_unwritten = irec->rm_flags & XFS_RMAP_UNWRITTEN;
 99 
100         /* If this is shared, must be a data fork extent. */
101         error = xfs_refcount_find_shared(sc->sa.refc_cur, irec->rm_startblock,
102                         irec->rm_blockcount, &fbno, &flen, false);
103         if (!xchk_should_check_xref(sc, &error, &sc->sa.refc_cur))
104                 return;
105         if (flen != 0 && (non_inode || is_attr || is_bmbt || is_unwritten))
106                 xchk_btree_xref_set_corrupt(sc, sc->sa.refc_cur, 0);
107 }
108 
109 /* Cross-reference with the other btrees. */
110 STATIC void
111 xchk_rmapbt_xref(
112         struct xfs_scrub        *sc,
113         struct xfs_rmap_irec    *irec)
114 {
115         xfs_agblock_t           agbno = irec->rm_startblock;
116         xfs_extlen_t            len = irec->rm_blockcount;
117 
118         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
119                 return;
120 
121         xchk_xref_is_used_space(sc, agbno, len);
122         if (irec->rm_owner == XFS_RMAP_OWN_INODES)
123                 xchk_xref_is_inode_chunk(sc, agbno, len);
124         else
125                 xchk_xref_is_not_inode_chunk(sc, agbno, len);
126         if (irec->rm_owner == XFS_RMAP_OWN_COW)
127                 xchk_xref_is_cow_staging(sc, irec->rm_startblock,
128                                 irec->rm_blockcount);
129         else
130                 xchk_rmapbt_xref_refc(sc, irec);
131 }
132 
133 /*
134  * Check for bogus UNWRITTEN flags in the rmapbt node block keys.
135  *
136  * In reverse mapping records, the file mapping extent state
137  * (XFS_RMAP_OFF_UNWRITTEN) is a record attribute, not a key field.  It is not
138  * involved in lookups in any way.  In older kernels, the functions that
139  * convert rmapbt records to keys forgot to filter out the extent state bit,
140  * even though the key comparison functions have filtered the flag correctly.
141  * If we spot an rmap key with the unwritten bit set in rm_offset, we should
142  * mark the btree as needing optimization to rebuild the btree without those
143  * flags.
144  */
145 STATIC void
146 xchk_rmapbt_check_unwritten_in_keyflags(
147         struct xchk_btree       *bs)
148 {
149         struct xfs_scrub        *sc = bs->sc;
150         struct xfs_btree_cur    *cur = bs->cur;
151         struct xfs_btree_block  *keyblock;
152         union xfs_btree_key     *lkey, *hkey;
153         __be64                  badflag = cpu_to_be64(XFS_RMAP_OFF_UNWRITTEN);
154         unsigned int            level;
155 
156         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_PREEN)
157                 return;
158 
159         for (level = 1; level < cur->bc_nlevels; level++) {
160                 struct xfs_buf  *bp;
161                 unsigned int    ptr;
162 
163                 /* Only check the first time we've seen this node block. */
164                 if (cur->bc_levels[level].ptr > 1)
165                         continue;
166 
167                 keyblock = xfs_btree_get_block(cur, level, &bp);
168                 for (ptr = 1; ptr <= be16_to_cpu(keyblock->bb_numrecs); ptr++) {
169                         lkey = xfs_btree_key_addr(cur, ptr, keyblock);
170 
171                         if (lkey->rmap.rm_offset & badflag) {
172                                 xchk_btree_set_preen(sc, cur, level);
173                                 break;
174                         }
175 
176                         hkey = xfs_btree_high_key_addr(cur, ptr, keyblock);
177                         if (hkey->rmap.rm_offset & badflag) {
178                                 xchk_btree_set_preen(sc, cur, level);
179                                 break;
180                         }
181                 }
182         }
183 }
184 
185 static inline bool
186 xchk_rmapbt_is_shareable(
187         struct xfs_scrub                *sc,
188         const struct xfs_rmap_irec      *irec)
189 {
190         if (!xfs_has_reflink(sc->mp))
191                 return false;
192         if (XFS_RMAP_NON_INODE_OWNER(irec->rm_owner))
193                 return false;
194         if (irec->rm_flags & (XFS_RMAP_BMBT_BLOCK | XFS_RMAP_ATTR_FORK |
195                               XFS_RMAP_UNWRITTEN))
196                 return false;
197         return true;
198 }
199 
200 /* Flag failures for records that overlap but cannot. */
201 STATIC void
202 xchk_rmapbt_check_overlapping(
203         struct xchk_btree               *bs,
204         struct xchk_rmap                *cr,
205         const struct xfs_rmap_irec      *irec)
206 {
207         xfs_agblock_t                   pnext, inext;
208 
209         if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
210                 return;
211 
212         /* No previous record? */
213         if (cr->overlap_rec.rm_blockcount == 0)
214                 goto set_prev;
215 
216         /* Do overlap_rec and irec overlap? */
217         pnext = cr->overlap_rec.rm_startblock + cr->overlap_rec.rm_blockcount;
218         if (pnext <= irec->rm_startblock)
219                 goto set_prev;
220 
221         /* Overlap is only allowed if both records are data fork mappings. */
222         if (!xchk_rmapbt_is_shareable(bs->sc, &cr->overlap_rec) ||
223             !xchk_rmapbt_is_shareable(bs->sc, irec))
224                 xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
225 
226         /* Save whichever rmap record extends furthest. */
227         inext = irec->rm_startblock + irec->rm_blockcount;
228         if (pnext > inext)
229                 return;
230 
231 set_prev:
232         memcpy(&cr->overlap_rec, irec, sizeof(struct xfs_rmap_irec));
233 }
234 
235 /* Decide if two reverse-mapping records can be merged. */
236 static inline bool
237 xchk_rmap_mergeable(
238         struct xchk_rmap                *cr,
239         const struct xfs_rmap_irec      *r2)
240 {
241         const struct xfs_rmap_irec      *r1 = &cr->prev_rec;
242 
243         /* Ignore if prev_rec is not yet initialized. */
244         if (cr->prev_rec.rm_blockcount == 0)
245                 return false;
246 
247         if (r1->rm_owner != r2->rm_owner)
248                 return false;
249         if (r1->rm_startblock + r1->rm_blockcount != r2->rm_startblock)
250                 return false;
251         if ((unsigned long long)r1->rm_blockcount + r2->rm_blockcount >
252             XFS_RMAP_LEN_MAX)
253                 return false;
254         if (XFS_RMAP_NON_INODE_OWNER(r2->rm_owner))
255                 return true;
256         /* must be an inode owner below here */
257         if (r1->rm_flags != r2->rm_flags)
258                 return false;
259         if (r1->rm_flags & XFS_RMAP_BMBT_BLOCK)
260                 return true;
261         return r1->rm_offset + r1->rm_blockcount == r2->rm_offset;
262 }
263 
264 /* Flag failures for records that could be merged. */
265 STATIC void
266 xchk_rmapbt_check_mergeable(
267         struct xchk_btree               *bs,
268         struct xchk_rmap                *cr,
269         const struct xfs_rmap_irec      *irec)
270 {
271         if (bs->sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
272                 return;
273 
274         if (xchk_rmap_mergeable(cr, irec))
275                 xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
276 
277         memcpy(&cr->prev_rec, irec, sizeof(struct xfs_rmap_irec));
278 }
279 
280 /* Compare an rmap for AG metadata against the metadata walk. */
281 STATIC int
282 xchk_rmapbt_mark_bitmap(
283         struct xchk_btree               *bs,
284         struct xchk_rmap                *cr,
285         const struct xfs_rmap_irec      *irec)
286 {
287         struct xfs_scrub                *sc = bs->sc;
288         struct xagb_bitmap              *bmp = NULL;
289         xfs_extlen_t                    fsbcount = irec->rm_blockcount;
290 
291         /*
292          * Skip corrupt records.  It is essential that we detect records in the
293          * btree that cannot overlap but do, flag those as CORRUPT, and skip
294          * the bitmap comparison to avoid generating false XCORRUPT reports.
295          */
296         if (sc->sm->sm_flags & XFS_SCRUB_OFLAG_CORRUPT)
297                 return 0;
298 
299         /*
300          * If the AG metadata walk didn't complete, there's no point in
301          * comparing against partial results.
302          */
303         if (!cr->bitmaps_complete)
304                 return 0;
305 
306         switch (irec->rm_owner) {
307         case XFS_RMAP_OWN_FS:
308                 bmp = &cr->fs_owned;
309                 break;
310         case XFS_RMAP_OWN_LOG:
311                 bmp = &cr->log_owned;
312                 break;
313         case XFS_RMAP_OWN_AG:
314                 bmp = &cr->ag_owned;
315                 break;
316         case XFS_RMAP_OWN_INOBT:
317                 bmp = &cr->inobt_owned;
318                 break;
319         case XFS_RMAP_OWN_REFC:
320                 bmp = &cr->refcbt_owned;
321                 break;
322         }
323 
324         if (!bmp)
325                 return 0;
326 
327         if (xagb_bitmap_test(bmp, irec->rm_startblock, &fsbcount)) {
328                 /*
329                  * The start of this reverse mapping corresponds to a set
330                  * region in the bitmap.  If the mapping covers more area than
331                  * the set region, then it covers space that wasn't found by
332                  * the AG metadata walk.
333                  */
334                 if (fsbcount < irec->rm_blockcount)
335                         xchk_btree_xref_set_corrupt(bs->sc,
336                                         bs->sc->sa.rmap_cur, 0);
337         } else {
338                 /*
339                  * The start of this reverse mapping does not correspond to a
340                  * completely set region in the bitmap.  The region wasn't
341                  * fully set by walking the AG metadata, so this is a
342                  * cross-referencing corruption.
343                  */
344                 xchk_btree_xref_set_corrupt(bs->sc, bs->sc->sa.rmap_cur, 0);
345         }
346 
347         /* Unset the region so that we can detect missing rmap records. */
348         return xagb_bitmap_clear(bmp, irec->rm_startblock, irec->rm_blockcount);
349 }
350 
351 /* Scrub an rmapbt record. */
352 STATIC int
353 xchk_rmapbt_rec(
354         struct xchk_btree       *bs,
355         const union xfs_btree_rec *rec)
356 {
357         struct xchk_rmap        *cr = bs->private;
358         struct xfs_rmap_irec    irec;
359 
360         if (xfs_rmap_btrec_to_irec(rec, &irec) != NULL ||
361             xfs_rmap_check_irec(bs->cur->bc_ag.pag, &irec) != NULL) {
362                 xchk_btree_set_corrupt(bs->sc, bs->cur, 0);
363                 return 0;
364         }
365 
366         xchk_rmapbt_check_unwritten_in_keyflags(bs);
367         xchk_rmapbt_check_mergeable(bs, cr, &irec);
368         xchk_rmapbt_check_overlapping(bs, cr, &irec);
369         xchk_rmapbt_xref(bs->sc, &irec);
370 
371         return xchk_rmapbt_mark_bitmap(bs, cr, &irec);
372 }
373 
374 /* Add an AGFL block to the rmap list. */
375 STATIC int
376 xchk_rmapbt_walk_agfl(
377         struct xfs_mount        *mp,
378         xfs_agblock_t           agbno,
379         void                    *priv)
380 {
381         struct xagb_bitmap      *bitmap = priv;
382 
383         return xagb_bitmap_set(bitmap, agbno, 1);
384 }
385 
386 /*
387  * Set up bitmaps mapping all the AG metadata to compare with the rmapbt
388  * records.
389  *
390  * Grab our own btree cursors here if the scrub setup function didn't give us a
391  * btree cursor due to reports of poor health.  We need to find out if the
392  * rmapbt disagrees with primary metadata btrees to tag the rmapbt as being
393  * XCORRUPT.
394  */
395 STATIC int
396 xchk_rmapbt_walk_ag_metadata(
397         struct xfs_scrub        *sc,
398         struct xchk_rmap        *cr)
399 {
400         struct xfs_mount        *mp = sc->mp;
401         struct xfs_buf          *agfl_bp;
402         struct xfs_agf          *agf = sc->sa.agf_bp->b_addr;
403         struct xfs_btree_cur    *cur;
404         int                     error;
405 
406         /* OWN_FS: AG headers */
407         error = xagb_bitmap_set(&cr->fs_owned, XFS_SB_BLOCK(mp),
408                         XFS_AGFL_BLOCK(mp) - XFS_SB_BLOCK(mp) + 1);
409         if (error)
410                 goto out;
411 
412         /* OWN_LOG: Internal log */
413         if (xfs_ag_contains_log(mp, sc->sa.pag->pag_agno)) {
414                 error = xagb_bitmap_set(&cr->log_owned,
415                                 XFS_FSB_TO_AGBNO(mp, mp->m_sb.sb_logstart),
416                                 mp->m_sb.sb_logblocks);
417                 if (error)
418                         goto out;
419         }
420 
421         /* OWN_AG: bnobt, cntbt, rmapbt, and AGFL */
422         cur = sc->sa.bno_cur;
423         if (!cur)
424                 cur = xfs_bnobt_init_cursor(sc->mp, sc->tp, sc->sa.agf_bp,
425                                 sc->sa.pag);
426         error = xagb_bitmap_set_btblocks(&cr->ag_owned, cur);
427         if (cur != sc->sa.bno_cur)
428                 xfs_btree_del_cursor(cur, error);
429         if (error)
430                 goto out;
431 
432         cur = sc->sa.cnt_cur;
433         if (!cur)
434                 cur = xfs_cntbt_init_cursor(sc->mp, sc->tp, sc->sa.agf_bp,
435                                 sc->sa.pag);
436         error = xagb_bitmap_set_btblocks(&cr->ag_owned, cur);
437         if (cur != sc->sa.cnt_cur)
438                 xfs_btree_del_cursor(cur, error);
439         if (error)
440                 goto out;
441 
442         error = xagb_bitmap_set_btblocks(&cr->ag_owned, sc->sa.rmap_cur);
443         if (error)
444                 goto out;
445 
446         error = xfs_alloc_read_agfl(sc->sa.pag, sc->tp, &agfl_bp);
447         if (error)
448                 goto out;
449 
450         error = xfs_agfl_walk(sc->mp, agf, agfl_bp, xchk_rmapbt_walk_agfl,
451                         &cr->ag_owned);
452         xfs_trans_brelse(sc->tp, agfl_bp);
453         if (error)
454                 goto out;
455 
456         /* OWN_INOBT: inobt, finobt */
457         cur = sc->sa.ino_cur;
458         if (!cur)
459                 cur = xfs_inobt_init_cursor(sc->sa.pag, sc->tp, sc->sa.agi_bp);
460         error = xagb_bitmap_set_btblocks(&cr->inobt_owned, cur);
461         if (cur != sc->sa.ino_cur)
462                 xfs_btree_del_cursor(cur, error);
463         if (error)
464                 goto out;
465 
466         if (xfs_has_finobt(sc->mp)) {
467                 cur = sc->sa.fino_cur;
468                 if (!cur)
469                         cur = xfs_finobt_init_cursor(sc->sa.pag, sc->tp,
470                                         sc->sa.agi_bp);
471                 error = xagb_bitmap_set_btblocks(&cr->inobt_owned, cur);
472                 if (cur != sc->sa.fino_cur)
473                         xfs_btree_del_cursor(cur, error);
474                 if (error)
475                         goto out;
476         }
477 
478         /* OWN_REFC: refcountbt */
479         if (xfs_has_reflink(sc->mp)) {
480                 cur = sc->sa.refc_cur;
481                 if (!cur)
482                         cur = xfs_refcountbt_init_cursor(sc->mp, sc->tp,
483                                         sc->sa.agf_bp, sc->sa.pag);
484                 error = xagb_bitmap_set_btblocks(&cr->refcbt_owned, cur);
485                 if (cur != sc->sa.refc_cur)
486                         xfs_btree_del_cursor(cur, error);
487                 if (error)
488                         goto out;
489         }
490 
491 out:
492         /*
493          * If there's an error, set XFAIL and disable the bitmap
494          * cross-referencing checks, but proceed with the scrub anyway.
495          */
496         if (error)
497                 xchk_btree_xref_process_error(sc, sc->sa.rmap_cur,
498                                 sc->sa.rmap_cur->bc_nlevels - 1, &error);
499         else
500                 cr->bitmaps_complete = true;
501         return 0;
502 }
503 
504 /*
505  * Check for set regions in the bitmaps; if there are any, the rmap records do
506  * not describe all the AG metadata.
507  */
508 STATIC void
509 xchk_rmapbt_check_bitmaps(
510         struct xfs_scrub        *sc,
511         struct xchk_rmap        *cr)
512 {
513         struct xfs_btree_cur    *cur = sc->sa.rmap_cur;
514         unsigned int            level;
515 
516         if (sc->sm->sm_flags & (XFS_SCRUB_OFLAG_CORRUPT |
517                                 XFS_SCRUB_OFLAG_XFAIL))
518                 return;
519         if (!cur)
520                 return;
521         level = cur->bc_nlevels - 1;
522 
523         /*
524          * Any bitmap with bits still set indicates that the reverse mapping
525          * doesn't cover the entire primary structure.
526          */
527         if (xagb_bitmap_hweight(&cr->fs_owned) != 0)
528                 xchk_btree_xref_set_corrupt(sc, cur, level);
529 
530         if (xagb_bitmap_hweight(&cr->log_owned) != 0)
531                 xchk_btree_xref_set_corrupt(sc, cur, level);
532 
533         if (xagb_bitmap_hweight(&cr->ag_owned) != 0)
534                 xchk_btree_xref_set_corrupt(sc, cur, level);
535 
536         if (xagb_bitmap_hweight(&cr->inobt_owned) != 0)
537                 xchk_btree_xref_set_corrupt(sc, cur, level);
538 
539         if (xagb_bitmap_hweight(&cr->refcbt_owned) != 0)
540                 xchk_btree_xref_set_corrupt(sc, cur, level);
541 }
542 
543 /* Scrub the rmap btree for some AG. */
544 int
545 xchk_rmapbt(
546         struct xfs_scrub        *sc)
547 {
548         struct xchk_rmap        *cr;
549         int                     error;
550 
551         cr = kzalloc(sizeof(struct xchk_rmap), XCHK_GFP_FLAGS);
552         if (!cr)
553                 return -ENOMEM;
554 
555         xagb_bitmap_init(&cr->fs_owned);
556         xagb_bitmap_init(&cr->log_owned);
557         xagb_bitmap_init(&cr->ag_owned);
558         xagb_bitmap_init(&cr->inobt_owned);
559         xagb_bitmap_init(&cr->refcbt_owned);
560 
561         error = xchk_rmapbt_walk_ag_metadata(sc, cr);
562         if (error)
563                 goto out;
564 
565         error = xchk_btree(sc, sc->sa.rmap_cur, xchk_rmapbt_rec,
566                         &XFS_RMAP_OINFO_AG, cr);
567         if (error)
568                 goto out;
569 
570         xchk_rmapbt_check_bitmaps(sc, cr);
571 
572 out:
573         xagb_bitmap_destroy(&cr->refcbt_owned);
574         xagb_bitmap_destroy(&cr->inobt_owned);
575         xagb_bitmap_destroy(&cr->ag_owned);
576         xagb_bitmap_destroy(&cr->log_owned);
577         xagb_bitmap_destroy(&cr->fs_owned);
578         kfree(cr);
579         return error;
580 }
581 
582 /* xref check that the extent is owned only by a given owner */
583 void
584 xchk_xref_is_only_owned_by(
585         struct xfs_scrub                *sc,
586         xfs_agblock_t                   bno,
587         xfs_extlen_t                    len,
588         const struct xfs_owner_info     *oinfo)
589 {
590         struct xfs_rmap_matches         res;
591         int                             error;
592 
593         if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm))
594                 return;
595 
596         error = xfs_rmap_count_owners(sc->sa.rmap_cur, bno, len, oinfo, &res);
597         if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
598                 return;
599         if (res.matches != 1)
600                 xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
601         if (res.bad_non_owner_matches)
602                 xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
603         if (res.non_owner_matches)
604                 xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
605 }
606 
607 /* xref check that the extent is not owned by a given owner */
608 void
609 xchk_xref_is_not_owned_by(
610         struct xfs_scrub                *sc,
611         xfs_agblock_t                   bno,
612         xfs_extlen_t                    len,
613         const struct xfs_owner_info     *oinfo)
614 {
615         struct xfs_rmap_matches         res;
616         int                             error;
617 
618         if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm))
619                 return;
620 
621         error = xfs_rmap_count_owners(sc->sa.rmap_cur, bno, len, oinfo, &res);
622         if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
623                 return;
624         if (res.matches != 0)
625                 xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
626         if (res.bad_non_owner_matches)
627                 xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
628 }
629 
630 /* xref check that the extent has no reverse mapping at all */
631 void
632 xchk_xref_has_no_owner(
633         struct xfs_scrub        *sc,
634         xfs_agblock_t           bno,
635         xfs_extlen_t            len)
636 {
637         enum xbtree_recpacking  outcome;
638         int                     error;
639 
640         if (!sc->sa.rmap_cur || xchk_skip_xref(sc->sm))
641                 return;
642 
643         error = xfs_rmap_has_records(sc->sa.rmap_cur, bno, len, &outcome);
644         if (!xchk_should_check_xref(sc, &error, &sc->sa.rmap_cur))
645                 return;
646         if (outcome != XBTREE_RECPACKING_EMPTY)
647                 xchk_btree_xref_set_corrupt(sc, sc->sa.rmap_cur, 0);
648 }
649 

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