diff --git a/for-next-xfs_repair-Bump-link-count-if-longform_dir2_rebuild-.patch b/for-next-xfs_repair-Bump-link-count-if-longform_dir2_rebuild-.patch new file mode 100644 index 0000000..a7092e7 --- /dev/null +++ b/for-next-xfs_repair-Bump-link-count-if-longform_dir2_rebuild-.patch @@ -0,0 +1,63 @@ +From 454fab69c484c24d8fb76ac3676553a54af381f7 Mon Sep 17 00:00:00 2001 +From: Eric Sandeen +Date: Tue, 15 Apr 2025 13:09:23 -0500 +Subject: [PATCH] xfs_repair: Bump link count if longform_dir2_rebuild yields + shortform dir + +If longform_dir2_rebuild() has so few entries in *hashtab that it results +in a short form directory, bump the link count manually as shortform +directories have no explicit "." entry. + +Without this, repair will end with i.e.: + +resetting inode 131 nlinks from 2 to 1 + +in this case, because it thinks this directory inode only has 1 link +discovered, and then a 2nd repair will fix it: + +resetting inode 131 nlinks from 1 to 2 + +because shortform_dir2_entry_check() explicitly adds the extra ref when +the (newly-created)shortform directory is checked: + + /* + * no '.' entry in shortform dirs, just bump up ref count by 1 + * '..' was already (or will be) accounted for and checked when + * the directory is reached or will be taken care of when the + * directory is moved to orphanage. + */ + add_inode_ref(current_irec, current_ino_offset); + +Avoid this by adding the extra ref if we convert from longform to +shortform. + +Signed-off-by: Eric Sandeen +[aalbersh drop SoB with user.mail as name] +Reviewed-by: Bill O'Donnell +Reviewed-by: Darrick J. Wong +Signed-off-by: Pavel Reichl +--- + repair/phase6.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/repair/phase6.c b/repair/phase6.c +index dbc090a5..8804278a 100644 +--- a/repair/phase6.c ++++ b/repair/phase6.c +@@ -1392,6 +1392,13 @@ _("name create failed in ino %" PRIu64 " (%d)\n"), ino, error); + _("name create failed (%d) during rebuild\n"), error); + } + ++ /* ++ * If we added too few entries to retain longform, add the extra ++ * ref for . as this is now a shortform directory. ++ */ ++ if (ip->i_df.if_format == XFS_DINODE_FMT_LOCAL) ++ add_inode_ref(irec, ino_offset); ++ + return; + + out_bmap_cancel: +-- +2.49.0 + diff --git a/for-next-xfs_repair-phase6-scan-longform-entries-before-heade.patch b/for-next-xfs_repair-phase6-scan-longform-entries-before-heade.patch new file mode 100644 index 0000000..959134d --- /dev/null +++ b/for-next-xfs_repair-phase6-scan-longform-entries-before-heade.patch @@ -0,0 +1,58 @@ +From 140fd5b163577bd99e07adcdea7e08a99bccbccd Mon Sep 17 00:00:00 2001 +From: Bill O'Donnell +Date: Tue, 15 Apr 2025 13:48:49 -0500 +Subject: [PATCH] xfs_repair: phase6: scan longform entries before header check + +In longform_dir2_entry_check, if check_dir3_header() fails for v5 +metadata, we immediately go to out_fix: and try to rebuild the +directory via longform_dir2_rebuild. But because we haven't yet +called longform_dir2_entry_check_data, the *hashtab used to rebuild +the directory is empty, which results in all existing entries +getting moved to lost+found, and an empty rebuilt directory. On top +of that, the empty directory is now short form, so its nlinks come +out wrong and this requires another repair run to fix. + +Scan the entries before checking the header, so that we have a +decent chance of properly rebuilding the dir if the header is +corrupt, rather than orphaning all the entries and moving them to +lost+found. + +Suggested-by: Eric Sandeen +Signed-off-by: Bill O'Donnell +[aalbersh updated changelog as suggested by Eric Sandeen] +Reviewed-by: Eric Sandeen +Reviewed-by: Darrick J. Wong +Signed-off-by: Pavel Reichl +--- + repair/phase6.c | 8 +++++--- + 1 file changed, 5 insertions(+), 3 deletions(-) + +diff --git a/repair/phase6.c b/repair/phase6.c +index 8804278a..a67cc0ab 100644 +--- a/repair/phase6.c ++++ b/repair/phase6.c +@@ -2431,6 +2431,11 @@ longform_dir2_entry_check( + continue; + } + ++ /* salvage any dirents that look ok */ ++ longform_dir2_entry_check_data(mp, ip, num_illegal, need_dot, ++ irec, ino_offset, bp, hashtab, ++ &freetab, da_bno, fmt == XFS_DIR2_FMT_BLOCK); ++ + /* check v5 metadata */ + if (xfs_has_crc(mp)) { + error = check_dir3_header(mp, bp, ino); +@@ -2445,9 +2450,6 @@ longform_dir2_entry_check( + } + } + +- longform_dir2_entry_check_data(mp, ip, num_illegal, need_dot, +- irec, ino_offset, bp, hashtab, +- &freetab, da_bno, fmt == XFS_DIR2_FMT_BLOCK); + if (fmt == XFS_DIR2_FMT_BLOCK) + break; + +-- +2.49.0 + diff --git a/v6.14-xfs_repair-handling-a-block-with-bad-crc-bad-uuid-an.patch b/v6.14-xfs_repair-handling-a-block-with-bad-crc-bad-uuid-an.patch new file mode 100644 index 0000000..fe01b7e --- /dev/null +++ b/v6.14-xfs_repair-handling-a-block-with-bad-crc-bad-uuid-an.patch @@ -0,0 +1,55 @@ +From 8cd85addd72f1f6e569bd286f6a44dfce90355f1 Mon Sep 17 00:00:00 2001 +From: Bill O'Donnell +Date: Fri, 21 Mar 2025 17:05:35 -0500 +Subject: [PATCH] xfs_repair: handling a block with bad crc, bad uuid, and bad + magic number needs fixing + +In certain cases, if a block is so messed up that crc, uuid and magic +number are all bad, we need to not only detect in phase3 but fix it +properly in phase6. In the current code, the mechanism doesn't work +in that it only pays attention to one of the parameters. + +Note: in this case, the nlink inode link count drops to 1, but +re-running xfs_repair fixes it back to 2. This is a side effect that +should probably be handled in update_inode_nlinks() with separate patch. +Regardless, running xfs_repair twice, with this patch applied +fixes the issue. Recognize that this patch is a fix for xfs v5. + +Signed-off-by: Bill O'Donnell +Reviewed-by: "Darrick J. Wong" + +v2: remove superfluous needmagic logic +v3: clarify the description +Reviewed-by: Christoph Hellwig +Reviewed-by: Darrick J. Wong +Signed-off-by: Pavel Reichl +--- + repair/phase6.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/repair/phase6.c b/repair/phase6.c +index 44b9bfc3..dbc090a5 100644 +--- a/repair/phase6.c ++++ b/repair/phase6.c +@@ -2378,7 +2378,6 @@ longform_dir2_entry_check( + da_bno = (xfs_dablk_t)next_da_bno) { + const struct xfs_buf_ops *ops; + int error; +- struct xfs_dir2_data_hdr *d; + + next_da_bno = da_bno + mp->m_dir_geo->fsbcount - 1; + if (bmap_next_offset(ip, &next_da_bno)) { +@@ -2426,9 +2425,7 @@ longform_dir2_entry_check( + } + + /* check v5 metadata */ +- d = bp->b_addr; +- if (be32_to_cpu(d->magic) == XFS_DIR3_BLOCK_MAGIC || +- be32_to_cpu(d->magic) == XFS_DIR3_DATA_MAGIC) { ++ if (xfs_has_crc(mp)) { + error = check_dir3_header(mp, bp, ino); + if (error) { + fixit++; +-- +2.49.0 + diff --git a/xfsprogs.spec b/xfsprogs.spec index 24c7b0d..42dbf5b 100644 --- a/xfsprogs.spec +++ b/xfsprogs.spec @@ -1,7 +1,7 @@ Summary: Utilities for managing the XFS filesystem Name: xfsprogs Version: 6.11.0 -Release: 1%{?dist} +Release: 2%{?dist} License: GPL-1.0-or-later AND LGPL-2.1-or-later URL: https://xfs.wiki.kernel.org Source0: http://kernel.org/pub/linux/utils/fs/xfs/xfsprogs/%{name}-%{version}.tar.xz @@ -30,6 +30,10 @@ Provides: /usr/sbin/fsck.xfs Provides: /usr/sbin/mkfs.xfs %endif +Patch0: v6.14-xfs_repair-handling-a-block-with-bad-crc-bad-uuid-an.patch +Patch1: for-next-xfs_repair-Bump-link-count-if-longform_dir2_rebuild-.patch +Patch2: for-next-xfs_repair-phase6-scan-longform-entries-before-heade.patch + %description A set of commands to use the XFS filesystem, including mkfs.xfs. @@ -140,6 +144,10 @@ rm -rf $RPM_BUILD_ROOT/%{_datadir}/doc/xfsprogs/ %{_libdir}/*.so %changelog +* Tue May 20 2025 Pavel Reichl - 6.11.0-2 +- xfs unrepairable filesystem if directory block not junked in phase 3 +- Related: RHEL-89682 + * Sat Nov 16 2024 Pavel Reichl - 6.11.0-1 - Update to the latest upstream version - Related: rhbz#2319902