@@ -300,6 +300,7 @@
#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
@@ -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();
}
@@ -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++)
@@ -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);
+}
@@ -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_ */
@@ -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