summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2021-09-01 11:18:40 -0700
committerDarrick J. Wong <djwong@kernel.org>2021-10-22 16:41:08 -0700
commite22660dc7050040ef73552e0bb24ec6accffd78b (patch)
treea04655117998b129d9dfb04a609a13d6b9c60750
parent3dae68d1b4372a5f8fe84c4d39033add164662d6 (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.c37
-rw-r--r--fs/xfs/libxfs/xfs_rtrefcount_btree.h1
-rw-r--r--fs/xfs/xfs_rtalloc.c10
3 files changed, 47 insertions, 1 deletions
diff --git a/fs/xfs/libxfs/xfs_rtrefcount_btree.c b/fs/xfs/libxfs/xfs_rtrefcount_btree.c
index 52ed21c52d7b..94ea2d53cbcd 100644
--- a/fs/xfs/libxfs/xfs_rtrefcount_btree.c
+++ b/fs/xfs/libxfs/xfs_rtrefcount_btree.c
@@ -408,3 +408,40 @@ xfs_rtrefcountbt_compute_maxlevels(
/* Add one level to handle the inode root level. */
return min(d_maxlevels, r_maxlevels) + 1;
}
+
+/* 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.
+ */
+xfs_filblks_t
+xfs_rtrefcountbt_calc_reserves(
+ struct xfs_mount *mp)
+{
+ if (!xfs_has_rtreflink(mp))
+ return 0;
+
+ return xfs_rtrefcountbt_max_size(mp, mp->m_sb.sb_rblocks);
+}
diff --git a/fs/xfs/libxfs/xfs_rtrefcount_btree.h b/fs/xfs/libxfs/xfs_rtrefcount_btree.h
index e3d274c1774c..6c63c8336c54 100644
--- a/fs/xfs/libxfs/xfs_rtrefcount_btree.h
+++ b/fs/xfs/libxfs/xfs_rtrefcount_btree.h
@@ -63,5 +63,6 @@ xfs_rtrefcount_ptr_addr(
}
int __init xfs_rtrefcountbt_create_cursor_cache(void);
+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 9f68450332c7..394d6b80bcd7 100644
--- a/fs/xfs/xfs_rtalloc.c
+++ b/fs/xfs/xfs_rtalloc.c
@@ -26,6 +26,7 @@
#include "xfs_quota.h"
#include "xfs_error.h"
#include "xfs_rtrmap_btree.h"
+#include "xfs_rtrefcount_btree.h"
/*
* Read and return the summary information for a given extent size,
@@ -1381,6 +1382,7 @@ void
xfs_rt_resv_free(
struct xfs_mount *mp)
{
+ xfs_imeta_resv_free_inode(mp, mp->m_rrefcountip);
xfs_imeta_resv_free_inode(mp, mp->m_rrmapip);
}
@@ -1390,9 +1392,15 @@ xfs_rt_resv_init(
struct xfs_mount *mp)
{
xfs_filblks_t ask;
+ int error;
ask = xfs_rtrmapbt_calc_reserves(mp);
- return xfs_imeta_resv_init_inode(mp, mp->m_rrmapip, ask);
+ error = xfs_imeta_resv_init_inode(mp, mp->m_rrmapip, ask);
+ if (error)
+ return error;
+
+ ask = xfs_rtrefcountbt_calc_reserves(mp);
+ return xfs_imeta_resv_init_inode(mp, mp->m_rrefcountip, ask);
}
/*