summaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorDarrick J. Wong <djwong@kernel.org>2021-01-05 17:45:54 -0800
committerDarrick J. Wong <djwong@kernel.org>2021-03-25 17:08:43 -0700
commit11881b3f390e13c0e929eadb9fe6be8c4192861d (patch)
tree95ae0d64b484043b8601561e45eb3aa9f52c3c3c /fs
parent5acbb872f7d828f132ea24de00b0cb96a707f2ee (diff)
xfs: realtime rmap btree transaction reservations
Make sure that there's enough log reservation to handle mapping and unmapping realtime extents. We have to reserve enough space to handle a split in the rtrmapbt to add the record and a second split in the regular rmapbt to record the rtrmapbt split. Signed-off-by: Darrick J. Wong <djwong@kernel.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/xfs/libxfs/xfs_trans_resv.c17
-rw-r--r--fs/xfs/libxfs/xfs_trans_space.h13
2 files changed, 26 insertions, 4 deletions
diff --git a/fs/xfs/libxfs/xfs_trans_resv.c b/fs/xfs/libxfs/xfs_trans_resv.c
index 6cc901684ea6..142f718945ec 100644
--- a/fs/xfs/libxfs/xfs_trans_resv.c
+++ b/fs/xfs/libxfs/xfs_trans_resv.c
@@ -210,7 +210,9 @@ xfs_calc_inode_chunk_res(
* Per-extent log reservation for the btree changes involved in freeing or
* allocating a realtime extent. We have to be able to log as many rtbitmap
* blocks as needed to mark inuse MAXEXTLEN blocks' worth of realtime extents,
- * as well as the realtime summary block.
+ * as well as the realtime summary block (t1). Realtime rmap btree operations
+ * happen in a second transaction, so factor in a couple of rtrmapbt splits
+ * (t2).
*/
static unsigned int
xfs_rtalloc_log_count(
@@ -219,9 +221,15 @@ xfs_rtalloc_log_count(
{
unsigned int blksz = XFS_FSB_TO_B(mp, 1);
unsigned int rtbmp_bytes;
+ unsigned int t1, t2 = 0;
rtbmp_bytes = (MAXEXTLEN / mp->m_sb.sb_rextsize) / NBBY;
- return (howmany(rtbmp_bytes, blksz) + 1) * num_ops;
+ t1 = (howmany(rtbmp_bytes, blksz) + 1) * num_ops;
+
+ if (xfs_sb_version_hasrmapbt(&mp->m_sb))
+ t2 = num_ops * (2 * mp->m_rtrmap_maxlevels - 1);
+
+ return max(t1, t2);
}
/*
@@ -1119,8 +1127,9 @@ xfs_trans_resv_calc_logsize(
ASSERT(resp != M_RES(mp));
/*
- * The metadata directory tree feature drops the oversized log
- * reservations introduced by reflink and rmap.
+ * The metadata directory tree feature (as well as realtime reflink and
+ * or rmap) drop the oversized log reservations introduced by reflink
+ * and rmap.
*/
if (xfs_sb_version_hasmetadir(&mp->m_sb)) {
xfs_trans_resv_calc(mp, resp);
diff --git a/fs/xfs/libxfs/xfs_trans_space.h b/fs/xfs/libxfs/xfs_trans_space.h
index 406ad6ab0467..9234a0138cd6 100644
--- a/fs/xfs/libxfs/xfs_trans_space.h
+++ b/fs/xfs/libxfs/xfs_trans_space.h
@@ -10,6 +10,19 @@
* Components of space reservations.
*/
+/* Worst case number of realtime rmaps that can be held in a block. */
+#define XFS_MAX_CONTIG_RTRMAPS_PER_BLOCK(mp) \
+ (((mp)->m_rtrmap_mxr[0]) - ((mp)->m_rtrmap_mnr[0]))
+
+/* Adding one realtime rmap could split every level to the top of the tree. */
+#define XFS_RTRMAPADD_SPACE_RES(mp) ((mp)->m_rtrmap_maxlevels)
+
+/* Blocks we might need to add "b" realtime rmaps to a tree. */
+#define XFS_NRTRMAPADD_SPACE_RES(mp, b) \
+ ((((b) + XFS_MAX_CONTIG_RTRMAPS_PER_BLOCK(mp) - 1) / \
+ XFS_MAX_CONTIG_RTRMAPS_PER_BLOCK(mp)) * \
+ XFS_RTRMAPADD_SPACE_RES(mp))
+
/* Worst case number of rmaps that can be held in a block. */
#define XFS_MAX_CONTIG_RMAPS_PER_BLOCK(mp) \
(((mp)->m_rmap_mxr[0]) - ((mp)->m_rmap_mnr[0]))