LCOV - code coverage report
Current view: top level - fs/xfs/scrub - rtsummary_repair.c (source / functions) Hit Total Coverage
Test: fstests of 6.5.0-rc4-xfsa @ Mon Jul 31 20:08:27 PDT 2023 Lines: 55 60 91.7 %
Date: 2023-07-31 20:08:27 Functions: 3 3 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_swapext.h"
      21             : #include "xfs_rtbitmap.h"
      22             : #include "scrub/scrub.h"
      23             : #include "scrub/common.h"
      24             : #include "scrub/trace.h"
      25             : #include "scrub/repair.h"
      26             : #include "scrub/tempfile.h"
      27             : #include "scrub/tempswap.h"
      28             : #include "scrub/reap.h"
      29             : #include "scrub/xfile.h"
      30             : #include "scrub/rtsummary.h"
      31             : 
      32             : struct xrep_rtsummary {
      33             :         /* suminfo position of xfile as we write buffers to disk. */
      34             :         xfs_rtsumoff_t          prep_wordoff;
      35             : };
      36             : 
      37             : /* Set us up to repair the rtsummary file. */
      38             : int
      39       21328 : xrep_setup_rtsummary(
      40             :         struct xfs_scrub        *sc,
      41             :         unsigned int            *resblks,
      42             :         size_t                  *bufsize)
      43             : {
      44       21328 :         struct xfs_mount        *mp = sc->mp;
      45       21328 :         unsigned long long      blocks;
      46       21328 :         int                     error;
      47             : 
      48       21328 :         *bufsize = max(*bufsize, sizeof(struct xrep_tempswap));
      49             : 
      50       21328 :         error = xrep_tempfile_create(sc, S_IFREG);
      51       21328 :         if (error)
      52             :                 return error;
      53             : 
      54             :         /*
      55             :          * If we're doing a repair, we reserve enough blocks to write out a
      56             :          * completely new summary file, plus twice as many blocks as we would
      57             :          * need if we can only allocate one block per data fork mapping.  This
      58             :          * should cover the preallocation of the temporary file and swapping
      59             :          * the extent mappings.
      60             :          *
      61             :          * We cannot use xfs_swapext_estimate because we have not yet
      62             :          * constructed the replacement rtsummary and therefore do not know how
      63             :          * many extents it will use.  By the time we do, we will have a dirty
      64             :          * transaction (which we cannot drop because we cannot drop the
      65             :          * rtsummary ILOCK) and cannot ask for more reservation.
      66             :          */
      67       21328 :         blocks = XFS_B_TO_FSB(mp, mp->m_rsumsize);
      68       21328 :         blocks += xfs_bmbt_calc_size(mp, blocks) * 2;
      69       21328 :         if (blocks > UINT_MAX)
      70             :                 return -EOPNOTSUPP;
      71             : 
      72       21328 :         *resblks += blocks;
      73             : 
      74             :         /*
      75             :          * Grab support for atomic extent swapping before we allocate any
      76             :          * transactions or grab ILOCKs.
      77             :          */
      78       21328 :         return xrep_tempswap_grab_log_assist(sc);
      79             : }
      80             : 
      81             : static int
      82      149296 : xrep_rtsummary_prep_buf(
      83             :         struct xfs_scrub        *sc,
      84             :         struct xfs_buf          *bp,
      85             :         void                    *data)
      86             : {
      87      149296 :         struct xrep_rtsummary   *rs = data;
      88      149296 :         struct xfs_mount        *mp = sc->mp;
      89      149296 :         int                     error;
      90             : 
      91      298592 :         error = xfsum_copyout(sc, rs->prep_wordoff,
      92             :                         xfs_rsumblock_infoptr(bp, 0), mp->m_blockwsize);
      93      149296 :         if (error)
      94             :                 return error;
      95             : 
      96      149296 :         if (xfs_has_rtgroups(sc->mp)) {
      97      149296 :                 struct xfs_rtbuf_blkinfo        *hdr = bp->b_addr;
      98             : 
      99      149296 :                 hdr->rt_magic = cpu_to_be32(XFS_RTSUMMARY_MAGIC);
     100      149296 :                 hdr->rt_owner = cpu_to_be64(sc->ip->i_ino);
     101      149296 :                 hdr->rt_blkno = cpu_to_be64(xfs_buf_daddr(bp));
     102      149296 :                 hdr->rt_lsn = 0;
     103      149296 :                 uuid_copy(&hdr->rt_uuid, &sc->mp->m_sb.sb_meta_uuid);
     104      149296 :                 bp->b_ops = &xfs_rtsummary_buf_ops;
     105             :         } else {
     106           0 :                 bp->b_ops = &xfs_rtbuf_ops;
     107             :         }
     108             : 
     109      149296 :         rs->prep_wordoff += mp->m_blockwsize;
     110      149296 :         xfs_trans_buf_set_type(sc->tp, bp, XFS_BLFT_RTSUMMARY_BUF);
     111      149296 :         return 0;
     112             : }
     113             : 
     114             : /* Repair the realtime summary. */
     115             : int
     116       21328 : xrep_rtsummary(
     117             :         struct xfs_scrub        *sc)
     118             : {
     119       21328 :         struct xrep_rtsummary   rs = { .prep_wordoff = 0, };
     120       21328 :         struct xrep_tempswap    *ti = NULL;
     121       21328 :         xfs_filblks_t           rsumblocks;
     122       21328 :         int                     error;
     123             : 
     124             :         /* We require the rmapbt to rebuild anything. */
     125       21328 :         if (!xfs_has_rmapbt(sc->mp))
     126             :                 return -EOPNOTSUPP;
     127             : 
     128             :         /* Make sure any problems with the fork are fixed. */
     129       21328 :         error = xrep_metadata_inode_forks(sc);
     130       21328 :         if (error)
     131             :                 return error;
     132             : 
     133             :         /*
     134             :          * Try to take ILOCK_EXCL of the temporary file.  We had better be the
     135             :          * only ones holding onto this inode, but we can't block while holding
     136             :          * the rtsummary file's ILOCK_EXCL.
     137             :          */
     138       21328 :         while (!xrep_tempfile_ilock_nowait(sc)) {
     139           0 :                 if (xchk_should_terminate(sc, &error))
     140           0 :                         return error;
     141           0 :                 delay(1);
     142             :         }
     143             : 
     144             :         /* Make sure we have space allocated for the entire summary file. */
     145       21328 :         rsumblocks = XFS_B_TO_FSB(sc->mp, sc->mp->m_rsumsize);
     146       21328 :         xfs_trans_ijoin(sc->tp, sc->ip, 0);
     147       21328 :         xfs_trans_ijoin(sc->tp, sc->tempip, 0);
     148       21328 :         error = xrep_tempfile_prealloc(sc, 0, rsumblocks);
     149       21328 :         if (error)
     150             :                 return error;
     151             : 
     152             :         /* Last chance to abort before we start committing fixes. */
     153       21328 :         if (xchk_should_terminate(sc, &error))
     154           0 :                 return error;
     155             : 
     156             :         /* Copy the rtsummary file that we generated. */
     157       21328 :         error = xrep_tempfile_copyin(sc, 0, rsumblocks,
     158             :                         xrep_rtsummary_prep_buf, &rs);
     159       21328 :         if (error)
     160             :                 return error;
     161       21328 :         error = xrep_tempfile_set_isize(sc, sc->mp->m_rsumsize);
     162       21328 :         if (error)
     163             :                 return error;
     164             : 
     165             :         /*
     166             :          * Now swap the extents.  Nothing in repair uses the temporary buffer,
     167             :          * so we can reuse it for the tempfile swapext information.
     168             :          */
     169       21328 :         ti = sc->buf;
     170       21328 :         error = xrep_tempswap_trans_reserve(sc, XFS_DATA_FORK, 0, rsumblocks,
     171             :                         ti);
     172       21328 :         if (error)
     173             :                 return error;
     174             : 
     175       21328 :         error = xrep_tempswap_contents(sc, ti);
     176       21328 :         if (error)
     177             :                 return error;
     178       21328 :         ti = NULL;
     179             : 
     180             :         /* Free the old rtsummary blocks if they're not in use. */
     181       21328 :         return xrep_reap_ifork(sc, sc->tempip, XFS_DATA_FORK);
     182             : }

Generated by: LCOV version 1.14