diff mbox series

[44/47] xfs_repair: reserve per-AG space while rebuilding rt metadata

Message ID 170405015899.1815505.4353601872526248570.stgit@frogsfrogsfrogs (mailing list archive)
State New
Headers show
Series [01/47] xfs: simplify the xfs_rmap_{alloc,free}_extent calling conventions | expand

Commit Message

Darrick J. Wong Dec. 27, 2023, 1:21 p.m. UTC
From: Darrick J. Wong <djwong@kernel.org>

Realtime metadata btrees can consume quite a bit of space on a full
filesystem.  Since the metadata are just regular files, we need to
make the per-AG reservations to avoid overfilling any of the AGs while
rebuilding metadata.  This avoids the situation where a filesystem comes
straight from repair and immediately trips over not having enough space
in an AG.

Signed-off-by: Darrick J. Wong <djwong@kernel.org>
---
 include/libxfs.h |    1 +
 repair/phase6.c  |   47 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 48 insertions(+)
diff mbox series

Patch

diff --git a/include/libxfs.h b/include/libxfs.h
index 3ab93158cf7..72f38938f69 100644
--- a/include/libxfs.h
+++ b/include/libxfs.h
@@ -94,6 +94,7 @@  struct iomap;
 #include "xfs_rtbitmap.h"
 #include "xfs_rtgroup.h"
 #include "xfs_rtrmap_btree.h"
+#include "xfs_ag_resv.h"
 
 #ifndef ARRAY_SIZE
 #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
diff --git a/repair/phase6.c b/repair/phase6.c
index ab5c22ffbb0..fd862362f1d 100644
--- a/repair/phase6.c
+++ b/repair/phase6.c
@@ -3997,10 +3997,43 @@  reset_rt_metadata_inodes(
 	}
 }
 
+static int
+reserve_ag_blocks(
+	struct xfs_mount	*mp)
+{
+	struct xfs_perag	*pag;
+	xfs_agnumber_t		agno;
+	int			error = 0;
+	int			err2;
+
+	mp->m_finobt_nores = false;
+
+	for_each_perag(mp, agno, pag) {
+		err2 = -libxfs_ag_resv_init(pag, NULL);
+		if (err2 && !error)
+			error = err2;
+	}
+
+	return error;
+}
+
+static void
+unreserve_ag_blocks(
+	struct xfs_mount	*mp)
+{
+	struct xfs_perag	*pag;
+	xfs_agnumber_t		agno;
+
+	for_each_perag(mp, agno, pag)
+		libxfs_ag_resv_free(pag);
+}
+
 void
 phase6(xfs_mount_t *mp)
 {
 	ino_tree_node_t		*irec;
+	bool			reserve_perag;
+	int			error;
 	int			i;
 
 	parent_ptr_init(mp);
@@ -4040,6 +4073,17 @@  phase6(xfs_mount_t *mp)
 		do_warn(_("would reinitialize metadata root directory\n"));
 	}
 
+	reserve_perag = xfs_has_realtime(mp) && !no_modify;
+	if (reserve_perag) {
+		error = reserve_ag_blocks(mp);
+		if (error) {
+			if (error != ENOSPC)
+				do_warn(
+	_("could not reserve per-AG space to rebuild realtime metadata"));
+			reserve_perag = false;
+		}
+	}
+
 	if (need_rbmino)  {
 		if (!no_modify)  {
 			if (need_rbmino > 0)
@@ -4078,6 +4122,9 @@  _("        - resetting contents of realtime bitmap and summary inodes\n"));
 		}
 	}
 
+	if (reserve_perag)
+		unreserve_ag_blocks(mp);
+
 	reattach_metadir_quota_inodes(mp);
 
 	mark_standalone_inodes(mp);