From 5d7d89ceceff5d841cb90803cb7435a420cb68d9 Mon Sep 17 00:00:00 2001 From: liuh Date: Fri, 29 Mar 2024 09:37:46 +0800 Subject: [PATCH] xfs: fix internal error from AGFL exhaustion (cherry picked from commit 7d6f4a7c58eb5fd88e7b9596b885166ae62d3fae) --- ...-internal-error-from-AGFL-exhaustion.patch | 107 ++++++++++++++++++ xfsprogs.spec | 6 +- 2 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 0002-xfs-fix-internal-error-from-AGFL-exhaustion.patch diff --git a/0002-xfs-fix-internal-error-from-AGFL-exhaustion.patch b/0002-xfs-fix-internal-error-from-AGFL-exhaustion.patch new file mode 100644 index 0000000..44b9b01 --- /dev/null +++ b/0002-xfs-fix-internal-error-from-AGFL-exhaustion.patch @@ -0,0 +1,107 @@ +From 8fdde9dd48edc32a2f5e5a061a12e8dad54c3c7e Mon Sep 17 00:00:00 2001 +From: Omar Sandoval +Date: Thu, 15 Feb 2024 09:27:54 +0100 +Subject: xfs: fix internal error from AGFL exhaustion + +Source kernel commit: f63a5b3769ad7659da4c0420751d78958ab97675 + +We've been seeing XFS errors like the following: + +XFS: Internal error i != 1 at line 3526 of file fs/xfs/libxfs/xfs_btree.c. Caller xfs_btree_insert+0x1ec/0x280 +... +Call Trace: +xfs_corruption_error+0x94/0xa0 +xfs_btree_insert+0x221/0x280 +xfs_alloc_fixup_trees+0x104/0x3e0 +xfs_alloc_ag_vextent_size+0x667/0x820 +xfs_alloc_fix_freelist+0x5d9/0x750 +xfs_free_extent_fix_freelist+0x65/0xa0 +__xfs_free_extent+0x57/0x180 +... + +This is the XFS_IS_CORRUPT() check in xfs_btree_insert() when +xfs_btree_insrec() fails. + +After converting this into a panic and dissecting the core dump, I found +that xfs_btree_insrec() is failing because it's trying to split a leaf +node in the cntbt when the AG free list is empty. In particular, it's +failing to get a block from the AGFL _while trying to refill the AGFL_. + +If a single operation splits every level of the bnobt and the cntbt (and +the rmapbt if it is enabled) at once, the free list will be empty. Then, +when the next operation tries to refill the free list, it allocates +space. If the allocation does not use a full extent, it will need to +insert records for the remaining space in the bnobt and cntbt. And if +those new records go in full leaves, the leaves (and potentially more +nodes up to the old root) need to be split. + +Fix it by accounting for the additional splits that may be required to +refill the free list in the calculation for the minimum free list size. + +P.S. As far as I can tell, this bug has existed for a long time -- maybe +back to xfs-history commit afdf80ae7405 ("Add XFS_AG_MAXLEVELS macros +...") in April 1994! It requires a very unlucky sequence of events, and +in fact we didn't hit it until a particular sparse mmap workload updated +from 5.12 to 5.19. But this bug existed in 5.12, so it must've been +exposed by some other change in allocation or writeback patterns. It's +also much less likely to be hit with the rmapbt enabled, since that +increases the minimum free list size and is unlikely to split at the +same time as the bnobt and cntbt. + +Reviewed-by: "Darrick J. Wong" +Reviewed-by: Dave Chinner +Signed-off-by: Omar Sandoval +Signed-off-by: Chandan Babu R +Signed-off-by: Carlos Maiolino +--- + libxfs/xfs_alloc.c | 27 ++++++++++++++++++++++++--- + 1 file changed, 24 insertions(+), 3 deletions(-) + +diff --git a/libxfs/xfs_alloc.c b/libxfs/xfs_alloc.c +index 4519a05551..7ac7c2f6cc 100644 +--- a/libxfs/xfs_alloc.c ++++ b/libxfs/xfs_alloc.c +@@ -2271,16 +2271,37 @@ xfs_alloc_min_freelist( + + ASSERT(mp->m_alloc_maxlevels > 0); + ++ /* ++ * For a btree shorter than the maximum height, the worst case is that ++ * every level gets split and a new level is added, then while inserting ++ * another entry to refill the AGFL, every level under the old root gets ++ * split again. This is: ++ * ++ * (full height split reservation) + (AGFL refill split height) ++ * = (current height + 1) + (current height - 1) ++ * = (new height) + (new height - 2) ++ * = 2 * new height - 2 ++ * ++ * For a btree of maximum height, the worst case is that every level ++ * under the root gets split, then while inserting another entry to ++ * refill the AGFL, every level under the root gets split again. This is ++ * also: ++ * ++ * 2 * (current height - 1) ++ * = 2 * (new height - 1) ++ * = 2 * new height - 2 ++ */ ++ + /* space needed by-bno freespace btree */ + min_free = min_t(unsigned int, levels[XFS_BTNUM_BNOi] + 1, +- mp->m_alloc_maxlevels); ++ mp->m_alloc_maxlevels) * 2 - 2; + /* space needed by-size freespace btree */ + min_free += min_t(unsigned int, levels[XFS_BTNUM_CNTi] + 1, +- mp->m_alloc_maxlevels); ++ mp->m_alloc_maxlevels) * 2 - 2; + /* space needed reverse mapping used space btree */ + if (xfs_has_rmapbt(mp)) + min_free += min_t(unsigned int, levels[XFS_BTNUM_RMAPi] + 1, +- mp->m_rmap_maxlevels); ++ mp->m_rmap_maxlevels) * 2 - 2; + + return min_free; + } +-- +cgit 1.2.3-korg + diff --git a/xfsprogs.spec b/xfsprogs.spec index 2dcc586..546403c 100644 --- a/xfsprogs.spec +++ b/xfsprogs.spec @@ -1,6 +1,6 @@ Name: xfsprogs Version: 6.6.0 -Release: 1 +Release: 2 Summary: Administration and debugging tools for the XFS file system License: GPL+ and LGPLv2+ URL: https://xfs.wiki.kernel.org @@ -20,6 +20,7 @@ Conflicts: xfsdump < 3.0.1 Patch0: xfsprogs-5.12.0-default-bigtime-inobtcnt-on.patch Patch1: 0001-xfsprogs-Add-sw64-architecture.patch +Patch2: 0002-xfs-fix-internal-error-from-AGFL-exhaustion.patch %description xfsprogs are the userspace utilities that manage XFS filesystems. @@ -101,6 +102,9 @@ rm -rf %{buildroot}%{_datadir}/doc/xfsprogs/ %changelog +* Fri Mar 29 2024 liuh - 6.6.0-2 +- sync patch from community + * Tue Feb 27 2024 wuguanghao - 6.6.0-1 - upgrade version to 6.6.0 -- Gitee