]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
xfs_repair: support realtime superblocks
authorDarrick J. Wong <djwong@kernel.org>
Thu, 21 Nov 2024 00:24:36 +0000 (16:24 -0800)
committerDarrick J. Wong <djwong@kernel.org>
Tue, 24 Dec 2024 02:01:33 +0000 (18:01 -0800)
Support the realtime superblock feature.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
libxfs/libxfs_api_defs.h
repair/incore.c
repair/phase3.c
repair/rt.c
repair/rt.h
repair/xfs_repair.c

index 84965106358d615806510098d978c5dd017c0a9a..dbdf5d100ec8e95b6f95c663d20878deb9bd5d97 100644 (file)
 
 #define xfs_rtfree_extent              libxfs_rtfree_extent
 #define xfs_rtfree_blocks              libxfs_rtfree_blocks
+#define xfs_update_rtsb                        libxfs_update_rtsb
 #define xfs_sb_from_disk               libxfs_sb_from_disk
 #define xfs_sb_quota_from_disk         libxfs_sb_quota_from_disk
 #define xfs_sb_read_secondary          libxfs_sb_read_secondary
index 2339d49a95773d8339592719df34cd27f0257a77..5b3d077f50e4956efc5eb410bd5d3c8a28ebfcb6 100644 (file)
@@ -220,6 +220,15 @@ set_rtbmap(
         (((uint64_t) state) << ((rtx % XR_BB_NUM) * XR_BB)));
 }
 
+static void
+rtsb_init(
+       struct xfs_mount        *mp)
+{
+       /* The first rtx of the realtime device contains the super */
+       if (xfs_has_rtsb(mp) && rt_bmap)
+               set_rtbmap(0, XR_E_INUSE_FS);
+}
+
 static void
 reset_rt_bmap(void)
 {
@@ -245,6 +254,8 @@ init_rt_bmap(
                        mp->m_sb.sb_rextents);
                return;
        }
+
+       rtsb_init(mp);
 }
 
 static void
@@ -332,6 +343,7 @@ reset_bmaps(
 
        if (xfs_has_rtgroups(mp)) {
                reset_rtg_bmaps(mp);
+               rtsb_init(mp);
        } else {
                reset_rt_bmap();
        }
index ca4dbee47434c8032191a25cf40cf205d4a72bf7..3a3ca22de14d269937eb73a73f1732b800c9b514 100644 (file)
@@ -17,6 +17,7 @@
 #include "progress.h"
 #include "bmap.h"
 #include "threads.h"
+#include "rt.h"
 
 static void
 process_agi_unlinked(
@@ -116,6 +117,9 @@ phase3(
 
        set_progress_msg(PROG_FMT_AGI_UNLINKED, (uint64_t) glob_agcount);
 
+       if (xfs_has_rtsb(mp) && xfs_has_realtime(mp))
+               check_rtsb(mp);
+
        /* first clear the agi unlinked AGI list */
        if (!no_modify) {
                for (i = 0; i < mp->m_sb.sb_agcount; i++)
index 2de6830c931e86bef41e6c23aa0b327830512a99..102baa1d5d6186f6d1f3f035082cb75b2a60b545 100644 (file)
@@ -562,3 +562,57 @@ free_rtgroup_inodes(void)
        for (i = 0; i < XFS_RTGI_MAX; i++)
                bitmap_free(&rtg_inodes[i]);
 }
+
+void
+check_rtsb(
+       struct xfs_mount        *mp)
+{
+       struct xfs_buf          *bp;
+       int                     error;
+
+       error = -libxfs_buf_read_uncached(mp->m_rtdev_targp, XFS_RTSB_DADDR,
+                       XFS_FSB_TO_BB(mp, 1), 0, &bp, &xfs_rtsb_buf_ops);
+       if (!error) {
+               libxfs_buf_relse(bp);
+               return;
+       }
+
+       if (no_modify) {
+               do_warn(_("would rewrite realtime superblock\n"));
+               return;
+       }
+
+       /*
+        * Rewrite the rt superblock so that an update to the primary fs
+        * superblock will not get confused by the non-matching rtsb.
+        */
+       do_warn(_("will rewrite realtime superblock\n"));
+       rewrite_rtsb(mp);
+}
+
+void
+rewrite_rtsb(
+       struct xfs_mount        *mp)
+{
+       struct xfs_buf          *rtsb_bp;
+       struct xfs_buf          *sb_bp = libxfs_getsb(mp);
+       int                     error;
+
+       if (!sb_bp)
+               do_error(
+ _("couldn't grab primary sb to update realtime sb\n"));
+
+       error = -libxfs_buf_get_uncached(mp->m_rtdev_targp,
+                       XFS_FSB_TO_BB(mp, 1), XFS_RTSB_DADDR, &rtsb_bp);
+       if (error)
+               do_error(
+ _("couldn't grab realtime superblock\n"));
+
+       rtsb_bp->b_maps[0].bm_bn = XFS_RTSB_DADDR;
+       rtsb_bp->b_ops = &xfs_rtsb_buf_ops;
+
+       libxfs_update_rtsb(rtsb_bp, sb_bp);
+       libxfs_buf_mark_dirty(rtsb_bp);
+       libxfs_buf_relse(rtsb_bp);
+       libxfs_buf_relse(sb_bp);
+}
index 4dfe4a921d4cdf08219327ff07e7cbfccb843692..865d950b2bf3c40c1822a1eca2839895b52f168f 100644 (file)
@@ -33,4 +33,7 @@ static inline bool is_rtsummary_inode(xfs_ino_t ino)
 void mark_rtgroup_inodes_bad(struct xfs_mount *mp, enum xfs_rtg_inodes type);
 bool rtgroup_inodes_were_bad(enum xfs_rtg_inodes type);
 
+void check_rtsb(struct xfs_mount *mp);
+void rewrite_rtsb(struct xfs_mount *mp);
+
 #endif /* _XFS_REPAIR_RT_H_ */
index d06bf659df89c16e9e63e22c888ff5bd42971e50..2a8a72e7027591aa1f099d347a9dd13edc9a4293 100644 (file)
@@ -1518,6 +1518,10 @@ _("Note - stripe unit (%d) and width (%d) were copied from a backup superblock.\
                                XFS_SB_FEAT_INCOMPAT_NEEDSREPAIR;
        }
 
+       /* Always rewrite the realtime superblock */
+       if (xfs_has_rtsb(mp) && xfs_has_realtime(mp))
+               rewrite_rtsb(mp);
+
        /*
         * Done. Flush all cached buffers and inodes first to ensure all
         * verifiers are run (where we discover the max metadata LSN), reformat