]> www.infradead.org Git - users/hch/xfsprogs.git/commitdiff
xfs_repair: find and mark the rtrefcountbt inode
authorDarrick J. Wong <djwong@kernel.org>
Tue, 15 Oct 2024 19:44:47 +0000 (12:44 -0700)
committerDarrick J. Wong <djwong@kernel.org>
Fri, 1 Nov 2024 20:45:01 +0000 (13:45 -0700)
Make sure that we find the realtime refcountbt inode and mark it
appropriately, just in case we find a rogue inode claiming to
be an rtrefcount, or just plain garbage in the superblock field.

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/scan.c

index 7378ee10bbd6027d8d4a36ae1deb55c3ef61a8c5..91d5e37270e715070ea1759c7ee25d2c2719f64b 100644 (file)
@@ -1036,6 +1036,17 @@ next_readbuf:
        _("would clear rtgroup rmap inode %" PRIu64 "\n"),
                                                ino);
                                }
+                       } else if (is_rtrefcount_inode(ino)) {
+                               refcount_avoid_check(mp);
+                               if (!no_modify)  {
+                                       do_warn(
+       _("cleared rtgroup refcount inode %" PRIu64 "\n"),
+                                               ino);
+                               } else  {
+                                       do_warn(
+       _("would clear rtgroup refcount inode %" PRIu64 "\n"),
+                                               ino);
+                               }
                        } else if (!no_modify)  {
                                do_warn(_("cleared inode %" PRIu64 "\n"),
                                        ino);
index 9b8af28babe6d0f6be804faf53f79221a10efa96..9c684b8d75b7949fc9b94aff1100754939713a43 100644 (file)
@@ -181,6 +181,9 @@ clear_dinode(
 
        if (is_rtrmap_inode(ino_num))
                rmap_avoid_check(mp);
+
+       if (is_rtrefcount_inode(ino_num))
+               refcount_avoid_check(mp);
 }
 
 /*
@@ -1139,15 +1142,28 @@ _("rtrefcount inode %" PRIu64 " not flagged as metadata\n"),
                return 1;
        }
 
-       if (!is_rtrefcount_inode(lino)) {
-               do_warn(
+       /*
+        * If this rtrefcount file claims to be from an rtgroup that actually
+        * exists, check that inode discovery actually found it.  Note that
+        * we can have stray rtrefcount files from failed growfsrt operations.
+        */
+       priv.rgno = metafile_rgnumber(dip);
+       if (priv.rgno < mp->m_sb.sb_rgcount) {
+               if (type != XR_INO_RTREFC) {
+                       do_warn(
+_("rtrefcount inode %" PRIu64 " was not found in the metadata directory tree\n"),
+                               lino);
+                       return 1;
+               }
+
+               if (!is_rtrefcount_inode(lino)) {
+                       do_warn(
 _("could not associate refcount inode %" PRIu64 " with any rtgroup\n"),
-                       lino);
-               return 1;
+                               lino);
+                       return 1;
+               }
        }
 
-       priv.rgno = metafile_rgnumber(dip);
-
        dib = (struct xfs_rtrefcount_root *)XFS_DFORK_PTR(dip, XFS_DATA_FORK);
        *tot = 0;
        *nex = 0;
@@ -1179,7 +1195,7 @@ _("computed size of rtrefcountbt root (%zu bytes) is greater than space in "
                error = process_rtrefc_reclist(mp, rp, numrecs,
                                &priv, "rtrefcountbt root");
                if (error) {
-                       refcount_avoid_check();
+                       refcount_avoid_check(mp);
                        return 1;
                }
                return 0;
@@ -2137,6 +2153,9 @@ process_check_metadata_inodes(
        if (is_rtrmap_inode(lino))
                return process_check_rt_inode(mp, dinoc, lino, type, dirty,
                                XR_INO_RTRMAP, _("realtime rmap btree"));
+       if (is_rtrefcount_inode(lino))
+               return process_check_rt_inode(mp, dinoc, lino, type, dirty,
+                               XR_INO_RTREFC, _("realtime refcount btree"));
        return 0;
 }
 
@@ -2247,6 +2266,18 @@ _("found inode %" PRIu64 " claiming to be a rtrmapbt file, but rmapbt is disable
                }
                break;
 
+       case XR_INO_RTREFC:
+               /*
+                * if we have no refcountbt, any inode claiming
+                * to be a real-time file is bogus
+                */
+               if (!xfs_has_reflink(mp)) {
+                       do_warn(
+_("found inode %" PRIu64 " claiming to be a rtrefcountbt file, but reflink is disabled\n"), lino);
+                       return 1;
+               }
+               break;
+
        default:
                break;
        }
@@ -2276,6 +2307,7 @@ _("bad attr fork offset %d in dev inode %" PRIu64 ", should be %d\n"),
                }
                break;
        case XFS_DINODE_FMT_RMAP:
+       case XFS_DINODE_FMT_REFCOUNT:
                if (!(xfs_has_metadir(mp) && xfs_has_parent(mp))) {
                        do_warn(
 _("metadata inode %" PRIu64 " type %d cannot have attr fork\n"),
@@ -3420,6 +3452,8 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"),
                        type = XR_INO_PQUOTA;
                else if (is_rtrmap_inode(lino))
                        type = XR_INO_RTRMAP;
+               else if (is_rtrefcount_inode(lino))
+                       type = XR_INO_RTREFC;
                else
                        type = XR_INO_DATA;
                break;
index af00b2d8d6c852b3b985cb77199188cf71430b65..a80160afaea5cf05cb6c70ed78a77a06e02528a3 100644 (file)
@@ -282,6 +282,9 @@ process_sf_dir2(
                } else if (is_rtrmap_inode(lino)) {
                        junkit = 1;
                        junkreason = _("realtime rmap");
+               } else if (is_rtrefcount_inode(lino)) {
+                       junkit = 1;
+                       junkreason = _("realtime refcount");
                } else if ((irec_p = find_inode_rec(mp,
                                        XFS_INO_TO_AGNO(mp, lino),
                                        XFS_INO_TO_AGINO(mp, lino))) != NULL) {
@@ -761,6 +764,8 @@ process_dir2_data(
                        clearreason = _("metadata directory root");
                } else if (is_rtrmap_inode(ent_ino)) {
                        clearreason = _("realtime rmap");
+               } else if (is_rtrefcount_inode(ent_ino)) {
+                       clearreason = _("realtime refcount");
                } else {
                        irec_p = find_inode_rec(mp,
                                                XFS_INO_TO_AGNO(mp, ent_ino),
index 4add12615e0a04cefc2882d6d03dca989bd4d99b..57019148f588c3fc14c4c7fd0f78fb100c52cf26 100644 (file)
@@ -242,6 +242,7 @@ int         count_bcnt_extents(xfs_agnumber_t);
 #define XR_INO_GQUOTA  13              /* group quota inode */
 #define XR_INO_PQUOTA  14              /* project quota inode */
 #define XR_INO_RTRMAP  15              /* realtime rmap */
+#define XR_INO_RTREFC  16              /* realtime refcount */
 
 /* inode allocation tree */
 
index 77020c1515012bf0ddf93b966be6ead72745d1a1..8de721146b7ccece47c3df3c7f701ef8de48cf0e 100644 (file)
@@ -1691,8 +1691,11 @@ init_refcount_cursor(
  * Disable the refcount btree check.
  */
 void
-refcount_avoid_check(void)
+refcount_avoid_check(
+       struct xfs_mount        *mp)
 {
+       if (xfs_has_rtgroups(mp))
+               mark_rtgroup_inodes_bad(mp, XFS_RTGI_REFCOUNT);
        refcbt_suspect = true;
 }
 
index 23859bf6c2ad42a6e89ba1092993900dd2c2c03b..c0984d97322861b613c8501a5498aaea151907bb 100644 (file)
@@ -41,7 +41,7 @@ extern void rmap_high_key_from_rec(struct xfs_rmap_irec *rec,
 extern int compute_refcounts(struct xfs_mount *, xfs_agnumber_t);
 uint64_t refcount_record_count(struct xfs_mount *mp, xfs_agnumber_t agno);
 extern int init_refcount_cursor(xfs_agnumber_t, struct xfs_slab_cursor **);
-extern void refcount_avoid_check(void);
+extern void refcount_avoid_check(struct xfs_mount *mp);
 void check_refcounts(struct xfs_mount *mp, xfs_agnumber_t agno);
 
 extern void record_inode_reflink_flag(struct xfs_mount *, struct xfs_dinode *,
index 21fa9018800c771ccfbf7341ada9ea648db86052..86565ebb9f2faf24c15e74826d1f65b98b40dd0a 100644 (file)
@@ -1980,7 +1980,7 @@ _("extent (%u/%u) len %u claimed, state is %d\n"),
        libxfs_perag_put(pag);
 out:
        if (suspect)
-               refcount_avoid_check();
+               refcount_avoid_check(mp);
        return;
 }
 
@@ -2285,7 +2285,7 @@ _("%s btree block claimed (state %d), agno %d, agbno %d, suspect %d\n"),
        }
 out:
        if (suspect) {
-               refcount_avoid_check();
+               refcount_avoid_check(mp);
                return 1;
        }
 
@@ -3148,7 +3148,7 @@ validate_agf(
                if (levels == 0 || levels > mp->m_refc_maxlevels) {
                        do_warn(_("bad levels %u for refcountbt root, agno %d\n"),
                                levels, agno);
-                       refcount_avoid_check();
+                       refcount_avoid_check(mp);
                }
 
                bno = be32_to_cpu(agf->agf_refcount_root);
@@ -3166,7 +3166,7 @@ validate_agf(
                } else {
                        do_warn(_("bad agbno %u for refcntbt root, agno %d\n"),
                                bno, agno);
-                       refcount_avoid_check();
+                       refcount_avoid_check(mp);
                }
        }