From: Darrick J. Wong <djwong@xxxxxxxxxx> Support the realtime superblock feature. Signed-off-by: "Darrick J. Wong" <djwong@xxxxxxxxxx> Reviewed-by: Christoph Hellwig <hch@xxxxxx> --- libxfs/libxfs_api_defs.h | 1 + repair/incore.c | 12 ++++++++++ repair/phase3.c | 4 +++ repair/rt.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++ repair/rt.h | 3 +++ repair/xfs_repair.c | 4 +++ 6 files changed, 78 insertions(+) diff --git a/libxfs/libxfs_api_defs.h b/libxfs/libxfs_api_defs.h index 84965106358d61..dbdf5d100ec8e9 100644 --- a/libxfs/libxfs_api_defs.h +++ b/libxfs/libxfs_api_defs.h @@ -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 diff --git a/repair/incore.c b/repair/incore.c index 2339d49a95773d..5b3d077f50e495 100644 --- a/repair/incore.c +++ b/repair/incore.c @@ -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(); } diff --git a/repair/phase3.c b/repair/phase3.c index ca4dbee47434c8..3a3ca22de14d26 100644 --- a/repair/phase3.c +++ b/repair/phase3.c @@ -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++) diff --git a/repair/rt.c b/repair/rt.c index 2de6830c931e86..102baa1d5d6186 100644 --- a/repair/rt.c +++ b/repair/rt.c @@ -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); +} diff --git a/repair/rt.h b/repair/rt.h index 4dfe4a921d4cdf..865d950b2bf3c4 100644 --- a/repair/rt.h +++ b/repair/rt.h @@ -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_ */ diff --git a/repair/xfs_repair.c b/repair/xfs_repair.c index d06bf659df89c1..2a8a72e7027591 100644 --- a/repair/xfs_repair.c +++ b/repair/xfs_repair.c @@ -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