From 617bf05890eb1c78f1d984332bfc5d2972e97a39 Mon Sep 17 00:00:00 2001 From: Pavel Reichl Date: Fri, 26 May 2023 16:23:30 +0200 Subject: [PATCH] Fix xfs corrupted when AG size is a multiple of SW This patch is taken from Linus' kernel repo as it is not in xfsprogs yet. Resolves: rhbz#2192982 Signed-off-by: Pavel Reichl --- ...tbt-numrecs-correctly-when-formattin.patch | 128 ++++++++++++++++++ xfsprogs.spec | 7 +- 2 files changed, 134 insertions(+), 1 deletion(-) create mode 100644 xfsprogs-kernel-xfs-set-bnobt-cntbt-numrecs-correctly-when-formattin.patch diff --git a/xfsprogs-kernel-xfs-set-bnobt-cntbt-numrecs-correctly-when-formattin.patch b/xfsprogs-kernel-xfs-set-bnobt-cntbt-numrecs-correctly-when-formattin.patch new file mode 100644 index 0000000..c343f6a --- /dev/null +++ b/xfsprogs-kernel-xfs-set-bnobt-cntbt-numrecs-correctly-when-formattin.patch @@ -0,0 +1,128 @@ +From 8e698ee72c4ecbbf18264568eb310875839fd601 Mon Sep 17 00:00:00 2001 +From: "Darrick J. Wong" +Date: Tue, 2 May 2023 09:14:36 +1000 +Subject: [PATCH] xfs: set bnobt/cntbt numrecs correctly when formatting new + AGs + +Through generic/300, I discovered that mkfs.xfs creates corrupt +filesystems when given these parameters: + +# mkfs.xfs -d size=512M /dev/sda -f -d su=128k,sw=4 --unsupported +Filesystems formatted with --unsupported are not supported!! +meta-data=/dev/sda isize=512 agcount=8, agsize=16352 blks + = sectsz=512 attr=2, projid32bit=1 + = crc=1 finobt=1, sparse=1, rmapbt=1 + = reflink=1 bigtime=1 inobtcount=1 nrext64=1 +data = bsize=4096 blocks=130816, imaxpct=25 + = sunit=32 swidth=128 blks +naming =version 2 bsize=4096 ascii-ci=0, ftype=1 +log =internal log bsize=4096 blocks=8192, version=2 + = sectsz=512 sunit=32 blks, lazy-count=1 +realtime =none extsz=4096 blocks=0, rtextents=0 + = rgcount=0 rgsize=0 blks +Discarding blocks...Done. +# xfs_repair -n /dev/sda +Phase 1 - find and verify superblock... + - reporting progress in intervals of 15 minutes +Phase 2 - using internal log + - zero log... + - 16:30:50: zeroing log - 16320 of 16320 blocks done + - scan filesystem freespace and inode maps... +agf_freeblks 25, counted 0 in ag 4 +sb_fdblocks 8823, counted 8798 + +The root cause of this problem is the numrecs handling in +xfs_freesp_init_recs, which is used to initialize a new AG. Prior to +calling the function, we set up the new bnobt block with numrecs == 1 +and rely on _freesp_init_recs to format that new record. If the last +record created has a blockcount of zero, then it sets numrecs = 0. + +That last bit isn't correct if the AG contains the log, the start of the +log is not immediately after the initial blocks due to stripe alignment, +and the end of the log is perfectly aligned with the end of the AG. For +this case, we actually formatted a single bnobt record to handle the +free space before the start of the (stripe aligned) log, and incremented +arec to try to format a second record. That second record turned out to +be unnecessary, so what we really want is to leave numrecs at 1. + +The numrecs handling itself is overly complicated because a different +function sets numrecs == 1. Change the bnobt creation code to start +with numrecs set to zero and only increment it after successfully +formatting a free space extent into the btree block. + +Fixes: f327a00745ff ("xfs: account for log space when formatting new AGs") +Signed-off-by: Darrick J. Wong +Reviewed-by: Dave Chinner +Signed-off-by: Dave Chinner +Signed-off-by: Pavel Reichl +--- + fs/xfs/libxfs/xfs_ag.c | 19 +++++++++---------- + 1 file changed, 9 insertions(+), 10 deletions(-) + +diff --git a/fs/xfs/libxfs/xfs_ag.c b/fs/xfs/libxfs/xfs_ag.c +index 1b078bbbf225..9b373a0c7aaf 100644 +--- a//libxfs/xfs_ag.c ++++ b//libxfs/xfs_ag.c +@@ -495,10 +495,12 @@ xfs_freesp_init_recs( + ASSERT(start >= mp->m_ag_prealloc_blocks); + if (start != mp->m_ag_prealloc_blocks) { + /* +- * Modify first record to pad stripe align of log ++ * Modify first record to pad stripe align of log and ++ * bump the record count. + */ + arec->ar_blockcount = cpu_to_be32(start - + mp->m_ag_prealloc_blocks); ++ be16_add_cpu(&block->bb_numrecs, 1); + nrec = arec + 1; + + /* +@@ -509,7 +511,6 @@ xfs_freesp_init_recs( + be32_to_cpu(arec->ar_startblock) + + be32_to_cpu(arec->ar_blockcount)); + arec = nrec; +- be16_add_cpu(&block->bb_numrecs, 1); + } + /* + * Change record start to after the internal log +@@ -518,15 +519,13 @@ xfs_freesp_init_recs( + } + + /* +- * Calculate the record block count and check for the case where +- * the log might have consumed all available space in the AG. If +- * so, reset the record count to 0 to avoid exposure of an invalid +- * record start block. ++ * Calculate the block count of this record; if it is nonzero, ++ * increment the record count. + */ + arec->ar_blockcount = cpu_to_be32(id->agsize - + be32_to_cpu(arec->ar_startblock)); +- if (!arec->ar_blockcount) +- block->bb_numrecs = 0; ++ if (arec->ar_blockcount) ++ be16_add_cpu(&block->bb_numrecs, 1); + } + + /* +@@ -538,7 +537,7 @@ xfs_bnoroot_init( + struct xfs_buf *bp, + struct aghdr_init_data *id) + { +- xfs_btree_init_block(mp, bp, XFS_BTNUM_BNO, 0, 1, id->agno); ++ xfs_btree_init_block(mp, bp, XFS_BTNUM_BNO, 0, 0, id->agno); + xfs_freesp_init_recs(mp, bp, id); + } + +@@ -548,7 +547,7 @@ xfs_cntroot_init( + struct xfs_buf *bp, + struct aghdr_init_data *id) + { +- xfs_btree_init_block(mp, bp, XFS_BTNUM_CNT, 0, 1, id->agno); ++ xfs_btree_init_block(mp, bp, XFS_BTNUM_CNT, 0, 0, id->agno); + xfs_freesp_init_recs(mp, bp, id); + } + +-- +2.40.1 + diff --git a/xfsprogs.spec b/xfsprogs.spec index c37ff3b..d37f431 100644 --- a/xfsprogs.spec +++ b/xfsprogs.spec @@ -1,7 +1,7 @@ Summary: Utilities for managing the XFS filesystem Name: xfsprogs Version: 5.19.0 -Release: 1%{?dist} +Release: 2%{?dist} License: GPL+ and LGPLv2+ URL: https://xfs.wiki.kernel.org Source0: http://kernel.org/pub/linux/utils/fs/xfs/xfsprogs/%{name}-%{version}.tar.xz @@ -34,6 +34,7 @@ Patch8: xfsprogs-5.19.0-xfs-fix-sb-write-verify-for-lazysbcount.patch Patch9: xfsprogs-5.19.0-xfs-get-rid-of-assert-from-xfs_btree_islastblock.patch Patch10: xfsprogs-5.19.0-xfs-removed-useless-condition-in-function-xfs_attr_n.patch Patch11: xfsprogs-5.19.0-xfs_repair-retain-superblock-buffer-to-avoid-write-h.patch +Patch12: xfsprogs-kernel-xfs-set-bnobt-cntbt-numrecs-correctly-when-formattin.patch %description A set of commands to use the XFS filesystem, including mkfs.xfs. @@ -145,6 +146,10 @@ install -m 0644 %{SOURCE3} %{buildroot}%{mkfsdir} %{_libdir}/*.so %changelog +* Fri May 26 2023 Pavel Reichl - 5.19.0-2 +- Fix xfs corrupted when AG size is a multiple of stripe width +- Related: rhbz#2192982 + * Tue Jan 10 2023 Pavel Reichl - 5.19.0-1 - New upstream release - Tolerate tiny (<300MB) filesystems