From: Darrick J. Wong <djwong@xxxxxxxxxx> 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@xxxxxxxxxx> --- 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