From: Darrick J. Wong <djwong@xxxxxxxxxx> During the 6.7 merge window, Linus noticed that the realtime allocator was doing some sketchy things trying to encode a u64 sequence counter into the rtbitmap file's atime. The sketchy casting of a struct pointer to a u64 pointer has subtly broken several times over the past decade as the codebase has transitioned to using the VFS i_atime field and that field has changed in size and layout over time. Since the goal of the rtpick code is to _suggest_ a starting place for new rt file allocations, the repeated breakage has not resulted in inconsistent metadata. IOWs, it's a hint. For rtgroups, we don't need this complex code to cut the rtextents space into fractions. Add an rtgroup rotor and use that for rtpick, similar to AG rotoring on the data device. The new rotor does not persist, which reduces the logging overhead slightly. Link: https://lore.kernel.org/linux-xfs/CAHk-=wj3oM3d-Hw2vvxys3KCZ9De+gBN7Gxr2jf96OTisL9udw@xxxxxxxxxxxxxx/ Signed-off-by: Darrick J. Wong <djwong@xxxxxxxxxx> --- fs/xfs/libxfs/xfs_rtbitmap.c | 12 ++++++++---- fs/xfs/xfs_mount.h | 1 + fs/xfs/xfs_rtalloc.c | 11 +++++++++++ 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/fs/xfs/libxfs/xfs_rtbitmap.c b/fs/xfs/libxfs/xfs_rtbitmap.c index 3530524b3fc2b..0ef14157e8157 100644 --- a/fs/xfs/libxfs/xfs_rtbitmap.c +++ b/fs/xfs/libxfs/xfs_rtbitmap.c @@ -1064,10 +1064,14 @@ xfs_rtfree_extent( if (!(mp->m_rbmip->i_diflags & XFS_DIFLAG_NEWRTBM)) mp->m_rbmip->i_diflags |= XFS_DIFLAG_NEWRTBM; - atime = inode_get_atime(VFS_I(mp->m_rbmip)); - atime.tv_sec = 0; - inode_set_atime_to_ts(VFS_I(mp->m_rbmip), atime); - xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE); + if (xfs_has_rtgroups(mp)) { + mp->m_rtgrotor = 0; + } else { + atime = inode_get_atime(VFS_I(mp->m_rbmip)); + atime.tv_sec = 0; + inode_set_atime_to_ts(VFS_I(mp->m_rbmip), atime); + xfs_trans_log_inode(tp, mp->m_rbmip, XFS_ILOG_CORE); + } } error = 0; out: diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index 14094b29ab6fe..a086b96b0a513 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h @@ -224,6 +224,7 @@ typedef struct xfs_mount { #ifdef CONFIG_XFS_ONLINE_SCRUB_STATS struct xchk_stats *m_scrub_stats; #endif + xfs_rgnumber_t m_rtgrotor; /* last rtgroup rtpicked */ xfs_agnumber_t m_agfrotor; /* last ag where space found */ atomic_t m_agirotor; /* last ag dir inode alloced */ diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index ff08c1d997fdb..6479bb04657ec 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -1688,6 +1688,17 @@ xfs_rtpick_extent( ASSERT(xfs_isilocked(mp->m_rbmip, XFS_ILOCK_EXCL)); + if (xfs_has_rtgroups(mp)) { + xfs_rtblock_t rtbno; + + /* Pick the first usable rtx of the group. */ + rtbno = xfs_rgbno_to_rtb(mp, mp->m_rtgrotor, 0); + *pick = xfs_rtb_to_rtx(mp, rtbno) + 1; + + mp->m_rtgrotor = (mp->m_rtgrotor + 1) % mp->m_sb.sb_rgcount; + return 0; + } + ts = inode_get_atime(VFS_I(mp->m_rbmip)); if (!(mp->m_rbmip->i_diflags & XFS_DIFLAG_NEWRTBM)) { mp->m_rbmip->i_diflags |= XFS_DIFLAG_NEWRTBM;