LCOV - code coverage report
Current view: top level - fs/xfs/scrub - rtbitmap_repair.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc4-xfsa @ Mon Jul 31 20:08:27 PDT 2023 Lines: 266 301 88.4 %
Date: 2023-07-31 20:08:27 Functions: 15 15 100.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0-or-later
       2             : /*
       3             :  * Copyright (C) 2020-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_btree.h"
      13             : #include "xfs_log_format.h"
      14             : #include "xfs_trans.h"
      15             : #include "xfs_rtalloc.h"
      16             : #include "xfs_inode.h"
      17             : #include "xfs_bit.h"
      18             : #include "xfs_bmap.h"
      19             : #include "xfs_bmap_btree.h"
      20             : #include "xfs_rmap.h"
      21             : #include "xfs_rtrmap_btree.h"
      22             : #include "xfs_swapext.h"
      23             : #include "xfs_rtbitmap.h"
      24             : #include "xfs_rtgroup.h"
      25             : #include "xfs_refcount.h"
      26             : #include "scrub/scrub.h"
      27             : #include "scrub/common.h"
      28             : #include "scrub/trace.h"
      29             : #include "scrub/repair.h"
      30             : #include "scrub/xfile.h"
      31             : #include "scrub/tempfile.h"
      32             : #include "scrub/tempswap.h"
      33             : #include "scrub/reap.h"
      34             : 
      35             : /*
      36             :  * We use an xfile to construct new bitmap blocks for the portion of the
      37             :  * rtbitmap file that we're replacing.  Whereas the ondisk bitmap must be
      38             :  * accessed through the buffer cache, the xfile bitmap supports direct
      39             :  * word-level accesses.  Therefore, we create a small abstraction for linear
      40             :  * access.
      41             :  */
      42             : typedef unsigned long long xrep_wordoff_t;
      43             : typedef unsigned int xrep_wordcnt_t;
      44             : 
      45             : struct xrep_rgbmp {
      46             :         struct xfs_scrub        *sc;
      47             : 
      48             :         /* file offset inside the rtbitmap where we start swapping */
      49             :         xfs_fileoff_t           group_rbmoff;
      50             : 
      51             :         /* number of rtbitmap blocks for this group */
      52             :         xfs_filblks_t           group_rbmlen;
      53             : 
      54             :         /* The next rtgroup block we expect to see during our rtrmapbt walk. */
      55             :         xfs_rgblock_t           next_rgbno;
      56             : 
      57             :         /* rtword position of xfile as we write buffers to disk. */
      58             :         xrep_wordoff_t          prep_wordoff;
      59             : };
      60             : 
      61             : /* Mask to round an rtx down to the nearest bitmap word. */
      62             : #define XREP_RTBMP_WORDMASK     ((1ULL << XFS_NBWORDLOG) - 1)
      63             : 
      64             : /* Set up to repair the realtime bitmap for this group. */
      65             : int
      66       37459 : xrep_setup_rgbitmap(
      67             :         struct xfs_scrub        *sc,
      68             :         unsigned int            *resblks)
      69             : {
      70       37459 :         struct xfs_mount        *mp = sc->mp;
      71       37459 :         char                    *descr;
      72       37459 :         unsigned long long      blocks = 0;
      73       37459 :         unsigned long long      rtbmp_words;
      74       37459 :         size_t                  bufsize = mp->m_sb.sb_blocksize;
      75       37459 :         int                     error;
      76             : 
      77       37459 :         error = xrep_tempfile_create(sc, S_IFREG);
      78       37459 :         if (error)
      79             :                 return error;
      80             : 
      81             :         /* Create an xfile to hold our reconstructed bitmap. */
      82       37459 :         rtbmp_words = xfs_rtbitmap_wordcount(mp, mp->m_sb.sb_rextents);
      83       37459 :         descr = xchk_xfile_rtgroup_descr(sc, "bitmap file");
      84       37459 :         error = xfile_create(descr, rtbmp_words << XFS_WORDLOG, &sc->xfile);
      85       37459 :         kfree(descr);
      86       37459 :         if (error)
      87             :                 return error;
      88             : 
      89       37459 :         bufsize = max(bufsize, sizeof(struct xrep_tempswap));
      90             : 
      91             :         /*
      92             :          * Allocate a memory buffer for faster creation of new bitmap
      93             :          * blocks.
      94             :          */
      95       37459 :         sc->buf = kvmalloc(bufsize, XCHK_GFP_FLAGS);
      96       37459 :         if (!sc->buf)
      97             :                 return -ENOMEM;
      98             : 
      99             :         /*
     100             :          * Reserve enough blocks to write out a completely new bitmap file,
     101             :          * plus twice as many blocks as we would need if we can only allocate
     102             :          * one block per data fork mapping.  This should cover the
     103             :          * preallocation of the temporary file and swapping the extent
     104             :          * mappings.
     105             :          *
     106             :          * We cannot use xfs_swapext_estimate because we have not yet
     107             :          * constructed the replacement bitmap and therefore do not know how
     108             :          * many extents it will use.  By the time we do, we will have a dirty
     109             :          * transaction (which we cannot drop because we cannot drop the
     110             :          * rtbitmap ILOCK) and cannot ask for more reservation.
     111             :          */
     112       37459 :         blocks = mp->m_sb.sb_rbmblocks;
     113       37459 :         blocks += xfs_bmbt_calc_size(mp, blocks) * 2;
     114       37459 :         if (blocks > UINT_MAX)
     115             :                 return -EOPNOTSUPP;
     116             : 
     117       37459 :         *resblks += blocks;
     118             : 
     119             :         /*
     120             :          * Grab support for atomic extent swapping before we allocate any
     121             :          * transactions or grab ILOCKs.
     122             :          */
     123       37459 :         return xrep_tempswap_grab_log_assist(sc);
     124             : }
     125             : 
     126             : static inline xrep_wordoff_t
     127             : rtx_to_wordoff(
     128             :         struct xfs_mount        *mp,
     129             :         xfs_rtxnum_t            rtx)
     130             : {
     131      939340 :         return rtx >> XFS_NBWORDLOG;
     132             : }
     133             : 
     134             : static inline xrep_wordcnt_t
     135             : rtxlen_to_wordcnt(
     136             :         xfs_rtxlen_t    rtxlen)
     137             : {
     138       52545 :         return rtxlen >> XFS_NBWORDLOG;
     139             : }
     140             : 
     141             : /* Helper functions to record rtwords in an xfile. */
     142             : 
     143             : static inline int
     144      839620 : xfbmp_load(
     145             :         struct xrep_rgbmp       *rb,
     146             :         xrep_wordoff_t          wordoff,
     147             :         xfs_rtword_t            *word)
     148             : {
     149      839620 :         union xfs_rtword_ondisk urk;
     150      839620 :         int                     error;
     151             : 
     152      839620 :         error = xfile_obj_load(rb->sc->xfile, &urk,
     153             :                         sizeof(union xfs_rtword_ondisk),
     154      839620 :                         wordoff << XFS_WORDLOG);
     155      839620 :         if (error)
     156             :                 return error;
     157             : 
     158      839620 :         *word = xfs_rtbitmap_getword(rb->sc->mp, &urk);
     159      839620 :         return 0;
     160             : }
     161             : 
     162             : static inline int
     163      839620 : xfbmp_store(
     164             :         struct xrep_rgbmp       *rb,
     165             :         xrep_wordoff_t          wordoff,
     166             :         const xfs_rtword_t      word)
     167             : {
     168      839620 :         union xfs_rtword_ondisk urk;
     169             : 
     170      839620 :         xfs_rtbitmap_setword(rb->sc->mp, &urk, word);
     171     1679240 :         return xfile_obj_store(rb->sc->xfile, &urk,
     172             :                         sizeof(union xfs_rtword_ondisk),
     173      839620 :                         wordoff << XFS_WORDLOG);
     174             : }
     175             : 
     176             : static inline int
     177     1446618 : xfbmp_copyin(
     178             :         struct xrep_rgbmp       *rb,
     179             :         xrep_wordoff_t          wordoff,
     180             :         const union xfs_rtword_ondisk   *word,
     181             :         xrep_wordcnt_t          nr_words)
     182             : {
     183     2893236 :         return xfile_obj_store(rb->sc->xfile, word, nr_words << XFS_WORDLOG,
     184     1446618 :                         wordoff << XFS_WORDLOG);
     185             : }
     186             : 
     187             : static inline int
     188     1806265 : xfbmp_copyout(
     189             :         struct xrep_rgbmp       *rb,
     190             :         xrep_wordoff_t          wordoff,
     191             :         union xfs_rtword_ondisk *word,
     192             :         xrep_wordcnt_t          nr_words)
     193             : {
     194     3612530 :         return xfile_obj_load(rb->sc->xfile, word, nr_words << XFS_WORDLOG,
     195     1806265 :                         wordoff << XFS_WORDLOG);
     196             : }
     197             : 
     198             : /*
     199             :  * Preserve the portions of the rtbitmap block for the start of this rtgroup
     200             :  * that map to the previous rtgroup.
     201             :  */
     202             : STATIC int
     203       32841 : xrep_rgbitmap_load_before(
     204             :         struct xrep_rgbmp       *rb)
     205             : {
     206       32841 :         struct xfs_scrub        *sc = rb->sc;
     207       32841 :         struct xfs_mount        *mp = sc->mp;
     208       32841 :         struct xfs_rtgroup      *rtg = sc->sr.rtg;
     209       32841 :         struct xfs_buf          *bp;
     210       32841 :         xrep_wordoff_t          wordoff;
     211       32841 :         xfs_rtblock_t           group_rtbno;
     212       32841 :         xfs_rtxnum_t            group_rtx, rbmoff_rtx;
     213       32841 :         xfs_rtword_t            ondisk_word;
     214       32841 :         xfs_rtword_t            xfile_word;
     215       32841 :         xfs_rtword_t            mask;
     216       32841 :         xrep_wordcnt_t          wordcnt;
     217       32841 :         int                     bit;
     218       32841 :         int                     error;
     219             : 
     220             :         /*
     221             :          * Compute the file offset within the rtbitmap block that corresponds
     222             :          * to the start of this group, and decide if we need to read blocks
     223             :          * from the group before this one.
     224             :          */
     225       32841 :         group_rtbno = xfs_rgbno_to_rtb(mp, rtg->rtg_rgno, 0);
     226       32841 :         group_rtx = xfs_rtb_to_rtxt(mp, group_rtbno);
     227             : 
     228       32841 :         rb->group_rbmoff = xfs_rtx_to_rbmblock(mp, group_rtx);
     229       32841 :         rbmoff_rtx = xfs_rbmblock_to_rtx(mp, rb->group_rbmoff);
     230       32841 :         rb->prep_wordoff = rtx_to_wordoff(mp, rbmoff_rtx);
     231             : 
     232       32841 :         trace_xrep_rgbitmap_load(rtg, rb->group_rbmoff, rbmoff_rtx,
     233             :                         group_rtx - 1);
     234             : 
     235       32841 :         if (rbmoff_rtx == group_rtx)
     236             :                 return 0;
     237             : 
     238       26272 :         error = xfs_rtbuf_get(mp, sc->tp, rb->group_rbmoff, 0, &bp);
     239       26272 :         if (error) {
     240             :                 /*
     241             :                  * Reading the existing rbmblock failed, and we must deal with
     242             :                  * the part of the rtbitmap block that corresponds to the
     243             :                  * previous group.  The most conservative option is to fill
     244             :                  * that part of the bitmap with zeroes so that it won't get
     245             :                  * allocated.  The xfile contains zeroes already, so we can
     246             :                  * return.
     247             :                  */
     248             :                 return 0;
     249             :         }
     250             : 
     251             :         /*
     252             :          * Copy full rtbitmap words into memory from the beginning of the
     253             :          * ondisk block until we get to the word that corresponds to the start
     254             :          * of this group.
     255             :          */
     256       26272 :         wordoff = rtx_to_wordoff(mp, rbmoff_rtx);
     257       26272 :         wordcnt = rtxlen_to_wordcnt(group_rtx - rbmoff_rtx);
     258       26272 :         if (wordcnt > 0) {
     259       26272 :                 union xfs_rtword_ondisk *p;
     260             : 
     261       26272 :                 p = xfs_rbmblock_wordptr(bp, 0);
     262       26272 :                 error = xfbmp_copyin(rb, wordoff, p, wordcnt);
     263       26272 :                 if (error)
     264           0 :                         goto out_rele;
     265             : 
     266       26272 :                 trace_xrep_rgbitmap_load_words(mp, rb->group_rbmoff, wordoff,
     267             :                                 wordcnt);
     268       26272 :                 wordoff += wordcnt;
     269             :         }
     270             : 
     271             :         /*
     272             :          * Compute the bit position of the first rtextent of this group.  If
     273             :          * the bit position is zero, we don't have to RMW a partial word and
     274             :          * move to the next step.
     275             :          */
     276       26272 :         bit = group_rtx & XREP_RTBMP_WORDMASK;
     277       26272 :         if (bit == 0)
     278       26272 :                 goto out_rele;
     279             : 
     280             :         /*
     281             :          * Create a mask of the bits that we want to load from disk.  These
     282             :          * bits track space in a different rtgroup, which is why we must
     283             :          * preserve them even as we replace parts of the bitmap.
     284             :          */
     285           0 :         mask = ~((((xfs_rtword_t)1 << (XFS_NBWORD - bit)) - 1) << bit);
     286             : 
     287           0 :         error = xfbmp_load(rb, wordoff, &xfile_word);
     288           0 :         if (error)
     289           0 :                 goto out_rele;
     290           0 :         ondisk_word = xfs_rtbitmap_getword(mp,
     291             :                         xfs_rbmblock_wordptr(bp, wordcnt));
     292             : 
     293           0 :         trace_xrep_rgbitmap_load_word(mp, wordoff, bit, ondisk_word,
     294             :                         xfile_word, mask);
     295             : 
     296           0 :         xfile_word &= ~mask;
     297           0 :         xfile_word |= (ondisk_word & mask);
     298             : 
     299           0 :         error = xfbmp_store(rb, wordoff, xfile_word);
     300           0 :         if (error)
     301           0 :                 goto out_rele;
     302             : 
     303           0 : out_rele:
     304       26272 :         xfs_trans_brelse(sc->tp, bp);
     305       26272 :         return error;
     306             : }
     307             : 
     308             : /*
     309             :  * Preserve the portions of the rtbitmap block for the end of this rtgroup
     310             :  * that map to the next rtgroup.
     311             :  */
     312             : STATIC int
     313       32841 : xrep_rgbitmap_load_after(
     314             :         struct xrep_rgbmp       *rb)
     315             : {
     316       32841 :         struct xfs_scrub        *sc = rb->sc;
     317       32841 :         struct xfs_mount        *mp = rb->sc->mp;
     318       32841 :         struct xfs_rtgroup      *rtg = rb->sc->sr.rtg;
     319       32841 :         struct xfs_buf          *bp;
     320       32841 :         xrep_wordoff_t          wordoff;
     321       32841 :         xfs_rtblock_t           last_rtbno;
     322       32841 :         xfs_rtxnum_t            last_group_rtx, last_rbmblock_rtx;
     323       32841 :         xfs_fileoff_t           last_group_rbmoff;
     324       32841 :         xfs_rtword_t            ondisk_word;
     325       32841 :         xfs_rtword_t            xfile_word;
     326       32841 :         xfs_rtword_t            mask;
     327       32841 :         xrep_wordcnt_t          wordcnt;
     328       32841 :         unsigned int            last_group_word;
     329       32841 :         int                     bit;
     330       32841 :         int                     error;
     331             : 
     332       32841 :         last_rtbno = xfs_rgbno_to_rtb(mp, rtg->rtg_rgno,
     333       32841 :                                         rtg->rtg_blockcount - 1);
     334       32841 :         last_group_rtx = xfs_rtb_to_rtxt(mp, last_rtbno);
     335             : 
     336       32841 :         last_group_rbmoff = xfs_rtx_to_rbmblock(mp, last_group_rtx);
     337       32841 :         rb->group_rbmlen = last_group_rbmoff - rb->group_rbmoff + 1;
     338       32841 :         last_rbmblock_rtx = xfs_rbmblock_to_rtx(mp, last_group_rbmoff + 1) - 1;
     339             : 
     340       32841 :         trace_xrep_rgbitmap_load(rtg, last_group_rbmoff, last_group_rtx + 1,
     341             :                         last_rbmblock_rtx);
     342             : 
     343       32841 :         if (last_rbmblock_rtx == last_group_rtx ||
     344       32841 :             rtg->rtg_rgno == mp->m_sb.sb_rgcount - 1)
     345             :                 return 0;
     346             : 
     347       26273 :         error = xfs_rtbuf_get(mp, sc->tp, last_group_rbmoff, 0, &bp);
     348       26273 :         if (error) {
     349             :                 /*
     350             :                  * Reading the existing rbmblock failed, and we must deal with
     351             :                  * the part of the rtbitmap block that corresponds to the
     352             :                  * previous group.  The most conservative option is to fill
     353             :                  * that part of the bitmap with zeroes so that it won't get
     354             :                  * allocated.  The xfile contains zeroes already, so we can
     355             :                  * return.
     356             :                  */
     357             :                 return 0;
     358             :         }
     359             : 
     360             :         /*
     361             :          * Compute the bit position of the first rtextent of the next group.
     362             :          * If the bit position is zero, we don't have to RMW a partial word
     363             :          * and move to the next step.
     364             :          */
     365       26273 :         wordoff = rtx_to_wordoff(mp, last_group_rtx);
     366       26273 :         bit = (last_group_rtx + 1) & XREP_RTBMP_WORDMASK;
     367       26273 :         if (bit == 0)
     368       26273 :                 goto copy_words;
     369             : 
     370             :         /*
     371             :          * Create a mask of the bits that we want to load from disk.  These
     372             :          * bits track space in a different rtgroup, which is why we must
     373             :          * preserve them even as we replace parts of the bitmap.
     374             :          */
     375           0 :         mask = (((xfs_rtword_t)1 << (XFS_NBWORD - bit)) - 1) << bit;
     376             : 
     377           0 :         error = xfbmp_load(rb, wordoff, &xfile_word);
     378           0 :         if (error)
     379           0 :                 goto out_rele;
     380           0 :         last_group_word = xfs_rtx_to_rbmword(mp, last_group_rtx);
     381           0 :         ondisk_word = xfs_rtbitmap_getword(mp,
     382             :                         xfs_rbmblock_wordptr(bp, last_group_word));
     383             : 
     384           0 :         trace_xrep_rgbitmap_load_word(mp, wordoff, bit, ondisk_word,
     385             :                         xfile_word, mask);
     386             : 
     387           0 :         xfile_word &= ~mask;
     388           0 :         xfile_word |= (ondisk_word & mask);
     389             : 
     390           0 :         error = xfbmp_store(rb, wordoff, xfile_word);
     391           0 :         if (error)
     392           0 :                 goto out_rele;
     393             : 
     394           0 : copy_words:
     395             :         /* Copy as many full words as we can. */
     396       26273 :         wordoff++;
     397       26273 :         wordcnt = rtxlen_to_wordcnt(last_rbmblock_rtx - last_group_rtx);
     398       26273 :         if (wordcnt > 0) {
     399       26273 :                 union xfs_rtword_ondisk *p;
     400             : 
     401       26273 :                 p = xfs_rbmblock_wordptr(bp, mp->m_blockwsize - wordcnt);
     402       26273 :                 error = xfbmp_copyin(rb, wordoff, p, wordcnt);
     403       26273 :                 if (error)
     404           0 :                         goto out_rele;
     405             : 
     406       26273 :                 trace_xrep_rgbitmap_load_words(mp, last_group_rbmoff, wordoff,
     407             :                                 wordcnt);
     408             :         }
     409             : 
     410           0 : out_rele:
     411       26273 :         xfs_trans_brelse(sc->tp, bp);
     412       26273 :         return error;
     413             : }
     414             : 
     415             : /* Perform a logical OR operation on an rtword in the incore bitmap. */
     416             : static int
     417      839620 : xrep_rgbitmap_or(
     418             :         struct xrep_rgbmp       *rb,
     419             :         xrep_wordoff_t          wordoff,
     420             :         xfs_rtword_t            mask)
     421             : {
     422      839620 :         xfs_rtword_t            word;
     423      839620 :         int                     error;
     424             : 
     425      839620 :         error = xfbmp_load(rb, wordoff, &word);
     426      839620 :         if (error)
     427             :                 return error;
     428             : 
     429      839620 :         trace_xrep_rgbitmap_or(rb->sc->mp, wordoff, mask, word);
     430             : 
     431      839620 :         return xfbmp_store(rb, wordoff, word | mask);
     432             : }
     433             : 
     434             : /*
     435             :  * Mark as free every rt extent between the next rt block we expected to see
     436             :  * in the rtrmap records and the given rt block.
     437             :  */
     438             : STATIC int
     439      734749 : xrep_rgbitmap_mark_free(
     440             :         struct xrep_rgbmp       *rb,
     441             :         xfs_rgblock_t           rgbno)
     442             : {
     443      734749 :         struct xfs_mount        *mp = rb->sc->mp;
     444      734749 :         struct xfs_rtgroup      *rtg = rb->sc->sr.rtg;
     445      734749 :         xfs_rtblock_t           rtbno;
     446      734749 :         xfs_rtxnum_t            startrtx;
     447      734749 :         xfs_rtxnum_t            nextrtx;
     448      734749 :         xrep_wordoff_t          wordoff, nextwordoff;
     449      734749 :         unsigned int            bit;
     450      734749 :         unsigned int            bufwsize;
     451      734749 :         xfs_extlen_t            mod;
     452      734749 :         xfs_rtword_t            mask;
     453      734749 :         enum xbtree_recpacking  outcome;
     454      734749 :         int                     error;
     455             : 
     456      734749 :         if (!xfs_verify_rgbext(rtg, rb->next_rgbno, rgbno - rb->next_rgbno))
     457             :                 return -EFSCORRUPTED;
     458             : 
     459             :         /*
     460             :          * Convert rt blocks to rt extents  The block range we find must be
     461             :          * aligned to an rtextent boundary on both ends.
     462             :          */
     463      734749 :         rtbno = xfs_rgbno_to_rtb(mp, rtg->rtg_rgno, rb->next_rgbno);
     464      734749 :         startrtx = xfs_rtb_to_rtx(mp, rtbno, &mod);
     465      734749 :         if (mod)
     466             :                 return -EFSCORRUPTED;
     467             : 
     468      734749 :         rtbno = xfs_rgbno_to_rtb(mp, rtg->rtg_rgno, rgbno - 1);
     469      734749 :         nextrtx = xfs_rtb_to_rtx(mp, rtbno, &mod) + 1;
     470      734749 :         if (mod != mp->m_sb.sb_rextsize - 1)
     471             :                 return -EFSCORRUPTED;
     472             : 
     473             :         /* Must not be shared or CoW staging. */
     474      734749 :         if (rb->sc->sr.refc_cur) {
     475      734749 :                 error = xfs_refcount_has_records(rb->sc->sr.refc_cur,
     476             :                                 XFS_REFC_DOMAIN_SHARED, rb->next_rgbno,
     477             :                                 rgbno - rb->next_rgbno, &outcome);
     478      734749 :                 if (error)
     479             :                         return error;
     480      734749 :                 if (outcome != XBTREE_RECPACKING_EMPTY)
     481             :                         return -EFSCORRUPTED;
     482             : 
     483      734749 :                 error = xfs_refcount_has_records(rb->sc->sr.refc_cur,
     484             :                                 XFS_REFC_DOMAIN_COW, rb->next_rgbno,
     485             :                                 rgbno - rb->next_rgbno, &outcome);
     486      734749 :                 if (error)
     487             :                         return error;
     488      734749 :                 if (outcome != XBTREE_RECPACKING_EMPTY)
     489             :                         return -EFSCORRUPTED;
     490             :         }
     491             : 
     492      734749 :         trace_xrep_rgbitmap_record_free(mp, startrtx, nextrtx - 1);
     493             : 
     494             :         /* Set bits as needed to round startrtx up to the nearest word. */
     495      734749 :         bit = startrtx & XREP_RTBMP_WORDMASK;
     496      734749 :         if (bit) {
     497      709218 :                 xfs_rtblock_t   len = nextrtx - startrtx;
     498      709218 :                 unsigned int    lastbit;
     499             : 
     500      709218 :                 lastbit = XFS_RTMIN(bit + len, XFS_NBWORD);
     501      709218 :                 mask = (((xfs_rtword_t)1 << (lastbit - bit)) - 1) << bit;
     502             : 
     503      709218 :                 error = xrep_rgbitmap_or(rb, rtx_to_wordoff(mp, startrtx), mask);
     504      709218 :                 if (error || lastbit - bit == len)
     505             :                         return error;
     506      138370 :                 startrtx += XFS_NBWORD - bit;
     507             :         }
     508             : 
     509             :         /* Set bits as needed to round nextrtx down to the nearest word. */
     510      163901 :         bit = nextrtx & XREP_RTBMP_WORDMASK;
     511      163901 :         if (bit) {
     512      130402 :                 mask = ((xfs_rtword_t)1 << bit) - 1;
     513             : 
     514      130402 :                 error = xrep_rgbitmap_or(rb, rtx_to_wordoff(mp, nextrtx), mask);
     515      130402 :                 if (error || startrtx + bit == nextrtx)
     516             :                         return error;
     517        7107 :                 nextrtx -= bit;
     518             :         }
     519             : 
     520       40606 :         trace_xrep_rgbitmap_record_free_bulk(mp, startrtx, nextrtx - 1);
     521             : 
     522             :         /* Set all the words in between, up to a whole fs block at once. */
     523       40606 :         wordoff = rtx_to_wordoff(mp, startrtx);
     524       40606 :         nextwordoff = rtx_to_wordoff(mp, nextrtx);
     525       40606 :         bufwsize = mp->m_sb.sb_blocksize >> XFS_WORDLOG;
     526             : 
     527     1434679 :         while (wordoff < nextwordoff) {
     528     1394073 :                 xrep_wordoff_t  rem;
     529     1394073 :                 xrep_wordcnt_t  wordcnt;
     530             : 
     531     1394073 :                 wordcnt = min_t(xrep_wordcnt_t, nextwordoff - wordoff,
     532             :                                 bufwsize);
     533             : 
     534             :                 /*
     535             :                  * Try to keep us aligned to sc->buf to reduce the number of
     536             :                  * xfile writes.
     537             :                  */
     538     1394073 :                 rem = wordoff & (bufwsize - 1);
     539     1394073 :                 if (rem)
     540       40587 :                         wordcnt = min_t(xrep_wordcnt_t, wordcnt,
     541             :                                         bufwsize - rem);
     542             : 
     543     1394073 :                 error = xfbmp_copyin(rb, wordoff, rb->sc->buf, wordcnt);
     544     1394073 :                 if (error)
     545           0 :                         return error;
     546             : 
     547     1394073 :                 wordoff += wordcnt;
     548             :         }
     549             : 
     550             :         return 0;
     551             : }
     552             : 
     553             : /* Set free space in the rtbitmap based on rtrmapbt records. */
     554             : STATIC int
     555  1236918701 : xrep_rgbitmap_walk_rtrmap(
     556             :         struct xfs_btree_cur            *cur,
     557             :         const struct xfs_rmap_irec      *rec,
     558             :         void                            *priv)
     559             : {
     560  1236918701 :         struct xrep_rgbmp               *rb = priv;
     561  1236918701 :         int                             error = 0;
     562             : 
     563  1236918701 :         if (xchk_should_terminate(rb->sc, &error))
     564           0 :                 return error;
     565             : 
     566  1236918701 :         if (rb->next_rgbno < rec->rm_startblock) {
     567      718491 :                 error = xrep_rgbitmap_mark_free(rb, rec->rm_startblock);
     568      718491 :                 if (error)
     569             :                         return error;
     570             :         }
     571             : 
     572  1236918701 :         rb->next_rgbno = max(rb->next_rgbno,
     573             :                         rec->rm_startblock + rec->rm_blockcount);
     574  1236918701 :         return 0;
     575             : }
     576             : 
     577             : /*
     578             :  * Walk the rtrmapbt to find all the gaps between records, and mark the gaps
     579             :  * in the realtime bitmap that we're computing.
     580             :  */
     581             : STATIC int
     582       32841 : xrep_rgbitmap_find_freespace(
     583             :         struct xrep_rgbmp       *rb)
     584             : {
     585       32841 :         struct xfs_scrub        *sc = rb->sc;
     586       32841 :         struct xfs_mount        *mp = sc->mp;
     587       32841 :         struct xfs_rtgroup      *rtg = sc->sr.rtg;
     588       32841 :         int                     error;
     589             : 
     590             :         /* Prepare a buffer of ones so that we can accelerate bulk setting. */
     591       32841 :         memset(sc->buf, 0xFF, mp->m_sb.sb_blocksize);
     592             : 
     593       32841 :         xrep_rtgroup_btcur_init(sc, &sc->sr);
     594       32841 :         error = xfs_rmap_query_all(sc->sr.rmap_cur, xrep_rgbitmap_walk_rtrmap,
     595             :                         rb);
     596       32841 :         if (error)
     597           0 :                 goto out;
     598             : 
     599             :         /*
     600             :          * Mark as free every possible rt extent from the last one we saw to
     601             :          * the end of the rt group.
     602             :          */
     603       32841 :         if (rb->next_rgbno < rtg->rtg_blockcount) {
     604       16258 :                 error = xrep_rgbitmap_mark_free(rb, rtg->rtg_blockcount);
     605       16258 :                 if (error)
     606           0 :                         goto out;
     607             :         }
     608             : 
     609       32841 : out:
     610       32841 :         xchk_rtgroup_btcur_free(&sc->sr);
     611       32841 :         return error;
     612             : }
     613             : 
     614             : static int
     615     1806265 : xrep_rgbitmap_prep_buf(
     616             :         struct xfs_scrub        *sc,
     617             :         struct xfs_buf          *bp,
     618             :         void                    *data)
     619             : {
     620     1806265 :         struct xrep_rgbmp       *rb = data;
     621     1806265 :         struct xfs_mount        *mp = sc->mp;
     622     1806265 :         int                     error;
     623             : 
     624     3612530 :         error = xfbmp_copyout(rb, rb->prep_wordoff,
     625             :                         xfs_rbmblock_wordptr(bp, 0), mp->m_blockwsize);
     626     1806265 :         if (error)
     627             :                 return error;
     628             : 
     629     1806265 :         if (xfs_has_rtgroups(sc->mp)) {
     630     1806265 :                 struct xfs_rtbuf_blkinfo        *hdr = bp->b_addr;
     631             : 
     632     1806265 :                 hdr->rt_magic = cpu_to_be32(XFS_RTBITMAP_MAGIC);
     633     1806265 :                 hdr->rt_owner = cpu_to_be64(sc->ip->i_ino);
     634     1806265 :                 hdr->rt_blkno = cpu_to_be64(xfs_buf_daddr(bp));
     635     1806265 :                 hdr->rt_lsn = 0;
     636     1806265 :                 uuid_copy(&hdr->rt_uuid, &sc->mp->m_sb.sb_meta_uuid);
     637     1806265 :                 bp->b_ops = &xfs_rtbitmap_buf_ops;
     638             :         } else {
     639           0 :                 bp->b_ops = &xfs_rtbuf_ops;
     640             :         }
     641             : 
     642     1806265 :         rb->prep_wordoff += mp->m_blockwsize;
     643     1806265 :         xfs_trans_buf_set_type(sc->tp, bp, XFS_BLFT_RTBITMAP_BUF);
     644     1806265 :         return 0;
     645             : }
     646             : 
     647             : /* Repair the realtime bitmap for this rt group. */
     648             : int
     649       32841 : xrep_rgbitmap(
     650             :         struct xfs_scrub        *sc)
     651             : {
     652       32841 :         struct xrep_rgbmp       rb = {
     653             :                 .sc             = sc,
     654             :                 .next_rgbno     = 0,
     655             :         };
     656       32841 :         struct xrep_tempswap    *ti = NULL;
     657       32841 :         int                     error;
     658             : 
     659             :         /*
     660             :          * We require the realtime rmapbt (and atomic file updates) to rebuild
     661             :          * anything.
     662             :          */
     663       32841 :         if (!xfs_has_rtrmapbt(sc->mp))
     664             :                 return -EOPNOTSUPP;
     665             : 
     666             :         /*
     667             :          * If the start or end of this rt group happens to be in the middle of
     668             :          * an rtbitmap block, try to read in the parts of the bitmap that are
     669             :          * from some other group.
     670             :          */
     671       32841 :         error = xrep_rgbitmap_load_before(&rb);
     672       32841 :         if (error)
     673             :                 return error;
     674       32841 :         error = xrep_rgbitmap_load_after(&rb);
     675       32841 :         if (error)
     676             :                 return error;
     677             : 
     678             :         /*
     679             :          * Generate the new rtbitmap data.  We don't need the rtbmp information
     680             :          * once this call is finished.
     681             :          */
     682       32841 :         error = xrep_rgbitmap_find_freespace(&rb);
     683       32841 :         if (error)
     684             :                 return error;
     685             : 
     686             :         /*
     687             :          * Try to take ILOCK_EXCL of the temporary file.  We had better be the
     688             :          * only ones holding onto this inode, but we can't block while holding
     689             :          * the rtbitmap file's ILOCK_EXCL.
     690             :          */
     691       32842 :         while (!xrep_tempfile_ilock_nowait(sc)) {
     692           1 :                 if (xchk_should_terminate(sc, &error))
     693           0 :                         return error;
     694           1 :                 delay(1);
     695             :         }
     696             : 
     697             :         /*
     698             :          * Make sure we have space allocated for the part of the bitmap
     699             :          * file that corresponds to this group.
     700             :          */
     701       32841 :         xfs_trans_ijoin(sc->tp, sc->ip, 0);
     702       32841 :         xfs_trans_ijoin(sc->tp, sc->tempip, 0);
     703       32841 :         error = xrep_tempfile_prealloc(sc, rb.group_rbmoff, rb.group_rbmlen);
     704       32841 :         if (error)
     705             :                 return error;
     706             : 
     707             :         /* Last chance to abort before we start committing fixes. */
     708       32841 :         if (xchk_should_terminate(sc, &error))
     709           0 :                 return error;
     710             : 
     711             :         /* Copy the bitmap file that we generated. */
     712       32841 :         error = xrep_tempfile_copyin(sc, rb.group_rbmoff, rb.group_rbmlen,
     713             :                         xrep_rgbitmap_prep_buf, &rb);
     714       32841 :         if (error)
     715             :                 return error;
     716       65682 :         error = xrep_tempfile_set_isize(sc,
     717       32841 :                         XFS_FSB_TO_B(sc->mp, sc->mp->m_sb.sb_rbmblocks));
     718       32841 :         if (error)
     719             :                 return error;
     720             : 
     721             :         /*
     722             :          * Now swap the extents.  We're done with the temporary buffer, so
     723             :          * we can reuse it for the tempfile swapext information.
     724             :          */
     725       32841 :         ti = sc->buf;
     726       32841 :         error = xrep_tempswap_trans_reserve(sc, XFS_DATA_FORK, rb.group_rbmoff,
     727             :                         rb.group_rbmlen, ti);
     728       32841 :         if (error)
     729             :                 return error;
     730             : 
     731       32841 :         error = xrep_tempswap_contents(sc, ti);
     732       32841 :         if (error)
     733             :                 return error;
     734       32841 :         ti = NULL;
     735             : 
     736             :         /* Free the old bitmap blocks if they are free. */
     737       32841 :         return xrep_reap_ifork(sc, sc->tempip, XFS_DATA_FORK);
     738             : }
     739             : 
     740             : /* Set up to repair the realtime bitmap file metadata. */
     741             : int
     742        6569 : xrep_setup_rtbitmap(
     743             :         struct xfs_scrub        *sc,
     744             :         unsigned int            *resblks)
     745             : {
     746        6569 :         struct xfs_mount        *mp = sc->mp;
     747        6569 :         unsigned long long      blocks = 0;
     748             : 
     749             :         /*
     750             :          * Reserve enough blocks to write out a completely new bmbt for the
     751             :          * bitmap file.
     752             :          */
     753        6569 :         blocks = xfs_bmbt_calc_size(mp, mp->m_sb.sb_rbmblocks);
     754        6569 :         if (blocks > UINT_MAX)
     755             :                 return -EOPNOTSUPP;
     756             : 
     757        6569 :         *resblks += blocks;
     758        6569 :         return 0;
     759             : }
     760             : 
     761             : /* Repair the realtime bitmap file metadata. */
     762             : int
     763        6569 : xrep_rtbitmap(
     764             :         struct xfs_scrub        *sc)
     765             : {
     766             :         /*
     767             :          * The only thing we know how to fix right now is problems with the
     768             :          * inode or its fork data.
     769             :          */
     770        6569 :         return xrep_metadata_inode_forks(sc);
     771             : }

Generated by: LCOV version 1.14