[PATCH 5/5] xfs: include min freelist in m_ag_max_usable

[Date Prev] [Date Next] [Thread Prev] [Thread Next] [Date Index] [Thread Index]



If agfl_reserve blocks are conditionally withheld from consideration in
xfs_alloc_space_available, then m_ag_max_usable overstates the amount of
max available space on an empty filesystem by the amount of blocks that
mkfs placed into the AGFL on our behalf.

While this space _is_ technically free, it's not usable for a maximum
sized allocation on an empty filesystem, because the blocks must remain
in the AGFL in order for an allocation to succeed.  Without this, stripe
aligned allocations on an empty AG pick a size that they can't actually
get which leads to allocations which can't be satisfied and that
consequently come back unaligned.

Signed-off-by: Krister Johansen <kjlx@xxxxxxxxxxxxxxxxxx>
---
 fs/xfs/libxfs/xfs_alloc.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)

diff --git a/fs/xfs/libxfs/xfs_alloc.c b/fs/xfs/libxfs/xfs_alloc.c
index 4dd401d407c2..26447e6061b3 100644
--- a/fs/xfs/libxfs/xfs_alloc.c
+++ b/fs/xfs/libxfs/xfs_alloc.c
@@ -246,7 +246,9 @@ xfs_alloc_set_aside(
  *	- the AG superblock, AGF, AGI and AGFL
  *	- the AGF (bno and cnt) and AGI btree root blocks, and optionally
  *	  the AGI free inode and rmap btree root blocks.
- *	- blocks on the AGFL according to xfs_alloc_set_aside() limits
+ *	- blocks on the AGFL when the filesystem is empty
+ *	- blocks on needed to AGFL while performing dependent allocations close
+ *	  to ENOSPC as given by xfs_allocbt_agfl_reserve()
  *	- the rmapbt root block
  *
  * The AG headers are sector sized, so the amount of space they take up is
@@ -259,6 +261,13 @@ xfs_alloc_ag_max_usable(
 	unsigned int		blocks;
 
 	blocks = XFS_BB_TO_FSB(mp, XFS_FSS_TO_BB(mp, 4)); /* ag headers */
+	/*
+	 * Minimal freelist length when filesystem is completely empty.
+	 * xfs_alloc_min_freelist needs m_alloc_maxlevels so this is computed in
+	 * our second invocation of xfs_alloc_ag_max_usable
+	 */
+	if (mp->m_alloc_maxlevels > 0)
+		blocks += xfs_alloc_min_freelist(mp, NULL);
 	blocks += xfs_allocbt_agfl_reserve(mp);
 	blocks += 3;			/* AGF, AGI btree root blocks */
 	if (xfs_has_finobt(mp))
-- 
2.25.1





[Index of Archives]     [Linux Filesystems Development]     [Linux NFS]     [Linux NILFS]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux