]> www.infradead.org Git - users/hch/xfs.git/commitdiff
xfs: repair inodes that have realtime extents
authorDarrick J. Wong <djwong@kernel.org>
Wed, 29 May 2024 04:12:56 +0000 (21:12 -0700)
committerChristoph Hellwig <hch@lst.de>
Mon, 12 Aug 2024 11:53:02 +0000 (13:53 +0200)
Plumb into the inode core repair code the ability to search for extents
on realtime devices.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
fs/xfs/scrub/inode_repair.c

index 1cb173d8a0f3951976da63beb252de4185904e20..65233c729f29077d753e9cf380544f832123c044 100644 (file)
@@ -38,6 +38,8 @@
 #include "xfs_log_priv.h"
 #include "xfs_health.h"
 #include "xfs_symlink_remote.h"
+#include "xfs_rtgroup.h"
+#include "xfs_rtrmap_btree.h"
 #include "scrub/xfs_scrub.h"
 #include "scrub/scrub.h"
 #include "scrub/common.h"
@@ -773,18 +775,77 @@ xrep_dinode_count_ag_rmaps(
        return error;
 }
 
+/* Count extents and blocks for an inode given an rt rmap. */
+STATIC int
+xrep_dinode_walk_rtrmap(
+       struct xfs_btree_cur            *cur,
+       const struct xfs_rmap_irec      *rec,
+       void                            *priv)
+{
+       struct xrep_inode               *ri = priv;
+       int                             error = 0;
+
+       if (xchk_should_terminate(ri->sc, &error))
+               return error;
+
+       /* We only care about this inode. */
+       if (rec->rm_owner != ri->sc->sm->sm_ino)
+               return 0;
+
+       if (rec->rm_flags & (XFS_RMAP_ATTR_FORK | XFS_RMAP_BMBT_BLOCK))
+               return -EFSCORRUPTED;
+
+       ri->rt_blocks += rec->rm_blockcount;
+       ri->rt_extents++;
+       return 0;
+}
+
+/* Count extents and blocks for an inode from all realtime rmap data. */
+STATIC int
+xrep_dinode_count_rtgroup_rmaps(
+       struct xrep_inode       *ri,
+       struct xfs_rtgroup      *rtg)
+{
+       struct xfs_scrub        *sc = ri->sc;
+       int                     error;
+
+       if (!xfs_has_realtime(sc->mp) ||
+           xrep_is_rtmeta_ino(sc, rtg, sc->sm->sm_ino))
+               return 0;
+
+       error = xrep_rtgroup_init(sc, rtg, &sc->sr, XFS_RTGLOCK_RMAP);
+       if (error)
+               return error;
+
+       error = xfs_rmap_query_all(sc->sr.rmap_cur, xrep_dinode_walk_rtrmap,
+                       ri);
+       xchk_rtgroup_btcur_free(&sc->sr);
+       xchk_rtgroup_free(sc, &sc->sr);
+       return error;
+}
+
 /* Count extents and blocks for a given inode from all rmap data. */
 STATIC int
 xrep_dinode_count_rmaps(
        struct xrep_inode       *ri)
 {
        struct xfs_perag        *pag;
+       struct xfs_rtgroup      *rtg;
        xfs_agnumber_t          agno;
+       xfs_rgnumber_t          rgno;
        int                     error;
 
-       if (!xfs_has_rmapbt(ri->sc->mp) || xfs_has_realtime(ri->sc->mp))
+       if (!xfs_has_rmapbt(ri->sc->mp))
                return -EOPNOTSUPP;
 
+       for_each_rtgroup(ri->sc->mp, rgno, rtg) {
+               error = xrep_dinode_count_rtgroup_rmaps(ri, rtg);
+               if (error) {
+                       xfs_rtgroup_rele(rtg);
+                       return error;
+               }
+       }
+
        for_each_perag(ri->sc->mp, agno, pag) {
                error = xrep_dinode_count_ag_rmaps(ri, pag);
                if (error) {