[PATCH 1/5] xfs: count the number of blocks in a per-ag reservation

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



In order to get the AGFL reservation, alloc_set_aside, and ag_max_usable
calculations correct in the face of per-AG reservations, we need to
understand the number of blocks that a per-AG reservation can leave free
in a worst-case scenario.

Compute the number of blocks used for a per-ag reservation by using AG
0's reservation.  Other code already assumes AG 0's reservation is as
large or larger than the other AG's.  Subsequent patches will used the
block count to construct a more accurate set of parameters.

The reservation is counted after log_mount_finish because reservations
are temporarily enabled for this operation.  An updated alloc_set_aside
and ag_max_usable need to be computed before enabling reservations at
the end of a RW mount.

Signed-off-by: Krister Johansen <kjlx@xxxxxxxxxxxxxxxxxx>
---
 fs/xfs/xfs_fsops.c | 21 +++++++++++++++++++++
 fs/xfs/xfs_fsops.h |  1 +
 fs/xfs/xfs_mount.c |  7 +++++++
 fs/xfs/xfs_mount.h |  7 +++++++
 4 files changed, 36 insertions(+)

diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c
index c211ea2b63c4..fefc20df8a2e 100644
--- a/fs/xfs/xfs_fsops.c
+++ b/fs/xfs/xfs_fsops.c
@@ -551,6 +551,27 @@ xfs_fs_reserve_ag_blocks(
 	return error;
 }
 
+/*
+ * Count the number of reserved blocks that an AG has requested.
+ */
+uint
+xfs_fs_count_reserved_ag_blocks(
+	struct xfs_mount	*mp,
+	xfs_agnumber_t		agno)
+{
+
+	struct xfs_perag	*pag;
+	uint			blocks = 0;
+
+	pag = xfs_perag_grab(mp, agno);
+	if (!pag)
+		return blocks;
+
+	blocks = pag->pag_meta_resv.ar_asked + pag->pag_rmapbt_resv.ar_asked;
+	xfs_perag_rele(pag);
+	return blocks;
+}
+
 /*
  * Free space reserved for per-AG metadata.
  */
diff --git a/fs/xfs/xfs_fsops.h b/fs/xfs/xfs_fsops.h
index 3e2f73bcf831..75f5fa1a38f4 100644
--- a/fs/xfs/xfs_fsops.h
+++ b/fs/xfs/xfs_fsops.h
@@ -12,6 +12,7 @@ int xfs_reserve_blocks(struct xfs_mount *mp, uint64_t request);
 int xfs_fs_goingdown(struct xfs_mount *mp, uint32_t inflags);
 
 int xfs_fs_reserve_ag_blocks(struct xfs_mount *mp);
+uint xfs_fs_count_reserved_ag_blocks(struct xfs_mount *mp, xfs_agnumber_t agno);
 void xfs_fs_unreserve_ag_blocks(struct xfs_mount *mp);
 
 #endif	/* __XFS_FSOPS_H__ */
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index 09eef1721ef4..d6ba67a29e3a 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -952,6 +952,13 @@ xfs_mountfs(
 		xfs_warn(mp,
 	"ENOSPC reserving per-AG metadata pool, log recovery may fail.");
 	error = xfs_log_mount_finish(mp);
+	/*
+	 * Before disabling the temporary per-ag reservation, count up the
+	 * reserved blocks in AG 0.  This will be used to determine how to
+	 * re-size the AGFL reserve and alloc_set_aside prior to enabling
+	 * reservations if the mount is RW.
+	 */
+	mp->m_ag_resblk_count = xfs_fs_count_reserved_ag_blocks(mp, 0);
 	xfs_fs_unreserve_ag_blocks(mp);
 	if (error) {
 		xfs_warn(mp, "log mount finish failed");
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h
index d0567dfbc036..800788043ca6 100644
--- a/fs/xfs/xfs_mount.h
+++ b/fs/xfs/xfs_mount.h
@@ -213,6 +213,13 @@ typedef struct xfs_mount {
 	uint64_t		m_resblks;	/* total reserved blocks */
 	uint64_t		m_resblks_avail;/* available reserved blocks */
 	uint64_t		m_resblks_save;	/* reserved blks @ remount,ro */
+
+	/*
+	 * Number of per-ag resv blocks for a single AG. Derived from AG 0
+	 * under the assumption no per-AG reservations will be larger than that
+	 * one.
+	 */
+	uint			m_ag_resblk_count;
 	struct delayed_work	m_reclaim_work;	/* background inode reclaim */
 	struct dentry		*m_debugfs;	/* debugfs parent */
 	struct xfs_kobj		m_kobj;
-- 
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