]> www.infradead.org Git - users/hch/xfs.git/commitdiff
xfs: repair inodes that have realtime extents
authorDarrick J. Wong <djwong@kernel.org>
Mon, 23 Sep 2024 20:42:14 +0000 (13:42 -0700)
committerChristoph Hellwig <hch@lst.de>
Wed, 9 Oct 2024 13:55:47 +0000 (15:55 +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 7e15d4a6103fa5a165d65f3e3e298e7ec7bad91a..a2aa23b8c401a5230662e51c30be982fce584a66 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,17 +775,71 @@ 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;
+
+       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 = NULL;
+       struct xfs_rtgroup      *rtg = NULL;
        int                     error;
 
-       if (!xfs_has_rmapbt(ri->sc->mp) || xfs_has_realtime(ri->sc->mp))
+       if (!xfs_has_rmapbt(ri->sc->mp))
                return -EOPNOTSUPP;
 
+       while ((rtg = xfs_rtgroup_next(ri->sc->mp, rtg))) {
+               error = xrep_dinode_count_rtgroup_rmaps(ri, rtg);
+               if (error) {
+                       xfs_rtgroup_rele(rtg);
+                       return error;
+               }
+       }
+
        while ((pag = xfs_perag_next(ri->sc->mp, pag))) {
                error = xrep_dinode_count_ag_rmaps(ri, pag);
                if (error) {