[PATCH 067/119] xfs: refcount btree requires more reserved space
From: Darrick J. Wong <hidden>
Date: 2016-06-17 01:25:08
Also in:
linux-fsdevel
Subsystem:
filesystems (vfs and infrastructure), the rest, xfs filesystem · Maintainers:
Alexander Viro, Christian Brauner, Linus Torvalds, Carlos Maiolino
The reference count btree is allocated from the free space, which means that we have to ensure that an AG can't run out of free space while performing a refcount operation. In the pathological case each AG block has its own refcntbt record, so we have to keep that much space available. v2: Calculate the maximum possible size of the rmap and refcount btrees based on minimally-full btree blocks. This increases the per-AG block reservations to handle the worst case btree size. Signed-off-by: Darrick J. Wong <redacted> --- fs/xfs/libxfs/xfs_alloc.c | 3 +++ fs/xfs/libxfs/xfs_refcount_btree.c | 23 +++++++++++++++++++++++ fs/xfs/libxfs/xfs_refcount_btree.h | 4 ++++ 3 files changed, 30 insertions(+)
diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
index be5d0df..c46db76 100644
--- a/fs/xfs/libxfs/xfs_alloc.c
+++ b/fs/xfs/libxfs/xfs_alloc.c@@ -38,6 +38,7 @@ #include "xfs_buf_item.h" #include "xfs_log.h" #include "xfs_ag_resv.h" +#include "xfs_refcount_btree.h" struct workqueue_struct *xfs_alloc_wq;
@@ -138,6 +139,8 @@ xfs_alloc_ag_max_usable(struct xfs_mount *mp) /* rmap root block + full tree split on full AG */ blocks += 1 + (2 * mp->m_ag_maxlevels) - 1; } + if (xfs_sb_version_hasreflink(&mp->m_sb)) + blocks += xfs_refcountbt_max_size(mp); return mp->m_sb.sb_agblocks - blocks; }
diff --git a/fs/xfs/libxfs/xfs_refcount_btree.c b/fs/xfs/libxfs/xfs_refcount_btree.c
index 7093c71..a944fca 100644
--- a/fs/xfs/libxfs/xfs_refcount_btree.c
+++ b/fs/xfs/libxfs/xfs_refcount_btree.c@@ -373,3 +373,26 @@ xfs_refcountbt_compute_maxlevels( mp->m_refc_maxlevels = xfs_btree_compute_maxlevels(mp, mp->m_refc_mnr, mp->m_sb.sb_agblocks); } + +/* Calculate the refcount btree size for some records. */ +xfs_extlen_t +xfs_refcountbt_calc_size( + struct xfs_mount *mp, + unsigned long long len) +{ + return xfs_btree_calc_size(mp, mp->m_refc_mnr, len); +} + +/* + * Calculate the maximum refcount btree size. + */ +xfs_extlen_t +xfs_refcountbt_max_size( + struct xfs_mount *mp) +{ + /* Bail out if we're uninitialized, which can happen in mkfs. */ + if (mp->m_refc_mxr[0] == 0) + return 0; + + return xfs_refcountbt_calc_size(mp, mp->m_sb.sb_agblocks); +}
diff --git a/fs/xfs/libxfs/xfs_refcount_btree.h b/fs/xfs/libxfs/xfs_refcount_btree.h
index 9e9ad7c..780b02f 100644
--- a/fs/xfs/libxfs/xfs_refcount_btree.h
+++ b/fs/xfs/libxfs/xfs_refcount_btree.h@@ -64,4 +64,8 @@ extern int xfs_refcountbt_maxrecs(struct xfs_mount *mp, int blocklen, bool leaf); extern void xfs_refcountbt_compute_maxlevels(struct xfs_mount *mp); +extern xfs_extlen_t xfs_refcountbt_calc_size(struct xfs_mount *mp, + unsigned long long len); +extern xfs_extlen_t xfs_refcountbt_max_size(struct xfs_mount *mp); + #endif /* __XFS_REFCOUNT_BTREE_H__ */
_______________________________________________ xfs mailing list xfs@oss.sgi.com http://oss.sgi.com/mailman/listinfo/xfs