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" <djwong@kernel.org>
Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
Darrick J. Wong 2024-11-20 16:20:28 -08:00
parent 6b08901a6e
commit 8491a55cfc
3 changed files with 65 additions and 1 deletions

View File

@ -540,3 +540,44 @@ 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)
{
uint32_t blocks = mp->m_groups[XG_TYPE_RTG].blocks;
if (!xfs_has_rtrmapbt(mp))
return 0;
/* Reserve 1% of the rtgroup or enough for 1 block per record. */
return max_t(xfs_filblks_t, blocks / 100,
xfs_rtrmapbt_max_size(mp, blocks));
}

View File

@ -79,4 +79,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__ */

View File

@ -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"
@ -1498,6 +1499,13 @@ void
xfs_rt_resv_free(
struct xfs_mount *mp)
{
struct xfs_rtgroup *rtg = NULL;
unsigned int i;
while ((rtg = xfs_rtgroup_next(mp, rtg))) {
for (i = 0; i < XFS_RTGI_MAX; i++)
xfs_metafile_resv_free(rtg->rtg_inodes[i]);
}
}
/* Reserve space for rt metadata inodes' space expansion. */
@ -1505,7 +1513,20 @@ int
xfs_rt_resv_init(
struct xfs_mount *mp)
{
return 0;
struct xfs_rtgroup *rtg = NULL;
xfs_filblks_t ask;
int error = 0;
while ((rtg = xfs_rtgroup_next(mp, rtg))) {
int err2;
ask = xfs_rtrmapbt_calc_reserves(mp);
err2 = xfs_metafile_resv_init(rtg_rmap(rtg), ask);
if (err2 && !error)
error = err2;
}
return error;
}
/*