From ca858c6cb30e11a53a731d760283e6c9badb8db3 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Tue, 15 Oct 2024 12:44:40 -0700 Subject: [PATCH] xfs_repair: reserve per-AG space while rebuilding rt metadata 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 --- include/libxfs.h | 1 + repair/phase6.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/include/libxfs.h b/include/libxfs.h index af08f176d..bf5261687 100644 --- a/include/libxfs.h +++ b/include/libxfs.h @@ -100,6 +100,7 @@ struct iomap; #include "xfs_rtgroup.h" #include "xfs_rtbitmap.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 2143d5068..1ae626320 100644 --- a/repair/phase6.c +++ b/repair/phase6.c @@ -3546,10 +3546,41 @@ reset_quota_metadir_inodes( libxfs_irele(dp); } +static int +reserve_ag_blocks( + struct xfs_mount *mp) +{ + struct xfs_perag *pag = NULL; + int error = 0; + int err2; + + mp->m_finobt_nores = false; + + while ((pag = xfs_perag_next(mp, 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 = NULL; + + while ((pag = xfs_perag_next(mp, 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); @@ -3594,6 +3625,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 (xfs_has_rtgroups(mp)) reset_rt_metadir_inodes(mp); else @@ -3602,6 +3644,9 @@ phase6(xfs_mount_t *mp) if (xfs_has_metadir(mp) && xfs_has_quota(mp) && !no_modify) reset_quota_metadir_inodes(mp); + if (reserve_perag) + unreserve_ag_blocks(mp); + mark_standalone_inodes(mp); do_log(_(" - traversing filesystem ...\n")); -- 2.50.1