diff --git a/xfsprogs-for-next-xfs_repair-Bump-link-count-if-longform_dir2_rebuild-.patch b/xfsprogs-for-next-xfs_repair-Bump-link-count-if-longform_dir2_rebuild-.patch new file mode 100644 index 0000000..a7092e7 --- /dev/null +++ b/xfsprogs-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/xfsprogs-for-next-xfs_repair-phase6-scan-longform-entries-before-heade.patch b/xfsprogs-for-next-xfs_repair-phase6-scan-longform-entries-before-heade.patch new file mode 100644 index 0000000..5a94bc4 --- /dev/null +++ b/xfsprogs-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 +@@ -2326,7 +2326,11 @@ + continue; + } + +- /* check v5 metadata */ ++ longform_dir2_entry_check_data(mp, ip, num_illegal, need_dot, ++ irec, ino_offset, bp, hashtab, ++ &freetab, da_bno, isblock); ++ ++ /* check v5 metadata */ + if (xfs_has_crc(mp)) { + error = check_dir3_header(mp, bp, ino); + if (error) { +@@ -2340,9 +2344,6 @@ + } + } + +- longform_dir2_entry_check_data(mp, ip, num_illegal, need_dot, +- irec, ino_offset, bp, hashtab, +- &freetab, da_bno, isblock); + if (isblock) + break; + +-- +2.49.0 diff --git a/xfsprogs.spec b/xfsprogs.spec index 5044453..8b0f908 100644 --- a/xfsprogs.spec +++ b/xfsprogs.spec @@ -1,7 +1,7 @@ Summary: Utilities for managing the XFS filesystem Name: xfsprogs Version: 6.4.0 -Release: 6%{?dist} +Release: 7%{?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 @@ -40,6 +40,8 @@ Patch13: xfsprogs-6.5.0-xfs.8-xfs-fix-bounds-check-in-xfs_defer_agfl_block.patch # v6.9.0-270-g5a43a004: This patch is taken from the `for-next` branch. Patch14: xfsprogs-for-next-xfs_repair-allow-symlinks-with-short-remote-targets.patch Patch15: xfsprogs-6.14.0-xfs_repair-handling-a-block-with-bad-crc-bad-uuid-an.patch +Patch16: xfsprogs-for-next-xfs_repair-Bump-link-count-if-longform_dir2_rebuild-.patch +Patch17: xfsprogs-for-next-xfs_repair-phase6-scan-longform-entries-before-heade.patch %description A set of commands to use the XFS filesystem, including mkfs.xfs. @@ -152,6 +154,11 @@ install -m 0644 %{SOURCE3} %{buildroot}%{mkfsdir} %{_libdir}/*.so %changelog +* Tue May 13 2025 Pavel Reichl - 6.4.0-7 +- xfs unrepairable filesystem if directory block not junked in phase 3 - more +- fixes +- Related: RHEL-54342 + * Tue May 06 2025 Pavel Reichl - 6.4.0-6 - xfs unrepairable filesystem if directory block not junked in phase 3 - Related: RHEL-54342