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-rc3-achx @ Mon Jul 31 20:08:12 PDT 2023 Lines: 12 52 23.1 %
Date: 2023-07-31 20:08:12 Functions: 1 3 33.3 %

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

Generated by: LCOV version 1.14