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-achx @ Mon Jul 31 20:08:12 PDT 2023 Lines: 299 317 94.3 %
Date: 2023-07-31 20:08:12 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    10410820 : xrep_bmap_discover_shared(
      89             :         struct xrep_bmap        *rb,
      90             :         xfs_fsblock_t           startblock,
      91             :         xfs_filblks_t           blockcount,
      92             :         bool                    unwritten)
      93             : {
      94    10410820 :         struct xfs_scrub        *sc = rb->sc;
      95    10410820 :         xfs_agblock_t           agbno;
      96    10410820 :         xfs_agblock_t           fbno;
      97    10410820 :         xfs_extlen_t            flen;
      98    10410820 :         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    10410820 :         if (rb->shared_extents)
     106             :                 return 0;
     107     3924742 :         if (unwritten)
     108             :                 return 0;
     109     3701345 :         if (rb->whichfork != XFS_DATA_FORK)
     110             :                 return 0;
     111     3666787 :         if (!S_ISREG(VFS_I(sc->ip)->i_mode))
     112             :                 return 0;
     113     3643057 :         if (!xfs_has_reflink(sc->mp))
     114             :                 return 0;
     115     3640756 :         if (XFS_IS_REALTIME_INODE(sc->ip))
     116             :                 return 0;
     117             : 
     118     3640756 :         agbno = XFS_FSB_TO_AGBNO(sc->mp, startblock);
     119     3640747 :         error = xfs_refcount_find_shared(sc->sa.refc_cur, agbno, blockcount,
     120             :                         &fbno, &flen, false);
     121     3640737 :         if (error)
     122             :                 return error;
     123             : 
     124     3640737 :         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    10410808 : 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    10410808 :         struct xfs_bmbt_irec    irec = {
     140             :                 .br_startoff    = startoff,
     141             :                 .br_startblock  = startblock,
     142    10410808 :                 .br_state       = unwritten ? XFS_EXT_UNWRITTEN : XFS_EXT_NORM,
     143             :         };
     144    10410808 :         struct xfs_bmbt_rec     rbe;
     145    10410808 :         struct xfs_scrub        *sc = rb->sc;
     146    10410808 :         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    10410808 :         error = xrep_bmap_discover_shared(rb, startblock, blockcount,
     154             :                         unwritten);
     155    10410795 :         if (error)
     156             :                 return error;
     157             : 
     158    10410801 :         do {
     159    10410801 :                 xfs_failaddr_t  fa;
     160             : 
     161    10410801 :                 irec.br_blockcount = min_t(xfs_filblks_t, blockcount,
     162             :                                 XFS_MAX_BMBT_EXTLEN);
     163             : 
     164    10410801 :                 fa = xfs_bmap_validate_extent(sc->ip, rb->whichfork, &irec);
     165    10410802 :                 if (fa)
     166             :                         return -EFSCORRUPTED;
     167             : 
     168    10410802 :                 xfs_bmbt_disk_set_all(&rbe, &irec);
     169             : 
     170    10410797 :                 trace_xrep_bmap_found(sc->ip, rb->whichfork, &irec);
     171             : 
     172    10410792 :                 if (xchk_should_terminate(sc, &error))
     173           0 :                         return error;
     174             : 
     175    10410808 :                 error = xfarray_append(rb->bmap_records, &rbe);
     176    10410823 :                 if (error)
     177           0 :                         return error;
     178             : 
     179    10410823 :                 rb->real_mappings++;
     180             : 
     181    10410823 :                 irec.br_startblock += irec.br_blockcount;
     182    10410823 :                 irec.br_startoff += irec.br_blockcount;
     183    10410823 :                 blockcount -= irec.br_blockcount;
     184    10410823 :         } 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    10499751 : 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    10499751 :         struct xfs_scrub                *sc = rb->sc;
     197    10499751 :         enum xbtree_recpacking          outcome;
     198    10499751 :         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    10499751 :         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    10499751 :         if (!xfs_verify_agbext(cur->bc_ag.pag, rec->rm_startblock,
     210    10499751 :                                 rec->rm_blockcount))
     211             :                 return -EFSCORRUPTED;
     212             : 
     213             :         /* Check the file offset range. */
     214    20948323 :         if (!(rec->rm_flags & XFS_RMAP_BMBT_BLOCK) &&
     215    10448576 :             !xfs_verify_fileext(sc->mp, rec->rm_offset, rec->rm_blockcount))
     216             :                 return -EFSCORRUPTED;
     217             : 
     218             :         /* No contradictory flags. */
     219    10499747 :         if ((rec->rm_flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK)) &&
     220       89283 :             (rec->rm_flags & XFS_RMAP_UNWRITTEN))
     221             :                 return -EFSCORRUPTED;
     222             : 
     223             :         /* Make sure this isn't free space. */
     224    10499747 :         error = xfs_alloc_has_records(sc->sa.bno_cur, rec->rm_startblock,
     225    10499747 :                         rec->rm_blockcount, &outcome);
     226    10499745 :         if (error)
     227             :                 return error;
     228    10499745 :         if (outcome != XBTREE_RECPACKING_EMPTY)
     229             :                 return -EFSCORRUPTED;
     230             : 
     231             :         /* Must not be an inode chunk. */
     232    10499745 :         error = xfs_ialloc_has_inodes_at_extent(sc->sa.ino_cur,
     233    10499745 :                         rec->rm_startblock, rec->rm_blockcount, &outcome);
     234    10499781 :         if (error)
     235             :                 return error;
     236    10499781 :         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 32456537333 : xrep_bmap_walk_rmap(
     245             :         struct xfs_btree_cur            *cur,
     246             :         const struct xfs_rmap_irec      *rec,
     247             :         void                            *priv)
     248             : {
     249 32456537333 :         struct xrep_bmap                *rb = priv;
     250 32456537333 :         struct xfs_mount                *mp = cur->bc_mp;
     251 32456537333 :         xfs_fsblock_t                   fsbno;
     252 32456537333 :         int                             error = 0;
     253             : 
     254 32456537333 :         if (xchk_should_terminate(rb->sc, &error))
     255           1 :                 return error;
     256             : 
     257 32454082756 :         if (rec->rm_owner != rb->sc->ip->i_ino)
     258             :                 return 0;
     259             : 
     260    10499757 :         error = xrep_bmap_check_fork_rmap(rb, cur, rec);
     261    10499794 :         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    10499794 :         rb->nblocks += rec->rm_blockcount;
     269             : 
     270             :         /* If this rmap isn't for the fork we want, we're done. */
     271    10499794 :         if (rb->whichfork == XFS_DATA_FORK &&
     272    10429820 :             (rec->rm_flags & XFS_RMAP_ATTR_FORK))
     273             :                 return 0;
     274    10496237 :         if (rb->whichfork == XFS_ATTR_FORK &&
     275       69965 :             !(rec->rm_flags & XFS_RMAP_ATTR_FORK))
     276             :                 return 0;
     277             : 
     278             :         /* Reject unwritten extents if we don't allow those. */
     279    10460833 :         if ((rec->rm_flags & XFS_RMAP_UNWRITTEN) && !rb->allow_unwritten)
     280             :                 return -EFSCORRUPTED;
     281             : 
     282    10460833 :         fsbno = XFS_AGB_TO_FSB(mp, cur->bc_ag.pag->pag_agno,
     283             :                         rec->rm_startblock);
     284             : 
     285    10460833 :         if (rec->rm_flags & XFS_RMAP_BMBT_BLOCK) {
     286       50015 :                 rb->old_bmbt_block_count += rec->rm_blockcount;
     287       50015 :                 return xfsb_bitmap_set(&rb->old_bmbt_blocks, fsbno,
     288       50015 :                                 rec->rm_blockcount);
     289             :         }
     290             : 
     291    10410818 :         return xrep_bmap_from_rmap(rb, rec->rm_offset, fsbno,
     292    10410818 :                         rec->rm_blockcount,
     293    10410818 :                         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   163882803 : xrep_bmap_extent_cmp(
     302             :         const void                      *a,
     303             :         const void                      *b)
     304             : {
     305   163882803 :         xfs_fileoff_t                   ao;
     306   163882803 :         xfs_fileoff_t                   bo;
     307             : 
     308   163882803 :         ao = xfs_bmbt_disk_get_startoff((struct xfs_bmbt_rec *)a);
     309   163882803 :         bo = xfs_bmbt_disk_get_startoff((struct xfs_bmbt_rec *)b);
     310             : 
     311   163882803 :         if (ao > bo)
     312             :                 return 1;
     313    88283076 :         else if (ao < bo)
     314    88283076 :                 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     2568677 : xrep_bmap_sort_records(
     324             :         struct xrep_bmap        *rb)
     325             : {
     326     2568677 :         struct xfs_bmbt_irec    irec;
     327     2568677 :         xfs_fileoff_t           next_off = 0;
     328     2568677 :         xfarray_idx_t           array_cur;
     329     2568677 :         int                     error;
     330             : 
     331     2568677 :         error = xfarray_sort(rb->bmap_records, xrep_bmap_extent_cmp,
     332             :                         XFARRAY_SORT_KILLABLE);
     333     2568677 :         if (error)
     334             :                 return error;
     335             : 
     336    12979536 :         foreach_xfarray_idx(rb->bmap_records, array_cur) {
     337    10410859 :                 struct xfs_bmbt_rec     rec;
     338             : 
     339    10410859 :                 if (xchk_should_terminate(rb->sc, &error))
     340           0 :                         return error;
     341             : 
     342    10410859 :                 error = xfarray_load(rb->bmap_records, array_cur, &rec);
     343    10410859 :                 if (error)
     344           0 :                         return error;
     345             : 
     346    10410859 :                 xfs_bmbt_disk_get_all(&rec, &irec);
     347             : 
     348    10410859 :                 if (irec.br_startoff < next_off)
     349             :                         return -EFSCORRUPTED;
     350             : 
     351    10410859 :                 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    12752601 : xrep_bmap_scan_ag(
     360             :         struct xrep_bmap        *rb,
     361             :         struct xfs_perag        *pag)
     362             : {
     363    12752601 :         struct xfs_scrub        *sc = rb->sc;
     364    12752601 :         int                     error;
     365             : 
     366    12752601 :         error = xrep_ag_init(sc, pag, &sc->sa);
     367    12752543 :         if (error)
     368             :                 return error;
     369             : 
     370    12752523 :         error = xfs_rmap_query_all(sc->sa.rmap_cur, xrep_bmap_walk_rmap, rb);
     371    12752462 :         xchk_ag_free(sc, &sc->sa);
     372    12752462 :         return error;
     373             : }
     374             : 
     375             : /* Find the delalloc extents from the old incore extent tree. */
     376             : STATIC int
     377     2568677 : xrep_bmap_find_delalloc(
     378             :         struct xrep_bmap        *rb)
     379             : {
     380     2568677 :         struct xfs_bmbt_irec    irec;
     381     2568677 :         struct xfs_iext_cursor  icur;
     382     2568677 :         struct xfs_bmbt_rec     rbe;
     383     2568677 :         struct xfs_inode        *ip = rb->sc->ip;
     384     2568677 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(ip, rb->whichfork);
     385     2568677 :         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     2568677 :         if (rb->whichfork == XFS_ATTR_FORK || ip->i_delayed_blks == 0)
     392             :                 return 0;
     393             : 
     394       48288 :         for_each_xfs_iext(ifp, &icur, &irec) {
     395       45804 :                 if (!isnullstartblock(irec.br_startblock))
     396       45803 :                         continue;
     397             : 
     398           1 :                 xfs_bmbt_disk_set_all(&rbe, &irec);
     399             : 
     400           1 :                 trace_xrep_bmap_found(ip, rb->whichfork, &irec);
     401             : 
     402           1 :                 if (xchk_should_terminate(rb->sc, &error))
     403           0 :                         return error;
     404             : 
     405           1 :                 error = xfarray_append(rb->bmap_records, &rbe);
     406           1 :                 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     2567712 : xrep_bmap_find_mappings(
     420             :         struct xrep_bmap        *rb)
     421             : {
     422     2567712 :         struct xfs_scrub        *sc = rb->sc;
     423     2567712 :         struct xfs_perag        *pag;
     424     2567712 :         xfs_agnumber_t          agno;
     425     2567712 :         int                     error = 0;
     426             : 
     427             :         /* Iterate the rmaps for extents. */
     428    15321234 :         for_each_perag(sc->mp, agno, pag) {
     429    12752786 :                 error = xrep_bmap_scan_ag(rb, pag);
     430    12753523 :                 if (error) {
     431           1 :                         xfs_perag_rele(pag);
     432           1 :                         return error;
     433             :                 }
     434             :         }
     435             : 
     436     2568677 :         return xrep_bmap_find_delalloc(rb);
     437             : }
     438             : 
     439             : /* Retrieve real extent mappings for bulk loading the bmap btree. */
     440             : STATIC int
     441       66831 : 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       66831 :         struct xfs_bmbt_rec     rec;
     449       66831 :         struct xfs_bmbt_irec    *irec = &cur->bc_rec.b;
     450       66831 :         struct xrep_bmap        *rb = priv;
     451       66831 :         union xfs_btree_rec     *block_rec;
     452       66831 :         unsigned int            loaded;
     453       66831 :         int                     error;
     454             : 
     455     9172980 :         for (loaded = 0; loaded < nr_wanted; loaded++, idx++) {
     456     9106149 :                 do {
     457     9106149 :                         error = xfarray_load(rb->bmap_records, rb->array_cur++,
     458             :                                         &rec);
     459     9106149 :                         if (error)
     460           0 :                                 return error;
     461             : 
     462     9106149 :                         xfs_bmbt_disk_get_all(&rec, irec);
     463     9106149 :                 } while (isnullstartblock(irec->br_startblock));
     464             : 
     465     9106149 :                 block_rec = xfs_btree_rec_addr(cur, idx, block);
     466     9106149 :                 cur->bc_ops->init_rec_from_cur(cur, block_rec);
     467             :         }
     468             : 
     469       66831 :         return loaded;
     470             : }
     471             : 
     472             : /* Feed one of the new btree blocks to the bulk loader. */
     473             : STATIC int
     474       67094 : xrep_bmap_claim_block(
     475             :         struct xfs_btree_cur    *cur,
     476             :         union xfs_btree_ptr     *ptr,
     477             :         void                    *priv)
     478             : {
     479       67094 :         struct xrep_bmap        *rb = priv;
     480       67094 :         int                     error;
     481             : 
     482       67094 :         error = xrep_newbt_relog_autoreap(&rb->new_bmapbt);
     483       67094 :         if (error)
     484             :                 return error;
     485             : 
     486       67094 :         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       23757 : 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       23757 :         ASSERT(level > 0);
     498             : 
     499       23757 :         return XFS_BMAP_BROOT_SPACE_CALC(cur->bc_mp, nr_this_level);
     500             : }
     501             : 
     502             : /* Update the inode counters. */
     503             : STATIC int
     504     2568665 : xrep_bmap_reset_counters(
     505             :         struct xrep_bmap        *rb)
     506             : {
     507     2568665 :         struct xfs_scrub        *sc = rb->sc;
     508     2568665 :         struct xbtree_ifakeroot *ifake = &rb->new_bmapbt.ifake;
     509     2568665 :         int64_t                 delta;
     510             : 
     511     2568665 :         if (rb->shared_extents)
     512       45108 :                 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     2568665 :         delta = ifake->if_blocks - rb->old_bmbt_block_count;
     519     2568665 :         sc->ip->i_nblocks = rb->nblocks + delta;
     520     2568665 :         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     2568665 :         xfs_trans_mod_dquot_byino(sc->tp, sc->ip, XFS_TRANS_DQ_BCOUNT, delta);
     527     2568665 :         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     2568665 : xrep_bmap_extents_load(
     537             :         struct xrep_bmap        *rb)
     538             : {
     539     2568665 :         struct xfs_iext_cursor  icur;
     540     2568665 :         struct xfs_bmbt_irec    irec;
     541     2568665 :         struct xfs_ifork        *ifp = rb->new_bmapbt.ifake.if_fork;
     542     2568665 :         xfarray_idx_t           array_cur;
     543     2568665 :         int                     error;
     544             : 
     545     2568665 :         ASSERT(ifp->if_bytes == 0);
     546             : 
     547             :         /* Add all the mappings (incl. delalloc) to the incore extent tree. */
     548     2568665 :         xfs_iext_first(ifp, &icur);
     549    15427802 :         foreach_xfarray_idx(rb->bmap_records, array_cur) {
     550    10290461 :                 struct xfs_bmbt_rec     rec;
     551             : 
     552    10290461 :                 error = xfarray_load(rb->bmap_records, array_cur, &rec);
     553    10290507 :                 if (error)
     554           0 :                         return error;
     555             : 
     556    10290507 :                 xfs_bmbt_disk_get_all(&rec, &irec);
     557             : 
     558    10290497 :                 xfs_iext_insert_raw(ifp, &icur, &irec);
     559    10290517 :                 if (!isnullstartblock(irec.br_startblock))
     560    10290516 :                         ifp->if_nextents++;
     561             : 
     562    10290517 :                 xfs_iext_next(ifp, &icur);
     563             :         }
     564             : 
     565     2568665 :         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       23769 : xrep_bmap_btree_load(
     575             :         struct xrep_bmap        *rb,
     576             :         struct xfs_btree_cur    *bmap_cur)
     577             : {
     578       23769 :         struct xfs_scrub        *sc = rb->sc;
     579       23769 :         int                     error;
     580             : 
     581             :         /* Compute how many blocks we'll need. */
     582       23769 :         error = xfs_btree_bload_compute_geometry(bmap_cur,
     583             :                         &rb->new_bmapbt.bload, rb->real_mappings);
     584       23769 :         if (error)
     585             :                 return error;
     586             : 
     587             :         /* Last chance to abort before we start committing fixes. */
     588       23769 :         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       47538 :         error = xfs_trans_reserve_more_inode(sc->tp, sc->ip,
     598       23769 :                         rb->new_bmapbt.bload.nr_blocks, 0, true);
     599       23769 :         if (error)
     600             :                 return error;
     601             : 
     602             :         /* Reserve the space we'll need for the new btree. */
     603       23757 :         error = xrep_newbt_alloc_blocks(&rb->new_bmapbt,
     604             :                         rb->new_bmapbt.bload.nr_blocks);
     605       23757 :         if (error)
     606             :                 return error;
     607             : 
     608             :         /* Add all observed bmap records. */
     609       23757 :         rb->array_cur = XFARRAY_CURSOR_INIT;
     610       23757 :         error = xfs_btree_bload(bmap_cur, &rb->new_bmapbt.bload, rb);
     611       23757 :         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       23757 :         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     2568677 : xrep_bmap_build_new_fork(
     633             :         struct xrep_bmap        *rb)
     634             : {
     635     2568677 :         struct xfs_owner_info   oinfo;
     636     2568677 :         struct xfs_scrub        *sc = rb->sc;
     637     2568677 :         struct xfs_btree_cur    *bmap_cur;
     638     2568677 :         struct xbtree_ifakeroot *ifake = &rb->new_bmapbt.ifake;
     639     2568677 :         int                     error;
     640             : 
     641     2568677 :         error = xrep_bmap_sort_records(rb);
     642     2568677 :         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     2568677 :         xfs_rmap_ino_bmbt_owner(&oinfo, sc->ip->i_ino, rb->whichfork);
     650     2568677 :         error = xrep_newbt_init_inode(&rb->new_bmapbt, sc, rb->whichfork,
     651             :                         &oinfo);
     652     2568677 :         if (error)
     653             :                 return error;
     654             : 
     655     2568677 :         rb->new_bmapbt.bload.get_records = xrep_bmap_get_records;
     656     2568677 :         rb->new_bmapbt.bload.claim_block = xrep_bmap_claim_block;
     657     2568677 :         rb->new_bmapbt.bload.iroot_size = xrep_bmap_iroot_size;
     658     2568677 :         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     2568677 :         if (rb->real_mappings <= XFS_IFORK_MAXEXT(sc->ip, rb->whichfork)) {
     666     2544908 :                 ifake->if_fork->if_format = XFS_DINODE_FMT_EXTENTS;
     667     2544908 :                 error = xrep_bmap_extents_load(rb);
     668             :         } else {
     669       23769 :                 ifake->if_fork->if_format = XFS_DINODE_FMT_BTREE;
     670       23769 :                 error = xrep_bmap_btree_load(rb, bmap_cur);
     671             :         }
     672     2568677 :         if (error)
     673          12 :                 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     2568665 :         xfs_bmbt_commit_staged_btree(bmap_cur, sc->tp, rb->whichfork);
     682     2568665 :         xfs_btree_del_cursor(bmap_cur, 0);
     683             : 
     684             :         /* Reset the inode counters now that we've changed the fork. */
     685     2568665 :         error = xrep_bmap_reset_counters(rb);
     686     2568665 :         if (error)
     687           0 :                 goto err_newbt;
     688             : 
     689             :         /* Dispose of any unused blocks and the accounting information. */
     690     2568665 :         error = xrep_newbt_commit(&rb->new_bmapbt);
     691     2568665 :         if (error)
     692             :                 return error;
     693             : 
     694     2568665 :         return xrep_roll_trans(sc);
     695             : 
     696             : err_cur:
     697          12 :         if (bmap_cur)
     698          12 :                 xfs_btree_del_cursor(bmap_cur, error);
     699           0 : err_newbt:
     700          12 :         xrep_newbt_cancel(&rb->new_bmapbt);
     701          12 :         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     2568661 : xrep_bmap_remove_old_tree(
     710             :         struct xrep_bmap        *rb)
     711             : {
     712     2568661 :         struct xfs_scrub        *sc = rb->sc;
     713     2568661 :         struct xfs_owner_info   oinfo;
     714             : 
     715             :         /* Free the old bmbt blocks if they're not in use. */
     716     2568661 :         xfs_rmap_ino_bmbt_owner(&oinfo, sc->ip->i_ino, rb->whichfork);
     717     2568661 :         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    19415129 : xrep_bmap_check_inputs(
     723             :         struct xfs_scrub        *sc,
     724             :         int                     whichfork)
     725             : {
     726    19415129 :         struct xfs_ifork        *ifp = xfs_ifork_ptr(sc->ip, whichfork);
     727             : 
     728    19415125 :         ASSERT(whichfork == XFS_DATA_FORK || whichfork == XFS_ATTR_FORK);
     729             : 
     730    19415125 :         if (!xfs_has_rmapbt(sc->mp))
     731             :                 return -EOPNOTSUPP;
     732             : 
     733             :         /* No fork means nothing to rebuild. */
     734     5805020 :         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     5805020 :         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     2568081 :                 break;
     751           0 :         default:
     752           0 :                 return -EFSCORRUPTED;
     753             :         }
     754             : 
     755     2568081 :         if (whichfork == XFS_ATTR_FORK)
     756             :                 return 0;
     757             : 
     758             :         /* Only files, symlinks, and directories get to have data forks. */
     759     2533892 :         switch (VFS_I(sc->ip)->i_mode & S_IFMT) {
     760             :         case S_IFREG:
     761             :         case S_IFDIR:
     762             :         case S_IFLNK:
     763             :                 /* ok */
     764     2533892 :                 break;
     765             :         default:
     766             :                 return -EINVAL;
     767             :         }
     768             : 
     769             :         /* Don't know how to rebuild realtime data forks. */
     770     2533892 :         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    19416591 : xrep_bmap(
     779             :         struct xfs_scrub        *sc,
     780             :         int                     whichfork,
     781             :         bool                    allow_unwritten)
     782             : {
     783    19416591 :         struct xrep_bmap        *rb;
     784    19416591 :         char                    *descr;
     785    19416591 :         unsigned int            max_bmbt_recs;
     786    19416591 :         bool                    large_extcount;
     787    19416591 :         int                     error = 0;
     788             : 
     789    19416591 :         error = xrep_bmap_check_inputs(sc, whichfork);
     790    19415409 :         if (error == -ECANCELED)
     791             :                 return 0;
     792    16178472 :         if (error)
     793             :                 return error;
     794             : 
     795     2568450 :         rb = kzalloc(sizeof(struct xrep_bmap), XCHK_GFP_FLAGS);
     796     2568472 :         if (!rb)
     797             :                 return -ENOMEM;
     798     2568472 :         rb->sc = sc;
     799     2568472 :         rb->whichfork = whichfork;
     800     2568472 :         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     2568472 :         if (whichfork == XFS_DATA_FORK && xfs_is_reflink_inode(sc->ip))
     807       45109 :                 rb->shared_extents = true;
     808             : 
     809             :         /* Set up enough storage to handle the max records for this fork. */
     810     2568472 :         large_extcount = xfs_has_large_extent_counts(sc->mp);
     811     2568472 :         max_bmbt_recs = xfs_iext_max_nextents(large_extcount, whichfork);
     812     2602383 :         descr = xchk_xfile_ino_descr(sc, "%s fork mapping records",
     813             :                         whichfork == XFS_DATA_FORK ? "data" : "attr");
     814     2568029 :         error = xfarray_create(descr, max_bmbt_recs,
     815             :                         sizeof(struct xfs_bmbt_rec), &rb->bmap_records);
     816     2567601 :         kfree(descr);
     817     2567397 :         if (error)
     818           0 :                 goto out_rb;
     819             : 
     820             :         /* Collect all reverse mappings for this fork's extents. */
     821     2567397 :         xfsb_bitmap_init(&rb->old_bmbt_blocks);
     822     2566814 :         error = xrep_bmap_find_mappings(rb);
     823     2568678 :         if (error)
     824           1 :                 goto out_bitmap;
     825             : 
     826     2568677 :         xfs_trans_ijoin(sc->tp, sc->ip, 0);
     827             : 
     828             :         /* Rebuild the bmap information. */
     829     2568677 :         error = xrep_bmap_build_new_fork(rb);
     830     2568675 :         if (error)
     831          12 :                 goto out_bitmap;
     832             : 
     833             :         /* Kill the old tree. */
     834     2568663 :         error = xrep_bmap_remove_old_tree(rb);
     835             : 
     836     2568674 : out_bitmap:
     837     2568674 :         xfsb_bitmap_destroy(&rb->old_bmbt_blocks);
     838     2568668 :         xfarray_destroy(rb->bmap_records);
     839     2568675 : out_rb:
     840     2568675 :         kfree(rb);
     841     2568675 :         return error;
     842             : }
     843             : 
     844             : /* Repair an inode's data fork. */
     845             : int
     846     9810208 : xrep_bmap_data(
     847             :         struct xfs_scrub        *sc)
     848             : {
     849     9810208 :         return xrep_bmap(sc, XFS_DATA_FORK, true);
     850             : }
     851             : 
     852             : /* Repair an inode's attr fork. */
     853             : int
     854     9601086 : xrep_bmap_attr(
     855             :         struct xfs_scrub        *sc)
     856             : {
     857     9601086 :         return xrep_bmap(sc, XFS_ATTR_FORK, false);
     858             : }

Generated by: LCOV version 1.14