[PATCH 23/41] xfs_repair: refactor fixing dotdot

Darrick J. Wong
2024-12-06T23:45:39Z

From: Darrick J. Wong <djwong@kernel.org>

Pull the code that fixes a directory's dot-dot entry into a separate
helper function so that we can call it on the rootdir and (later) the
metadir.

Signed-off-by: "Darrick J. Wong" <djwong@kernel.org>
---
repair/phase6.c | 96 +++++++++++++++++++++++++++++++++----------------------
1 file changed, 57 insertions(+), 39 deletions(-)

diff --git a/repair/phase6.c b/repair/phase6.c
index 630617ef8ab8fe..0f13d996fe726a 100644
--- a/repair/phase6.c
+++ b/repair/phase6.c
@@ -2649,6 +2649,62 @@ dir_hash_add_parent_ptrs(
}
}

+/*
+ * If we have to create a .. for /, do it now *before* we delete the bogus
+ * entries, otherwise the directory could transform into a shortform dir which
+ * would probably cause the simulation to choke. Even if the illegal entries
+ * get shifted around, it's ok because the entries are structurally intact and
+ * in in hash-value order so the simulation won't get confused if it has to
+ * move them around.
+ */
+static void
+fix_dotdot(
+ struct xfs_mount *mp,
+ xfs_ino_t ino,
+ struct xfs_inode *ip,
+ xfs_ino_t rootino,
+ const char *tag,
+ int *need_dotdot)
+{
+ struct xfs_trans *tp;
+ int nres;
+ int error;
+
+ if (ino != rootino || !*need_dotdot)
+ return;
+
+ if (no_modify) {
+ do_warn(_("would recreate %s directory .. entry\n"), tag);
+ return;
+ }
+
+ ASSERT(ip->i_df.if_format != XFS_DINODE_FMT_LOCAL);
+
+ do_warn(_("recreating %s directory .. entry\n"), tag);
+
+ nres = libxfs_mkdir_space_res(mp, 2);
+ error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_mkdir, nres, 0, 0, &tp);
+ if (error)
+ res_failed(error);
+
+ libxfs_trans_ijoin(tp, ip, 0);
+
+ error = -libxfs_dir_createname(tp, ip, &xfs_name_dotdot, ip->i_ino,
+ nres);
+ if (error)
+ do_error(
+_("can't make \"..\" entry in %s inode %" PRIu64 ", createname error %d\n"),
+ tag ,ino, error);
+
+ libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
+ error = -libxfs_trans_commit(tp);
+ if (error)
+ do_error(
+_("%s inode \"..\" entry recreation failed (%d)\n"), tag, error);
+
+ *need_dotdot = 0;
+}
+
/*
* processes all reachable inodes in directories
*/
@@ -2778,45 +2834,7 @@ _("error %d fixing shortform directory %llu\n"),
dir_hash_add_parent_ptrs(ip, hashtab);
dir_hash_done(hashtab);

- /*
- * if we have to create a .. for /, do it now *before*
- * we delete the bogus entries, otherwise the directory
- * could transform into a shortform dir which would
- * probably cause the simulation to choke. Even
- * if the illegal entries get shifted around, it's ok
- * because the entries are structurally intact and in
- * in hash-value order so the simulation won't get confused
- * if it has to move them around.
- */
- if (!no_modify && need_root_dotdot && ino == mp->m_sb.sb_rootino) {
- ASSERT(ip->i_df.if_format != XFS_DINODE_FMT_LOCAL);
-
- do_warn(_("recreating root directory .. entry\n"));
-
- nres = libxfs_mkdir_space_res(mp, 2);
- error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_mkdir,
- nres, 0, 0, &tp);
- if (error)
- res_failed(error);
-
- libxfs_trans_ijoin(tp, ip, 0);
-
- error = -libxfs_dir_createname(tp, ip, &xfs_name_dotdot,
- ip->i_ino, nres);
- if (error)
- do_error(
- _("can't make \"..\" entry in root inode %" PRIu64 ", createname error %d\n"), ino, error);
-
- libxfs_trans_log_inode(tp, ip, XFS_ILOG_CORE);
- error = -libxfs_trans_commit(tp);
- if (error)
- do_error(
- _("root inode \"..\" entry recreation failed (%d)\n"), error);
-
- need_root_dotdot = 0;
- } else if (need_root_dotdot && ino == mp->m_sb.sb_rootino) {
- do_warn(_("would recreate root directory .. entry\n"));
- }
+ fix_dotdot(mp, ino, ip, mp->m_sb.sb_rootino, "root", &need_root_dotdot);

/*
* if we need to create the '.' entry, do so only if