]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
xfs_repair: find and mark the rtrmapbt inodes
authorDarrick J. Wong <djwong@kernel.org>
Fri, 9 Aug 2024 12:20:14 +0000 (14:20 +0200)
committerChristoph Hellwig <hch@lst.de>
Mon, 12 Aug 2024 11:53:50 +0000 (13:53 +0200)
Make sure that we find the realtime rmapbt inodes and mark them
appropriately, just in case we find a rogue inode claiming to be an
rtrmap, or garbage in the metadata directory tree.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
repair/dino_chunks.c
repair/dinode.c
repair/dir2.c
repair/incore.h
repair/rmap.c
repair/rmap.h
repair/rt.h
repair/scan.c

index c09dac20ac1af7c200ec5776f6a148b4e5915b70..4d6d9cb3eab67d60130ba9cb030dfb4a48ad33d0 100644 (file)
@@ -15,6 +15,9 @@
 #include "versions.h"
 #include "prefetch.h"
 #include "progress.h"
+#include "slab.h"
+#include "rmap.h"
+#include "rt.h"
 
 /*
  * validates inode block or chunk, returns # of good inodes
@@ -1003,6 +1006,17 @@ next_readbuf:
        _("would clear realtime summary inode %" PRIu64 "\n"),
                                                ino);
                                }
+                       } else if (is_rtrmap_inode(ino)) {
+                               rmap_avoid_check(mp);
+                               if (!no_modify)  {
+                                       do_warn(
+       _("cleared realtime rmap inode %" PRIu64 "\n"),
+                                               ino);
+                               } else  {
+                                       do_warn(
+       _("would clear realtime rmap inode %" PRIu64 "\n"),
+                                               ino);
+                               }
                        } else if (!no_modify)  {
                                do_warn(_("cleared inode %" PRIu64 "\n"),
                                        ino);
index 087cc8691f3b37211316bb0cee401c5182a4cdc8..4d25db3486a94404be25b71cd0b05c481484bf26 100644 (file)
@@ -154,6 +154,9 @@ clear_dinode(xfs_mount_t *mp, struct xfs_dinode *dino, xfs_ino_t ino_num)
        clear_dinode_core(mp, dino, ino_num);
        clear_dinode_unlinked(mp, dino);
 
+       if (is_rtrmap_inode(ino_num))
+               rmap_avoid_check(mp);
+
        /* and clear the forks */
        memset(XFS_DFORK_DPTR(dino), 0, XFS_LITINO(mp));
        return;
@@ -861,13 +864,22 @@ process_rtrmap(
 
        lino = XFS_AGINO_TO_INO(mp, agno, ino);
 
-       /* This rmap btree inode must be a metadata inode. */
+       /*
+        * This rmap btree inode must be a metadata inode reachable via
+        * /rtgroups/$rgno.rmap in the metadata directory tree.
+        */
        if (!(dip->di_flags2 & be64_to_cpu(XFS_DIFLAG2_METADATA))) {
                do_warn(
 _("rtrmap inode %" PRIu64 " not flagged as metadata\n"),
                        lino);
                return 1;
        }
+       if (type != XR_INO_RTRMAP) {
+               do_warn(
+_("rtrmap inode %" PRIu64 " was not found in the metadata directory tree\n"),
+                       lino);
+               return 1;
+       }
 
        rgno = rtgroup_for_rtrmap_inode(mp, lino);
        if (rgno == NULLRGNUMBER) {
@@ -913,7 +925,7 @@ _("computed size of rtrmapbt root (%zu bytes) is greater than space in "
                error = process_rtrmap_reclist(mp, rp, numrecs,
                                &priv.last_rec, NULL, "rtrmapbt root");
                if (error) {
-                       rmap_avoid_check();
+                       rmap_avoid_check(mp);
                        return 1;
                }
                return 0;
@@ -1877,6 +1889,9 @@ process_check_metadata_inodes(
        if (lino == mp->m_sb.sb_rbmino || is_rtbitmap_inode(lino))
                return process_check_rt_inode(mp, dinoc, lino, type, dirty,
                                XR_INO_RTBITMAP, _("realtime bitmap"));
+       if (is_rtrmap_inode(lino))
+               return process_check_rt_inode(mp, dinoc, lino, type, dirty,
+                               XR_INO_RTRMAP, _("realtime rmap btree"));
        return 0;
 }
 
@@ -1975,6 +1990,18 @@ _("realtime summary inode %" PRIu64 " has bad size %" PRIu64 " (should be %" PRI
                }
                break;
 
+       case XR_INO_RTRMAP:
+               /*
+                * if we have no rmapbt, any inode claiming
+                * to be a real-time file is bogus
+                */
+               if (!xfs_has_rmapbt(mp)) {
+                       do_warn(
+_("found inode %" PRIu64 " claiming to be a rtrmapbt file, but rmapbt is disabled\n"), lino);
+                       return 1;
+               }
+               break;
+
        default:
                break;
        }
@@ -2003,6 +2030,14 @@ _("bad attr fork offset %d in dev inode %" PRIu64 ", should be %d\n"),
                        return 1;
                }
                break;
+       case XFS_DINODE_FMT_RMAP:
+               if (!(xfs_has_metadir(mp) && xfs_has_parent(mp))) {
+                       do_warn(
+_("metadata inode %" PRIu64 " type %d cannot have attr fork\n"),
+                               lino, dino->di_format);
+                       return 1;
+               }
+               fallthrough;
        case XFS_DINODE_FMT_LOCAL:
        case XFS_DINODE_FMT_EXTENTS:
        case XFS_DINODE_FMT_BTREE:
@@ -3136,6 +3171,8 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"),
                        type = XR_INO_GQUOTA;
                else if (lino == mp->m_sb.sb_pquotino)
                        type = XR_INO_PQUOTA;
+               else if (is_rtrmap_inode(lino))
+                       type = XR_INO_RTRMAP;
                else
                        type = XR_INO_DATA;
                break;
@@ -3242,6 +3279,7 @@ _("Bad CoW extent size %u on inode %" PRIu64 ", "),
                case XR_INO_UQUOTA:
                case XR_INO_GQUOTA:
                case XR_INO_PQUOTA:
+               case XR_INO_RTRMAP:
                        /*
                         * This inode was recognized as being filesystem
                         * metadata, so preserve the inode and its contents for
index ca747c90175e932dd0541fe1f711d567085aba38..affb556e6eb5ecd1718533adf5bfdfd988040b86 100644 (file)
@@ -15,6 +15,8 @@
 #include "da_util.h"
 #include "prefetch.h"
 #include "progress.h"
+#include "slab.h"
+#include "rmap.h"
 #include "rt.h"
 
 /*
@@ -277,6 +279,9 @@ process_sf_dir2(
                } else if (lino == mp->m_sb.sb_metadirino)  {
                        junkit = 1;
                        junkreason = _("metadata directory root");
+               } else if (is_rtrmap_inode(lino)) {
+                       junkit = 1;
+                       junkreason = _("realtime rmap");
                } else if ((irec_p = find_inode_rec(mp,
                                        XFS_INO_TO_AGNO(mp, lino),
                                        XFS_INO_TO_AGINO(mp, lino))) != NULL) {
@@ -754,6 +759,8 @@ process_dir2_data(
                        clearreason = _("project quota");
                } else if (ent_ino == mp->m_sb.sb_metadirino)  {
                        clearreason = _("metadata directory root");
+               } else if (is_rtrmap_inode(ent_ino)) {
+                       clearreason = _("realtime rmap");
                } else {
                        irec_p = find_inode_rec(mp,
                                                XFS_INO_TO_AGNO(mp, ent_ino),
index 9982aa1138a303ca2c8cfcdbf8c7d6345ffbccae..28777bac7920dafaf57fca726a4725b6f66c7edb 100644 (file)
@@ -221,6 +221,7 @@ int         count_bcnt_extents(xfs_agnumber_t);
 #define XR_INO_UQUOTA  12              /* user quota inode */
 #define XR_INO_GQUOTA  13              /* group quota inode */
 #define XR_INO_PQUOTA  14              /* project quota inode */
+#define XR_INO_RTRMAP  15              /* realtime rmap */
 
 /* inode allocation tree */
 
index 3e7961263a2f7d74d9c4a16f7f45ccdf1049dc34..9d135f472c3a8d36d2df8569bde863854ec3e40f 100644 (file)
@@ -15,6 +15,7 @@
 #include "libfrog/bitmap.h"
 #include "libfrog/platform.h"
 #include "rcbag.h"
+#include "rt.h"
 
 #undef RMAP_DEBUG
 
@@ -169,15 +170,6 @@ nomem:
 _("Insufficient memory while allocating realtime reverse mapping btree."));
 }
 
-xfs_rgnumber_t
-rtgroup_for_rtrmap_inode(
-       struct xfs_mount        *mp,
-       xfs_ino_t               ino)
-{
-       /* This will be implemented later. */
-       return NULLRGNUMBER;
-}
-
 /*
  * Initialize per-AG reverse map data.
  */
@@ -203,6 +195,8 @@ rmaps_init(
 
        for (i = 0; i < mp->m_sb.sb_rgcount; i++)
                rmaps_init_rt(mp, i, &rg_rmaps[i]);
+
+       discover_rtgroup_inodes(mp);
 }
 
 /*
@@ -1142,11 +1136,14 @@ rmap_record_count(
 }
 
 /*
- * Disable the refcount btree check.
+ * Disable the rmap btree check.
  */
 void
-rmap_avoid_check(void)
+rmap_avoid_check(
+       struct xfs_mount        *mp)
 {
+       if (xfs_has_rtgroups(mp))
+               rtginode_avoid_check(mp, XFS_RTG_RMAP);
        rmapbt_suspect = true;
 }
 
index 23871e6d60e77485aa6d193f2b47e32fdb13b52e..b5c8b4f0bef7948e08fc2265439044de376aa061 100644 (file)
@@ -28,7 +28,7 @@ int rmap_commit_agbtree_mappings(struct xfs_mount *mp, xfs_agnumber_t agno);
 
 uint64_t rmap_record_count(struct xfs_mount *mp, bool isrt,
                xfs_agnumber_t agno);
-extern void rmap_avoid_check(void);
+extern void rmap_avoid_check(struct xfs_mount *mp);
 void rmaps_verify_btree(struct xfs_mount *mp, xfs_agnumber_t agno);
 
 extern int64_t rmap_diffkeys(struct xfs_rmap_irec *kp1,
@@ -56,6 +56,7 @@ int rmap_init_mem_cursor(struct xfs_mount *mp, struct xfs_trans *tp,
                bool isrt, xfs_agnumber_t agno, struct xfs_btree_cur **rmcurp);
 int rmap_get_mem_rec(struct xfs_btree_cur *rmcur, struct xfs_rmap_irec *irec);
 
-xfs_rgnumber_t rtgroup_for_rtrmap_inode(struct xfs_mount *mp, xfs_ino_t ino);
+void populate_rtgroup_rmapbt(struct xfs_rtgroup *rtg,
+               xfs_filblks_t est_fdblocks);
 
 #endif /* RMAP_H_ */
index ee199282f3e2f27b9eb30055b00bb5206b203e08..1617dba6b7dd624d9de4795930a61a60886b876d 100644 (file)
@@ -35,4 +35,25 @@ void rtginode_avoid_check(struct xfs_mount *mp, enum xfs_rtg_inodes type);
 void check_rtsb(struct xfs_mount *mp);
 void rewrite_rtsb(struct xfs_mount *mp);
 
+void discover_rtgroup_inodes(struct xfs_mount *mp);
+void free_rtgroup_inodes(struct xfs_mount *mp);
+
+xfs_rgnumber_t rtgroup_for_rtginode(struct xfs_mount *mp, xfs_ino_t ino,
+               enum xfs_rtg_inodes type);
+
+static inline xfs_rgnumber_t
+rtgroup_for_rtrmap_inode(struct xfs_mount *mp, xfs_ino_t ino)
+{
+       return rtgroup_for_rtginode(mp, ino, XFS_RTG_RMAP);
+}
+
+bool is_rtgroup_inode(xfs_ino_t ino, enum xfs_rtg_inodes type);
+
+static inline bool is_rtrmap_inode(xfs_ino_t ino)
+{
+       return is_rtgroup_inode(ino, XFS_RTG_RMAP);
+}
+
+void rtginode_avoid_check(struct xfs_mount *mp, enum xfs_rtg_inodes type);
+
 #endif /* _XFS_REPAIR_RT_H_ */
index 806d11dcc46f0ab121edd9a71c13ee06e0bbfeb4..60dc6354d8334c08581d4ff58ead897234395e82 100644 (file)
@@ -1346,7 +1346,7 @@ _("out of order key %u in %s btree block (%u/%u)\n"),
 
 out:
        if (suspect)
-               rmap_avoid_check();
+               rmap_avoid_check(mp);
 }
 
 int
@@ -1726,7 +1726,7 @@ _("bad %s btree ptr 0x%llx in ino %" PRIu64 "\n"),
 
 out:
        if (hdr_errors || suspect) {
-               rmap_avoid_check();
+               rmap_avoid_check(mp);
                return 1;
        }
        return 0;
@@ -2807,7 +2807,7 @@ validate_agf(
                if (levels == 0 || levels > mp->m_rmap_maxlevels) {
                        do_warn(_("bad levels %u for rmapbt root, agno %d\n"),
                                levels, agno);
-                       rmap_avoid_check();
+                       rmap_avoid_check(mp);
                }
 
                bno = be32_to_cpu(agf->agf_rmap_root);
@@ -2822,7 +2822,7 @@ validate_agf(
                } else {
                        do_warn(_("bad agbno %u for rmapbt root, agno %d\n"),
                                bno, agno);
-                       rmap_avoid_check();
+                       rmap_avoid_check(mp);
                }
        }