summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2022-07-14 11:15:59 -0700
committerDarrick J. Wong <djwong@kernel.org>2022-11-09 19:08:09 -0800
commit1a5570ad47c90e819b2a631e9a18516758324e83 (patch)
treeb265faab970357015f3ac9dc89b9de62d27a6484
parent3636278c54a47099962940503533c14995b2644e (diff)
xfs: add metadata reservations for realtime refcount btree
Reserve some free blocks so that we will always have enough free blocks in the data volume to handle expansion of the realtime refcount btree. Signed-off-by: Darrick J. Wong <djwong@kernel.org>
-rw-r--r--fs/xfs/libxfs/xfs_rtrefcount_btree.c39
-rw-r--r--fs/xfs/libxfs/xfs_rtrefcount_btree.h2
-rw-r--r--fs/xfs/xfs_rtalloc.c9
3 files changed, 49 insertions, 1 deletions
diff --git a/fs/xfs/libxfs/xfs_rtrefcount_btree.c b/fs/xfs/libxfs/xfs_rtrefcount_btree.c
index 8bcb554e1e32..28f92688bf42 100644
--- a/fs/xfs/libxfs/xfs_rtrefcount_btree.c
+++ b/fs/xfs/libxfs/xfs_rtrefcount_btree.c
@@ -490,3 +490,42 @@ xfs_rtrefcountbt_create_path(
*pathp = path;
return 0;
}
+
+/* Calculate the rtrefcount btree size for some records. */
+static unsigned long long
+xfs_rtrefcountbt_calc_size(
+ struct xfs_mount *mp,
+ unsigned long long len)
+{
+ return xfs_btree_calc_size(mp->m_rtrefc_mnr, len);
+}
+
+/*
+ * Calculate the maximum refcount btree size.
+ */
+static unsigned long long
+xfs_rtrefcountbt_max_size(
+ struct xfs_mount *mp,
+ xfs_rtblock_t rtblocks)
+{
+ /* Bail out if we're uninitialized, which can happen in mkfs. */
+ if (mp->m_rtrefc_mxr[0] == 0)
+ return 0;
+
+ return xfs_rtrefcountbt_calc_size(mp, rtblocks);
+}
+
+/*
+ * Figure out how many blocks to reserve and how many are used by this btree.
+ * We need enough space to hold one record for every rt extent in the rtgroup.
+ */
+xfs_filblks_t
+xfs_rtrefcountbt_calc_reserves(
+ struct xfs_mount *mp)
+{
+ if (!xfs_has_rtreflink(mp))
+ return 0;
+
+ return xfs_rtrefcountbt_max_size(mp,
+ xfs_rtb_to_rtxt(mp, mp->m_sb.sb_rgblocks));
+}
diff --git a/fs/xfs/libxfs/xfs_rtrefcount_btree.h b/fs/xfs/libxfs/xfs_rtrefcount_btree.h
index 1f3f590c68e6..ffda0b063bcf 100644
--- a/fs/xfs/libxfs/xfs_rtrefcount_btree.h
+++ b/fs/xfs/libxfs/xfs_rtrefcount_btree.h
@@ -72,4 +72,6 @@ void xfs_rtrefcountbt_destroy_cur_cache(void);
int xfs_rtrefcountbt_create_path(struct xfs_mount *mp, xfs_rgnumber_t rgno,
struct xfs_imeta_path **pathp);
+xfs_filblks_t xfs_rtrefcountbt_calc_reserves(struct xfs_mount *mp);
+
#endif /* __XFS_RTREFCOUNT_BTREE_H__ */
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c
index c998e26f5db9..48c7cc28b7f2 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -1733,8 +1733,10 @@ xfs_rt_resv_free(
struct xfs_rtgroup *rtg;
xfs_rgnumber_t rgno;
- for_each_rtgroup(mp, rgno, rtg)
+ for_each_rtgroup(mp, rgno, rtg) {
+ xfs_imeta_resv_free_inode(rtg->rtg_refcountip);
xfs_imeta_resv_free_inode(rtg->rtg_rmapip);
+ }
}
/* Reserve space for rt metadata inodes' space expansion. */
@@ -1754,6 +1756,11 @@ xfs_rt_resv_init(
err2 = xfs_imeta_resv_init_inode(rtg->rtg_rmapip, ask);
if (err2 && !error)
error = err2;
+
+ ask = xfs_rtrefcountbt_calc_reserves(mp);
+ err2 = xfs_imeta_resv_init_inode(rtg->rtg_refcountip, ask);
+ if (err2 && !error)
+ error = err2;
}
return error;