From 96e6d68712d5d66f3980fc5e6f889c4428bf8c38 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Tue, 28 May 2024 21:11:52 -0700 Subject: [PATCH] xfs: add metadata reservations for realtime rmap btrees Reserve some free blocks so that we will always have enough free blocks in the data volume to handle expansion of the realtime rmap btree. Signed-off-by: Darrick J. Wong --- fs/xfs/libxfs/xfs_metafile.c | 6 ++++- fs/xfs/libxfs/xfs_rtrmap_btree.c | 39 ++++++++++++++++++++++++++++++++ fs/xfs/libxfs/xfs_rtrmap_btree.h | 2 ++ fs/xfs/xfs_rtalloc.c | 26 ++++++++++++++++++++- 4 files changed, 71 insertions(+), 2 deletions(-) diff --git a/fs/xfs/libxfs/xfs_metafile.c b/fs/xfs/libxfs/xfs_metafile.c index b0394435265e..e6b83e2af8da 100644 --- a/fs/xfs/libxfs/xfs_metafile.c +++ b/fs/xfs/libxfs/xfs_metafile.c @@ -203,7 +203,11 @@ void xfs_metafile_resv_free( struct xfs_inode *ip) { - if (!ip) + /* + * We can end up here for the rt bitmap/summary inodes that don't have + * reservations. Just exist early in that case. + */ + if (!ip || !ip->i_delayed_blks) return; ASSERT(xfs_is_metadir_inode(ip)); diff --git a/fs/xfs/libxfs/xfs_rtrmap_btree.c b/fs/xfs/libxfs/xfs_rtrmap_btree.c index 39d735cc1fd4..a0d246bd9ff2 100644 --- a/fs/xfs/libxfs/xfs_rtrmap_btree.c +++ b/fs/xfs/libxfs/xfs_rtrmap_btree.c @@ -546,3 +546,42 @@ xfs_rtrmapbt_compute_maxlevels( /* Add one level to handle the inode root level. */ mp->m_rtrmap_maxlevels = min(d_maxlevels, r_maxlevels) + 1; } + +/* Calculate the rtrmap btree size for some records. */ +static unsigned long long +xfs_rtrmapbt_calc_size( + struct xfs_mount *mp, + unsigned long long len) +{ + return xfs_btree_calc_size(mp->m_rtrmap_mnr, len); +} + +/* + * Calculate the maximum rmap btree size. + */ +static unsigned long long +xfs_rtrmapbt_max_size( + struct xfs_mount *mp, + xfs_rtblock_t rtblocks) +{ + /* Bail out if we're uninitialized, which can happen in mkfs. */ + if (mp->m_rtrmap_mxr[0] == 0) + return 0; + + return xfs_rtrmapbt_calc_size(mp, rtblocks); +} + +/* + * Figure out how many blocks to reserve and how many are used by this btree. + */ +xfs_filblks_t +xfs_rtrmapbt_calc_reserves( + struct xfs_mount *mp) +{ + if (!xfs_has_rtrmapbt(mp)) + return 0; + + /* 1/64th (~1.5%) of the space, and enough for 1 record per block. */ + return max_t(xfs_filblks_t, mp->m_rgblocks >> 6, + xfs_rtrmapbt_max_size(mp, mp->m_rgblocks)); +} diff --git a/fs/xfs/libxfs/xfs_rtrmap_btree.h b/fs/xfs/libxfs/xfs_rtrmap_btree.h index 0f7326797192..bb0ebc07f47e 100644 --- a/fs/xfs/libxfs/xfs_rtrmap_btree.h +++ b/fs/xfs/libxfs/xfs_rtrmap_btree.h @@ -80,4 +80,6 @@ unsigned int xfs_rtrmapbt_maxlevels_ondisk(void); int __init xfs_rtrmapbt_init_cur_cache(void); void xfs_rtrmapbt_destroy_cur_cache(void); +xfs_filblks_t xfs_rtrmapbt_calc_reserves(struct xfs_mount *mp); + #endif /* __XFS_RTRMAP_BTREE_H__ */ diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index e22f94b42da6..a1a5c8245d42 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c @@ -22,6 +22,7 @@ #include "xfs_rtalloc.h" #include "xfs_sb.h" #include "xfs_rtbitmap.h" +#include "xfs_rtrmap_btree.h" #include "xfs_quota.h" #include "xfs_log_priv.h" #include "xfs_health.h" @@ -1430,6 +1431,14 @@ void xfs_rt_resv_free( struct xfs_mount *mp) { + struct xfs_rtgroup *rtg; + xfs_rgnumber_t rgno; + unsigned int i; + + for_each_rtgroup(mp, rgno, rtg) { + for (i = 0; i < XFS_RTG_MAX; i++) + xfs_metafile_resv_free(rtg->rtg_inodes[i]); + } } /* Reserve space for rt metadata inodes' space expansion. */ @@ -1437,7 +1446,22 @@ int xfs_rt_resv_init( struct xfs_mount *mp) { - return 0; + struct xfs_rtgroup *rtg; + xfs_filblks_t ask; + xfs_rgnumber_t rgno; + int error = 0; + + for_each_rtgroup(mp, rgno, rtg) { + int err2; + + ask = xfs_rtrmapbt_calc_reserves(mp); + err2 = xfs_metafile_resv_init(rtg->rtg_inodes[XFS_RTG_RMAP], + ask); + if (err2 && !error) + error = err2; + } + + return error; } /* -- 2.50.1