LCOV - code coverage report
Current view: top level - fs/xfs/scrub - bmap_repair.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc3-acha @ Mon Jul 31 20:08:06 PDT 2023 Lines: 283 316 89.6 %
Date: 2023-07-31 20:08:07 Functions: 21 21 100.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-or-later
       2             : /*
       3             :  * Copyright (C) 2018-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_defer.h"
      13             : #include "xfs_btree.h"
      14             : #include "xfs_btree_staging.h"
      15             : #include "xfs_bit.h"
      16             : #include "xfs_log_format.h"
      17             : #include "xfs_trans.h"
      18             : #include "xfs_sb.h"
      19             : #include "xfs_inode.h"
      20             : #include "xfs_inode_fork.h"
      21             : #include "xfs_alloc.h"
      22             : #include "xfs_rtalloc.h"
      23             : #include "xfs_bmap.h"
      24             : #include "xfs_bmap_util.h"
      25             : #include "xfs_bmap_btree.h"
      26             : #include "xfs_rmap.h"
      27             : #include "xfs_rmap_btree.h"
      28             : #include "xfs_refcount.h"
      29             : #include "xfs_quota.h"
      30             : #include "xfs_ialloc.h"
      31             : #include "xfs_ag.h"
      32             : #include "xfs_reflink.h"
      33             : #include "scrub/xfs_scrub.h"
      34             : #include "scrub/scrub.h"
      35             : #include "scrub/common.h"
      36             : #include "scrub/btree.h"
      37             : #include "scrub/trace.h"
      38             : #include "scrub/repair.h"
      39             : #include "scrub/bitmap.h"
      40             : #include "scrub/xfile.h"
      41             : #include "scrub/xfarray.h"
      42             : #include "scrub/newbt.h"
      43             : #include "scrub/reap.h"
      44             : 
      45             : /*
      46             :  * Inode Fork Block Mapping (BMBT) Repair
      47             :  * ======================================
      48             :  *
      49             :  * Gather all the rmap records for the inode and fork we're fixing, reset the
      50             :  * incore fork, then recreate the btree.
      51             :  */
      52             : struct xrep_bmap {
      53             :         /* Old bmbt blocks */
      54             :         struct xfsb_bitmap      old_bmbt_blocks;
      55             : 
      56             :         /* New fork. */
      57             :         struct xrep_newbt       new_bmapbt;
      58             : 
      59             :         /* List of new bmap records. */
      60             :         struct xfarray          *bmap_records;
      61             : 
      62             :         struct xfs_scrub        *sc;
      63             : 
      64             :         /* How many blocks did we find allocated to this file? */
      65             :         xfs_rfsblock_t          nblocks;
      66             : 
      67             :         /* How many bmbt blocks did we find for this fork? */
      68             :         xfs_rfsblock_t          old_bmbt_block_count;
      69             : 
      70             :         /* get_records()'s position in the free space record array. */
      71             :         xfarray_idx_t           array_cur;
      72             : 
      73             :         /* How many real (non-hole, non-delalloc) mappings do we have? */
      74             :         uint64_t                real_mappings;
      75             : 
      76             :         /* Which fork are we fixing? */
      77             :         int                     whichfork;
      78             : 
      79             :         /* Are there shared extents? */
      80             :         bool                    shared_extents;
      81             : 
      82             :         /* Do we allow unwritten extents? */
      83             :         bool                    allow_unwritten;
      84             : };
      85             : 
      86             : /* Is this space extent shared?  Flag the inode if it is. */
      87             : STATIC int
      88      254145 : xrep_bmap_discover_shared(
      89             :         struct xrep_bmap        *rb,
      90             :         xfs_fsblock_t           startblock,
      91             :         xfs_filblks_t           blockcount,
      92             :         bool                    unwritten)
      93             : {
      94      254145 :         struct xfs_scrub        *sc = rb->sc;
      95      254145 :         xfs_agblock_t           agbno;
      96      254145 :         xfs_agblock_t           fbno;
      97      254145 :         xfs_extlen_t            flen;
      98      254145 :         int                     error;
      99             : 
     100             :         /*
     101             :          * Only investigate if we need to set the shared extents flag if we are
     102             :          * adding a written extent mapping to the data fork of a regular file
     103             :          * on reflink filesystem.
     104             :          */
     105      254145 :         if (rb->shared_extents)
     106             :                 return 0;
     107      159094 :         if (unwritten)
     108             :                 return 0;
     109      136209 :         if (rb->whichfork != XFS_DATA_FORK)
     110             :                 return 0;
     111      104930 :         if (!S_ISREG(VFS_I(sc->ip)->i_mode))
     112             :                 return 0;
     113      100178 :         if (!xfs_has_reflink(sc->mp))
     114             :                 return 0;
     115      100178 :         if (XFS_IS_REALTIME_INODE(sc->ip))
     116             :                 return 0;
     117             : 
     118      100178 :         agbno = XFS_FSB_TO_AGBNO(sc->mp, startblock);
     119      100178 :         error = xfs_refcount_find_shared(sc->sa.refc_cur, agbno, blockcount,
     120             :                         &fbno, &flen, false);
     121      100178 :         if (error)
     122             :                 return error;
     123             : 
     124      100178 :         if (fbno != NULLAGBLOCK)
     125           0 :                 rb->shared_extents = true;
     126             : 
     127             :         return 0;
     128             : }
     129             : 
     130             : /* Remember this reverse-mapping as a series of bmap records. */
     131             : STATIC int
     132      254145 : xrep_bmap_from_rmap(
     133             :         struct xrep_bmap        *rb,
     134             :         xfs_fileoff_t           startoff,
     135             :         xfs_fsblock_t           startblock,
     136             :         xfs_filblks_t           blockcount,
     137             :         bool                    unwritten)
     138             : {
     139      254145 :         struct xfs_bmbt_irec    irec = {
     140             :                 .br_startoff    = startoff,
     141             :                 .br_startblock  = startblock,
     142      254145 :                 .br_state       = unwritten ? XFS_EXT_UNWRITTEN : XFS_EXT_NORM,
     143             :         };
     144      254145 :         struct xfs_bmbt_rec     rbe;
     145      254145 :         struct xfs_scrub        *sc = rb->sc;
     146      254145 :         int                     error = 0;
     147             : 
     148             :         /*
     149             :          * If we're repairing the data fork of a non-reflinked regular file on
     150             :          * a reflink filesystem, we need to figure out if this space extent is
     151             :          * shared.
     152             :          */
     153      254145 :         error = xrep_bmap_discover_shared(rb, startblock, blockcount,
     154             :                         unwritten);
     155      254145 :         if (error)
     156             :                 return error;
     157             : 
     158      254145 :         do {
     159      254145 :                 xfs_failaddr_t  fa;
     160             : 
     161      254145 :                 irec.br_blockcount = min_t(xfs_filblks_t, blockcount,
     162             :                                 XFS_MAX_BMBT_EXTLEN);
     163             : 
     164      254145 :                 fa = xfs_bmap_validate_extent(sc->ip, rb->whichfork, &irec);
     165      254144 :                 if (fa)
     166             :                         return -EFSCORRUPTED;
     167             : 
     168      254144 :                 xfs_bmbt_disk_set_all(&rbe, &irec);
     169             : 
     170      254144 :                 trace_xrep_bmap_found(sc->ip, rb->whichfork, &irec);
     171             : 
     172      254144 :                 if (xchk_should_terminate(sc, &error))
     173           0 :                         return error;
     174             : 
     175      254145 :                 error = xfarray_append(rb->bmap_records, &rbe);
     176      254145 :                 if (error)
     177           0 :                         return error;
     178             : 
     179      254145 :                 rb->real_mappings++;
     180             : 
     181      254145 :                 irec.br_startblock += irec.br_blockcount;
     182      254145 :                 irec.br_startoff += irec.br_blockcount;
     183      254145 :                 blockcount -= irec.br_blockcount;
     184      254145 :         } while (blockcount > 0);
     185             : 
     186             :         return 0;
     187             : }
     188             : 
     189             : /* Check for any obvious errors or conflicts in the file mapping. */
     190             : STATIC int
     191      270386 : xrep_bmap_check_fork_rmap(
     192             :         struct xrep_bmap                *rb,
     193             :         struct xfs_btree_cur            *cur,
     194             :         const struct xfs_rmap_irec      *rec)
     195             : {
     196      270386 :         struct xfs_scrub                *sc = rb->sc;
     197      270386 :         enum xbtree_recpacking          outcome;
     198      270386 :         int                             error;
     199             : 
     200             :         /*
     201             :          * Data extents for rt files are never stored on the data device, but
     202             :          * everything else (xattrs, bmbt blocks) can be.
     203             :          */
     204      270386 :         if (XFS_IS_REALTIME_INODE(sc->ip) &&
     205           0 :             !(rec->rm_flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK)))
     206             :                 return -EFSCORRUPTED;
     207             : 
     208             :         /* Check that this is within the AG. */
     209      270386 :         if (!xfs_verify_agbext(cur->bc_ag.pag, rec->rm_startblock,
     210      270386 :                                 rec->rm_blockcount))
     211             :                 return -EFSCORRUPTED;
     212             : 
     213             :         /* Check the file offset range. */
     214      535110 :         if (!(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
     215      264724 :             !xfs_verify_fileext(sc->mp, rec->rm_offset, rec->rm_blockcount))
     216             :                 return -EFSCORRUPTED;
     217             : 
     218             :         /* No contradictory flags. */
     219      270386 :         if ((rec->rm_flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK)) &&
     220       37668 :             (rec->rm_flags & XFS_RMAP_UNWRITTEN))
     221             :                 return -EFSCORRUPTED;
     222             : 
     223             :         /* Make sure this isn't free space. */
     224      270386 :         error = xfs_alloc_has_records(sc->sa.bno_cur, rec->rm_startblock,
     225      270386 :                         rec->rm_blockcount, &outcome);
     226      270386 :         if (error)
     227             :                 return error;
     228      270386 :         if (outcome != XBTREE_RECPACKING_EMPTY)
     229             :                 return -EFSCORRUPTED;
     230             : 
     231             :         /* Must not be an inode chunk. */
     232      270386 :         error = xfs_ialloc_has_inodes_at_extent(sc->sa.ino_cur,
     233      270386 :                         rec->rm_startblock, rec->rm_blockcount, &outcome);
     234      270386 :         if (error)
     235             :                 return error;
     236      270386 :         if (outcome != XBTREE_RECPACKING_EMPTY)
     237           0 :                 return -EFSCORRUPTED;
     238             : 
     239             :         return 0;
     240             : }
     241             : 
     242             : /* Record extents that belong to this inode's fork. */
     243             : STATIC int
     244  3315556385 : xrep_bmap_walk_rmap(
     245             :         struct xfs_btree_cur            *cur,
     246             :         const struct xfs_rmap_irec      *rec,
     247             :         void                            *priv)
     248             : {
     249  3315556385 :         struct xrep_bmap                *rb = priv;
     250  3315556385 :         struct xfs_mount                *mp = cur->bc_mp;
     251  3315556385 :         xfs_fsblock_t                   fsbno;
     252  3315556385 :         int                             error = 0;
     253             : 
     254  3315556385 :         if (xchk_should_terminate(rb->sc, &error))
     255           0 :                 return error;
     256             : 
     257  3315622005 :         if (rec->rm_owner != rb->sc->ip->i_ino)
     258             :                 return 0;
     259             : 
     260      270386 :         error = xrep_bmap_check_fork_rmap(rb, cur, rec);
     261      270386 :         if (error)
     262             :                 return error;
     263             : 
     264             :         /*
     265             :          * Record all blocks allocated to this file even if the extent isn't
     266             :          * for the fork we're rebuilding so that we can reset di_nblocks later.
     267             :          */
     268      270386 :         rb->nblocks += rec->rm_blockcount;
     269             : 
     270             :         /* If this rmap isn't for the fork we want, we're done. */
     271      270386 :         if (rb->whichfork == XFS_DATA_FORK &&
     272      228898 :             (rec->rm_flags & XFS_RMAP_ATTR_FORK))
     273             :                 return 0;
     274      269659 :         if (rb->whichfork == XFS_ATTR_FORK &&
     275       41488 :             !(rec->rm_flags & XFS_RMAP_ATTR_FORK))
     276             :                 return 0;
     277             : 
     278             :         /* Reject unwritten extents if we don't allow those. */
     279      259450 :         if ((rec->rm_flags & XFS_RMAP_UNWRITTEN) && !rb->allow_unwritten)
     280             :                 return -EFSCORRUPTED;
     281             : 
     282      259450 :         fsbno = XFS_AGB_TO_FSB(mp, cur->bc_ag.pag->pag_agno,
     283             :                         rec->rm_startblock);
     284             : 
     285      259450 :         if (rec->rm_flags & XFS_RMAP_BMBT_BLOCK) {
     286        5305 :                 rb->old_bmbt_block_count += rec->rm_blockcount;
     287        5305 :                 return xfsb_bitmap_set(&rb->old_bmbt_blocks, fsbno,
     288        5305 :                                 rec->rm_blockcount);
     289             :         }
     290             : 
     291      254145 :         return xrep_bmap_from_rmap(rb, rec->rm_offset, fsbno,
     292      254145 :                         rec->rm_blockcount,
     293             :                         rec->rm_flags & XFS_RMAP_UNWRITTEN);
     294             : }
     295             : 
     296             : /*
     297             :  * Compare two block mapping records.  We want to sort in order of increasing
     298             :  * file offset.
     299             :  */
     300             : static int
     301     1177519 : xrep_bmap_extent_cmp(
     302             :         const void                      *a,
     303             :         const void                      *b)
     304             : {
     305     1177519 :         xfs_fileoff_t                   ao;
     306     1177519 :         xfs_fileoff_t                   bo;
     307             : 
     308     1177519 :         ao = xfs_bmbt_disk_get_startoff((struct xfs_bmbt_rec *)a);
     309     1177519 :         bo = xfs_bmbt_disk_get_startoff((struct xfs_bmbt_rec *)b);
     310             : 
     311     1177519 :         if (ao > bo)
     312             :                 return 1;
     313      662661 :         else if (ao < bo)
     314      662661 :                 return -1;
     315             :         return 0;
     316             : }
     317             : 
     318             : /*
     319             :  * Sort the bmap extents by fork offset or else the records will be in the
     320             :  * wrong order.  Ensure there are no overlaps in the file offset ranges.
     321             :  */
     322             : STATIC int
     323       60814 : xrep_bmap_sort_records(
     324             :         struct xrep_bmap        *rb)
     325             : {
     326       60814 :         struct xfs_bmbt_irec    irec;
     327       60814 :         xfs_fileoff_t           next_off = 0;
     328       60814 :         xfarray_idx_t           array_cur;
     329       60814 :         int                     error;
     330             : 
     331       60814 :         error = xfarray_sort(rb->bmap_records, xrep_bmap_extent_cmp,
     332             :                         XFARRAY_SORT_KILLABLE);
     333       60814 :         if (error)
     334             :                 return error;
     335             : 
     336      314959 :         foreach_xfarray_idx(rb->bmap_records, array_cur) {
     337      254145 :                 struct xfs_bmbt_rec     rec;
     338             : 
     339      254145 :                 if (xchk_should_terminate(rb->sc, &error))
     340           0 :                         return error;
     341             : 
     342      254145 :                 error = xfarray_load(rb->bmap_records, array_cur, &rec);
     343      254145 :                 if (error)
     344           0 :                         return error;
     345             : 
     346      254145 :                 xfs_bmbt_disk_get_all(&rec, &irec);
     347             : 
     348      254145 :                 if (irec.br_startoff < next_off)
     349             :                         return -EFSCORRUPTED;
     350             : 
     351      254145 :                 next_off = irec.br_startoff + irec.br_blockcount;
     352             :         }
     353             : 
     354             :         return 0;
     355             : }
     356             : 
     357             : /* Scan one AG for reverse mappings that we can turn into extent maps. */
     358             : STATIC int
     359      243256 : xrep_bmap_scan_ag(
     360             :         struct xrep_bmap        *rb,
     361             :         struct xfs_perag        *pag)
     362             : {
     363      243256 :         struct xfs_scrub        *sc = rb->sc;
     364      243256 :         int                     error;
     365             : 
     366      243256 :         error = xrep_ag_init(sc, pag, &sc->sa);
     367      243256 :         if (error)
     368             :                 return error;
     369             : 
     370      243256 :         error = xfs_rmap_query_all(sc->sa.rmap_cur, xrep_bmap_walk_rmap, rb);
     371      243256 :         xchk_ag_free(sc, &sc->sa);
     372      243256 :         return error;
     373             : }
     374             : 
     375             : /* Find the delalloc extents from the old incore extent tree. */
     376             : STATIC int
     377       60814 : xrep_bmap_find_delalloc(
     378             :         struct xrep_bmap        *rb)
     379             : {
     380       60814 :         struct xfs_bmbt_irec    irec;
     381       60814 :         struct xfs_iext_cursor  icur;
     382       60814 :         struct xfs_bmbt_rec     rbe;
     383       60814 :         struct xfs_inode        *ip = rb->sc->ip;
     384       60814 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, rb->whichfork);
     385       60814 :         int                     error = 0;
     386             : 
     387             :         /*
     388             :          * Skip this scan if we don't expect to find delayed allocation
     389             :          * reservations in this fork.
     390             :          */
     391       60814 :         if (rb->whichfork == XFS_ATTR_FORK || ip->i_delayed_blks == 0)
     392             :                 return 0;
     393             : 
     394        1335 :         for_each_xfs_iext(ifp, &icur, &irec) {
     395        1252 :                 if (!isnullstartblock(irec.br_startblock))
     396        1252 :                         continue;
     397             : 
     398           0 :                 xfs_bmbt_disk_set_all(&rbe, &irec);
     399             : 
     400           0 :                 trace_xrep_bmap_found(ip, rb->whichfork, &irec);
     401             : 
     402           0 :                 if (xchk_should_terminate(rb->sc, &error))
     403           0 :                         return error;
     404             : 
     405           0 :                 error = xfarray_append(rb->bmap_records, &rbe);
     406           0 :                 if (error)
     407           0 :                         return error;
     408             :         }
     409             : 
     410             :         return 0;
     411             : }
     412             : 
     413             : /*
     414             :  * Collect block mappings for this fork of this inode and decide if we have
     415             :  * enough space to rebuild.  Caller is responsible for cleaning up the list if
     416             :  * anything goes wrong.
     417             :  */
     418             : STATIC int
     419       60814 : xrep_bmap_find_mappings(
     420             :         struct xrep_bmap        *rb)
     421             : {
     422       60814 :         struct xfs_scrub        *sc = rb->sc;
     423       60814 :         struct xfs_perag        *pag;
     424       60814 :         xfs_agnumber_t          agno;
     425       60814 :         int                     error = 0;
     426             : 
     427             :         /* Iterate the rmaps for extents. */
     428      304070 :         for_each_perag(sc->mp, agno, pag) {
     429      243256 :                 error = xrep_bmap_scan_ag(rb, pag);
     430      243256 :                 if (error) {
     431           0 :                         xfs_perag_rele(pag);
     432           0 :                         return error;
     433             :                 }
     434             :         }
     435             : 
     436       60814 :         return xrep_bmap_find_delalloc(rb);
     437             : }
     438             : 
     439             : /* Retrieve real extent mappings for bulk loading the bmap btree. */
     440             : STATIC int
     441        5338 : xrep_bmap_get_records(
     442             :         struct xfs_btree_cur    *cur,
     443             :         unsigned int            idx,
     444             :         struct xfs_btree_block  *block,
     445             :         unsigned int            nr_wanted,
     446             :         void                    *priv)
     447             : {
     448        5338 :         struct xfs_bmbt_rec     rec;
     449        5338 :         struct xfs_bmbt_irec    *irec = &cur->bc_rec.b;
     450        5338 :         struct xrep_bmap        *rb = priv;
     451        5338 :         union xfs_btree_rec     *block_rec;
     452        5338 :         unsigned int            loaded;
     453        5338 :         int                     error;
     454             : 
     455      153291 :         for (loaded = 0; loaded < nr_wanted; loaded++, idx++) {
     456      147953 :                 do {
     457      147953 :                         error = xfarray_load(rb->bmap_records, rb->array_cur++,
     458             :                                         &rec);
     459      147953 :                         if (error)
     460           0 :                                 return error;
     461             : 
     462      147953 :                         xfs_bmbt_disk_get_all(&rec, irec);
     463      147953 :                 } while (isnullstartblock(irec->br_startblock));
     464             : 
     465      147953 :                 block_rec = xfs_btree_rec_addr(cur, idx, block);
     466      147953 :                 cur->bc_ops->init_rec_from_cur(cur, block_rec);
     467             :         }
     468             : 
     469        5338 :         return loaded;
     470             : }
     471             : 
     472             : /* Feed one of the new btree blocks to the bulk loader. */
     473             : STATIC int
     474        5340 : xrep_bmap_claim_block(
     475             :         struct xfs_btree_cur    *cur,
     476             :         union xfs_btree_ptr     *ptr,
     477             :         void                    *priv)
     478             : {
     479        5340 :         struct xrep_bmap        *rb = priv;
     480        5340 :         int                     error;
     481             : 
     482        5340 :         error = xrep_newbt_relog_autoreap(&rb->new_bmapbt);
     483        5340 :         if (error)
     484             :                 return error;
     485             : 
     486        5340 :         return xrep_newbt_claim_block(cur, &rb->new_bmapbt, ptr);
     487             : }
     488             : 
     489             : /* Figure out how much space we need to create the incore btree root block. */
     490             : STATIC size_t
     491        5163 : xrep_bmap_iroot_size(
     492             :         struct xfs_btree_cur    *cur,
     493             :         unsigned int            level,
     494             :         unsigned int            nr_this_level,
     495             :         void                    *priv)
     496             : {
     497        5163 :         ASSERT(level > 0);
     498             : 
     499        5163 :         return XFS_BMAP_BROOT_SPACE_CALC(cur->bc_mp, nr_this_level);
     500             : }
     501             : 
     502             : /* Update the inode counters. */
     503             : STATIC int
     504       60814 : xrep_bmap_reset_counters(
     505             :         struct xrep_bmap        *rb)
     506             : {
     507       60814 :         struct xfs_scrub        *sc = rb->sc;
     508       60814 :         struct xbtree_ifakeroot *ifake = &rb->new_bmapbt.ifake;
     509       60814 :         int64_t                 delta;
     510             : 
     511       60814 :         if (rb->shared_extents)
     512        7836 :                 sc->ip->i_diflags2 |= XFS_DIFLAG2_REFLINK;
     513             : 
     514             :         /*
     515             :          * Update the inode block counts to reflect the extents we found in the
     516             :          * rmapbt.
     517             :          */
     518       60814 :         delta = ifake->if_blocks - rb->old_bmbt_block_count;
     519       60814 :         sc->ip->i_nblocks = rb->nblocks + delta;
     520       60814 :         xfs_trans_log_inode(sc->tp, sc->ip, XFS_ILOG_CORE);
     521             : 
     522             :         /*
     523             :          * Adjust the quota counts by the difference in size between the old
     524             :          * and new bmbt.
     525             :          */
     526       60814 :         xfs_trans_mod_dquot_byino(sc->tp, sc->ip, XFS_TRANS_DQ_BCOUNT, delta);
     527       60814 :         return 0;
     528             : }
     529             : 
     530             : /*
     531             :  * Create a new iext tree and load it with block mappings.  If the inode is
     532             :  * in extents format, that's all we need to do to commit the new mappings.
     533             :  * If it is in btree format, this takes care of preloading the incore tree.
     534             :  */
     535             : STATIC int
     536       60814 : xrep_bmap_extents_load(
     537             :         struct xrep_bmap        *rb)
     538             : {
     539       60814 :         struct xfs_iext_cursor  icur;
     540       60814 :         struct xfs_bmbt_irec    irec;
     541       60814 :         struct xfs_ifork        *ifp = rb->new_bmapbt.ifake.if_fork;
     542       60814 :         xfarray_idx_t           array_cur;
     543       60814 :         int                     error;
     544             : 
     545       60814 :         ASSERT(ifp->if_bytes == 0);
     546             : 
     547             :         /* Add all the mappings (incl. delalloc) to the incore extent tree. */
     548       60814 :         xfs_iext_first(ifp, &icur);
     549      375763 :         foreach_xfarray_idx(rb->bmap_records, array_cur) {
     550      254133 :                 struct xfs_bmbt_rec     rec;
     551             : 
     552      254133 :                 error = xfarray_load(rb->bmap_records, array_cur, &rec);
     553      254138 :                 if (error)
     554           0 :                         return error;
     555             : 
     556      254138 :                 xfs_bmbt_disk_get_all(&rec, &irec);
     557             : 
     558      254135 :                 xfs_iext_insert_raw(ifp, &icur, &irec);
     559      254130 :                 if (!isnullstartblock(irec.br_startblock))
     560      254130 :                         ifp->if_nextents++;
     561             : 
     562      254130 :                 xfs_iext_next(ifp, &icur);
     563             :         }
     564             : 
     565       60814 :         return xrep_ino_ensure_extent_count(rb->sc, rb->whichfork,
     566             :                         ifp->if_nextents);
     567             : }
     568             : 
     569             : /*
     570             :  * Reserve new btree blocks, bulk load the bmap records into the ondisk btree,
     571             :  * and load the incore extent tree.
     572             :  */
     573             : STATIC int
     574        5163 : xrep_bmap_btree_load(
     575             :         struct xrep_bmap        *rb,
     576             :         struct xfs_btree_cur    *bmap_cur)
     577             : {
     578        5163 :         struct xfs_scrub        *sc = rb->sc;
     579        5163 :         int                     error;
     580             : 
     581             :         /* Compute how many blocks we'll need. */
     582        5163 :         error = xfs_btree_bload_compute_geometry(bmap_cur,
     583             :                         &rb->new_bmapbt.bload, rb->real_mappings);
     584        5163 :         if (error)
     585             :                 return error;
     586             : 
     587             :         /* Last chance to abort before we start committing fixes. */
     588        5163 :         if (xchk_should_terminate(sc, &error))
     589           0 :                 return error;
     590             : 
     591             :         /*
     592             :          * Guess how many blocks we're going to need to rebuild an entire bmap
     593             :          * from the number of extents we found, and pump up our transaction to
     594             :          * have sufficient block reservation.  We're allowed to exceed file
     595             :          * quota to repair inconsistent metadata.
     596             :          */
     597       10326 :         error = xfs_trans_reserve_more_inode(sc->tp, sc->ip,
     598        5163 :                         rb->new_bmapbt.bload.nr_blocks, 0, true);
     599        5163 :         if (error)
     600             :                 return error;
     601             : 
     602             :         /* Reserve the space we'll need for the new btree. */
     603        5163 :         error = xrep_newbt_alloc_blocks(&rb->new_bmapbt,
     604             :                         rb->new_bmapbt.bload.nr_blocks);
     605        5163 :         if (error)
     606             :                 return error;
     607             : 
     608             :         /* Add all observed bmap records. */
     609        5163 :         rb->array_cur = XFARRAY_CURSOR_INIT;
     610        5163 :         error = xfs_btree_bload(bmap_cur, &rb->new_bmapbt.bload, rb);
     611        5163 :         if (error)
     612             :                 return error;
     613             : 
     614             :         /*
     615             :          * Load the new bmap records into the new incore extent tree to
     616             :          * preserve delalloc reservations for regular files.  The directory
     617             :          * code loads the extent tree during xfs_dir_open and assumes
     618             :          * thereafter that it remains loaded, so we must not violate that
     619             :          * assumption.
     620             :          */
     621        5163 :         return xrep_bmap_extents_load(rb);
     622             : }
     623             : 
     624             : /*
     625             :  * Use the collected bmap information to stage a new bmap fork.  If this is
     626             :  * successful we'll return with the new fork information logged to the repair
     627             :  * transaction but not yet committed.  The caller must ensure that the inode
     628             :  * is joined to the transaction; the inode will be joined to a clean
     629             :  * transaction when the function returns.
     630             :  */
     631             : STATIC int
     632       60814 : xrep_bmap_build_new_fork(
     633             :         struct xrep_bmap        *rb)
     634             : {
     635       60814 :         struct xfs_owner_info   oinfo;
     636       60814 :         struct xfs_scrub        *sc = rb->sc;
     637       60814 :         struct xfs_btree_cur    *bmap_cur;
     638       60814 :         struct xbtree_ifakeroot *ifake = &rb->new_bmapbt.ifake;
     639       60814 :         int                     error;
     640             : 
     641       60814 :         error = xrep_bmap_sort_records(rb);
     642       60814 :         if (error)
     643             :                 return error;
     644             : 
     645             :         /*
     646             :          * Prepare to construct the new fork by initializing the new btree
     647             :          * structure and creating a fake ifork in the ifakeroot structure.
     648             :          */
     649       60814 :         xfs_rmap_ino_bmbt_owner(&oinfo, sc->ip->i_ino, rb->whichfork);
     650       60814 :         error = xrep_newbt_init_inode(&rb->new_bmapbt, sc, rb->whichfork,
     651             :                         &oinfo);
     652       60814 :         if (error)
     653             :                 return error;
     654             : 
     655       60814 :         rb->new_bmapbt.bload.get_records = xrep_bmap_get_records;
     656       60814 :         rb->new_bmapbt.bload.claim_block = xrep_bmap_claim_block;
     657       60814 :         rb->new_bmapbt.bload.iroot_size = xrep_bmap_iroot_size;
     658       60814 :         bmap_cur = xfs_bmbt_stage_cursor(sc->mp, sc->ip, ifake);
     659             : 
     660             :         /*
     661             :          * Figure out the size and format of the new fork, then fill it with
     662             :          * all the bmap records we've found.  Join the inode to the transaction
     663             :          * so that we can roll the transaction while holding the inode locked.
     664             :          */
     665       60814 :         if (rb->real_mappings <= XFS_IFORK_MAXEXT(sc->ip, rb->whichfork)) {
     666       55651 :                 ifake->if_fork->if_format = XFS_DINODE_FMT_EXTENTS;
     667       55651 :                 error = xrep_bmap_extents_load(rb);
     668             :         } else {
     669        5163 :                 ifake->if_fork->if_format = XFS_DINODE_FMT_BTREE;
     670        5163 :                 error = xrep_bmap_btree_load(rb, bmap_cur);
     671             :         }
     672       60814 :         if (error)
     673           0 :                 goto err_cur;
     674             : 
     675             :         /*
     676             :          * Install the new fork in the inode.  After this point the old mapping
     677             :          * data are no longer accessible and the new tree is live.  We delete
     678             :          * the cursor immediately after committing the staged root because the
     679             :          * staged fork might be in extents format.
     680             :          */
     681       60814 :         xfs_bmbt_commit_staged_btree(bmap_cur, sc->tp, rb->whichfork);
     682       60814 :         xfs_btree_del_cursor(bmap_cur, 0);
     683             : 
     684             :         /* Reset the inode counters now that we've changed the fork. */
     685       60814 :         error = xrep_bmap_reset_counters(rb);
     686       60814 :         if (error)
     687           0 :                 goto err_newbt;
     688             : 
     689             :         /* Dispose of any unused blocks and the accounting information. */
     690       60814 :         error = xrep_newbt_commit(&rb->new_bmapbt);
     691       60813 :         if (error)
     692             :                 return error;
     693             : 
     694       60813 :         return xrep_roll_trans(sc);
     695             : 
     696             : err_cur:
     697           0 :         if (bmap_cur)
     698           0 :                 xfs_btree_del_cursor(bmap_cur, error);
     699           0 : err_newbt:
     700           0 :         xrep_newbt_cancel(&rb->new_bmapbt);
     701           0 :         return error;
     702             : }
     703             : 
     704             : /*
     705             :  * Now that we've logged the new inode btree, invalidate all of the old blocks
     706             :  * and free them, if there were any.
     707             :  */
     708             : STATIC int
     709       60814 : xrep_bmap_remove_old_tree(
     710             :         struct xrep_bmap        *rb)
     711             : {
     712       60814 :         struct xfs_scrub        *sc = rb->sc;
     713       60814 :         struct xfs_owner_info   oinfo;
     714             : 
     715             :         /* Free the old bmbt blocks if they're not in use. */
     716       60814 :         xfs_rmap_ino_bmbt_owner(&oinfo, sc->ip->i_ino, rb->whichfork);
     717       60814 :         return xrep_reap_fsblocks(sc, &rb->old_bmbt_blocks, &oinfo);
     718             : }
     719             : 
     720             : /* Check for garbage inputs.  Returns -ECANCELED if there's nothing to do. */
     721             : STATIC int
     722     6689681 : xrep_bmap_check_inputs(
     723             :         struct xfs_scrub        *sc,
     724             :         int                     whichfork)
     725             : {
     726     6689681 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(sc->ip, whichfork);
     727             : 
     728     6689676 :         ASSERT(whichfork == XFS_DATA_FORK || whichfork == XFS_ATTR_FORK);
     729             : 
     730     6689676 :         if (!xfs_has_rmapbt(sc->mp))
     731             :                 return -EOPNOTSUPP;
     732             : 
     733             :         /* No fork means nothing to rebuild. */
     734      187818 :         if (!ifp)
     735             :                 return -ECANCELED;
     736             : 
     737             :         /*
     738             :          * We only know how to repair extent mappings, which is to say that we
     739             :          * only support extents and btree fork format.  Repairs to a local
     740             :          * format fork require a higher level repair function, so we do not
     741             :          * have any work to do here.
     742             :          */
     743      187818 :         switch (ifp->if_format) {
     744             :         case XFS_DINODE_FMT_DEV:
     745             :         case XFS_DINODE_FMT_LOCAL:
     746             :         case XFS_DINODE_FMT_UUID:
     747             :                 return -ECANCELED;
     748             :         case XFS_DINODE_FMT_EXTENTS:
     749             :         case XFS_DINODE_FMT_BTREE:
     750       60814 :                 break;
     751           0 :         default:
     752           0 :                 return -EFSCORRUPTED;
     753             :         }
     754             : 
     755       60814 :         if (whichfork == XFS_ATTR_FORK)
     756             :                 return 0;
     757             : 
     758             :         /* Only files, symlinks, and directories get to have data forks. */
     759       30331 :         switch (VFS_I(sc->ip)->i_mode & S_IFMT) {
     760             :         case S_IFREG:
     761             :         case S_IFDIR:
     762             :         case S_IFLNK:
     763             :                 /* ok */
     764       30331 :                 break;
     765             :         default:
     766             :                 return -EINVAL;
     767             :         }
     768             : 
     769             :         /* Don't know how to rebuild realtime data forks. */
     770       30331 :         if (XFS_IS_REALTIME_INODE(sc->ip))
     771           0 :                 return -EOPNOTSUPP;
     772             : 
     773             :         return 0;
     774             : }
     775             : 
     776             : /* Repair an inode fork. */
     777             : int
     778     6689689 : xrep_bmap(
     779             :         struct xfs_scrub        *sc,
     780             :         int                     whichfork,
     781             :         bool                    allow_unwritten)
     782             : {
     783     6689689 :         struct xrep_bmap        *rb;
     784     6689689 :         char                    *descr;
     785     6689689 :         unsigned int            max_bmbt_recs;
     786     6689689 :         bool                    large_extcount;
     787     6689689 :         int                     error = 0;
     788             : 
     789     6689689 :         error = xrep_bmap_check_inputs(sc, whichfork);
     790     6689706 :         if (error == -ECANCELED)
     791             :                 return 0;
     792     6562702 :         if (error)
     793             :                 return error;
     794             : 
     795       60814 :         rb = kzalloc(sizeof(struct xrep_bmap), XCHK_GFP_FLAGS);
     796       60814 :         if (!rb)
     797             :                 return -ENOMEM;
     798       60814 :         rb->sc = sc;
     799       60814 :         rb->whichfork = whichfork;
     800       60814 :         rb->allow_unwritten = allow_unwritten;
     801             : 
     802             :         /*
     803             :          * No need to waste time scanning for shared extents if the inode is
     804             :          * already marked.
     805             :          */
     806       60814 :         if (whichfork == XFS_DATA_FORK && xfs_is_reflink_inode(sc->ip))
     807        7836 :                 rb->shared_extents = true;
     808             : 
     809             :         /* Set up enough storage to handle the max records for this fork. */
     810       60814 :         large_extcount = xfs_has_large_extent_counts(sc->mp);
     811       60814 :         max_bmbt_recs = xfs_iext_max_nextents(large_extcount, whichfork);
     812       91297 :         descr = xchk_xfile_ino_descr(sc, "%s fork mapping records",
     813             :                         whichfork == XFS_DATA_FORK ? "data" : "attr");
     814       60814 :         error = xfarray_create(descr, max_bmbt_recs,
     815             :                         sizeof(struct xfs_bmbt_rec), &rb->bmap_records);
     816       60814 :         kfree(descr);
     817       60814 :         if (error)
     818           0 :                 goto out_rb;
     819             : 
     820             :         /* Collect all reverse mappings for this fork's extents. */
     821       60814 :         xfsb_bitmap_init(&rb->old_bmbt_blocks);
     822       60814 :         error = xrep_bmap_find_mappings(rb);
     823       60814 :         if (error)
     824           0 :                 goto out_bitmap;
     825             : 
     826       60814 :         xfs_trans_ijoin(sc->tp, sc->ip, 0);
     827             : 
     828             :         /* Rebuild the bmap information. */
     829       60814 :         error = xrep_bmap_build_new_fork(rb);
     830       60814 :         if (error)
     831           0 :                 goto out_bitmap;
     832             : 
     833             :         /* Kill the old tree. */
     834       60814 :         error = xrep_bmap_remove_old_tree(rb);
     835             : 
     836       60814 : out_bitmap:
     837       60814 :         xfsb_bitmap_destroy(&rb->old_bmbt_blocks);
     838       60814 :         xfarray_destroy(rb->bmap_records);
     839       60814 : out_rb:
     840       60814 :         kfree(rb);
     841       60814 :         return error;
     842             : }
     843             : 
     844             : /* Repair an inode's data fork. */
     845             : int
     846     3328558 : xrep_bmap_data(
     847             :         struct xfs_scrub        *sc)
     848             : {
     849     3328558 :         return xrep_bmap(sc, XFS_DATA_FORK, true);
     850             : }
     851             : 
     852             : /* Repair an inode's attr fork. */
     853             : int
     854     3357850 : xrep_bmap_attr(
     855             :         struct xfs_scrub        *sc)
     856             : {
     857     3357850 :         return xrep_bmap(sc, XFS_ATTR_FORK, false);
     858             : }

Generated by: LCOV version 1.14