From 0078fa1a574f3b83c8f3b16ef824ba34971cbd21 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Wed, 10 Jul 2024 09:35:23 +0200 Subject: [PATCH] repair: factor out a ensure_rtgroup_file helper MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit The code to relink/rebuіld the rtrmap and rtrefcount inodes is almost entirely duplicated. Add a common helper for them, which will also be useful if/when we add more per-rtg inodes. Signed-off-by: Christoph Hellwig --- repair/phase6.c | 229 +++++++++++-------------------------- repair/rmap.h | 8 +- repair/rtrefcount_repair.c | 27 +++-- repair/rtrmap_repair.c | 27 +++-- 4 files changed, 101 insertions(+), 190 deletions(-) diff --git a/repair/phase6.c b/repair/phase6.c index f6a85c577..2b5a9f4d6 100644 --- a/repair/phase6.c +++ b/repair/phase6.c @@ -881,37 +881,28 @@ ensure_imeta_dirpath( return error; } -static void -ensure_rtgroup_rmapbt( +static struct xfs_inode * +ensure_rtgroup_file( struct xfs_rtgroup *rtg, - xfs_filblks_t est_fdblocks) + xfs_ino_t ino, + struct xfs_imeta_path *path, + const char *name, + int (*create)(struct xfs_imeta_update *upd)) { - struct xfs_imeta_update upd = { }; struct xfs_mount *mp = rtg->rtg_mount; - struct xfs_imeta_path *path; - xfs_ino_t ino; + struct xfs_imeta_update upd = { }; int error; - if (!xfs_has_rtrmapbt(mp)) - return; - - ino = rtgroup_rmap_ino(rtg); if (no_modify) { if (ino == NULLFSINO) - do_warn(_("would reset rtgroup %u rmap btree\n"), - rtg->rtg_rgno); - return; + do_warn(_("would reset rtgroup %u %s inode\n"), + rtg->rtg_rgno, name); + return NULL; } if (ino == NULLFSINO) - do_warn(_("resetting rtgroup %u rmap btree\n"), - rtg->rtg_rgno); - - path = xfs_rtrmapbt_create_path(mp, rtg->rtg_rgno); - if (!path) - do_error( - _("Couldn't create rtgroup %u rmap file path\n"), - rtg->rtg_rgno); + do_warn(_("resetting rtgroup %u %s inode\n"), + rtg->rtg_rgno, name); error = ensure_imeta_dirpath(mp, path); if (error) @@ -925,21 +916,21 @@ ensure_rtgroup_rmapbt( /* * We're still hanging on to our old inode pointer, so grab it * and reconnect it to the metadata directory tree. If it - * can't be grabbed, create a new rtrmap file. + * can't be grabbed, create a new file. */ error = -libxfs_trans_alloc_empty(mp, &tp); if (error) do_error( - _("Couldn't allocate transaction to iget rtgroup %u rmap inode 0x%llx, error %d\n"), - rtg->rtg_rgno, (unsigned long long)ino, - error); + _("Couldn't allocate transaction to iget rtgroup %u %s inode 0x%llx, error %d\n"), + rtg->rtg_rgno, name, (unsigned long long)ino, + error); error = -libxfs_imeta_iget(tp, ino, S_IFREG, &upd.ip); libxfs_trans_cancel(tp); if (error) { do_warn( - _("Couldn't iget rtgroup %u rmap inode 0x%llx, error %d\n"), - rtg->rtg_rgno, (unsigned long long)ino, - error); + _("Couldn't iget rtgroup %u %s inode 0x%llx, error %d\n"), + rtg->rtg_rgno, name, (unsigned long long)ino, + error); goto zap; } @@ -953,16 +944,15 @@ ensure_rtgroup_rmapbt( error = -libxfs_imeta_start_link(mp, path, upd.ip, &upd); if (error) do_error( - _("Couldn't grab resources to reconnect rtgroup %u rmapbt, error %d\n"), - rtg->rtg_rgno, error); + _("Couldn't grab resources to reconnect rtgroup %u %s, error %d\n"), + rtg->rtg_rgno, name, error); error = -libxfs_imeta_link(&upd); if (error) do_error( - _("Failed to link rtgroup %u rmapbt inode 0x%llx, error %d\n"), - rtg->rtg_rgno, - (unsigned long long)upd.ip->i_ino, - error); + _("Failed to link rtgroup %u %s inode 0x%llx, error %d\n"), + rtg->rtg_rgno, name, + (unsigned long long)upd.ip->i_ino, error); /* Reset the link count to something sane. */ set_nlink(VFS_I(upd.ip), 1); @@ -970,20 +960,20 @@ ensure_rtgroup_rmapbt( } else { zap: /* - * The rtrmap inode was bad or gone, so just make a new one - * and give our reference to the rtgroup structure. + * The inode was bad or gone, so just make a new one and give + * our reference to the rtgroup structure. */ error = -libxfs_imeta_start_create(mp, path, &upd); if (error) do_error( - _("Couldn't grab resources to recreate rtgroup %u rmapbt, error %d\n"), - rtg->rtg_rgno, error); + _("Couldn't grab resources to recreate rtgroup %u %s, error %d\n"), + rtg->rtg_rgno, name, error); - error = -libxfs_rtrmapbt_create(&upd); + error = -create(&upd); if (error) do_error( - _("Couldn't create rtgroup %u rmap inode, error %d\n"), - rtg->rtg_rgno, error); + _("Couldn't create rtgroup %u %s inode, error %d\n"), + rtg->rtg_rgno, name, error); } /* Mark the inode in use. */ @@ -993,148 +983,63 @@ zap: error = -libxfs_imeta_commit(&upd); if (error) do_error( - _("Couldn't commit new rtgroup %u rmap inode %llu, error %d\n"), - rtg->rtg_rgno, - (unsigned long long)upd.ip->i_ino, - error); - - /* Copy our incore rmap data to the ondisk rmap inode. */ - error = populate_rtgroup_rmapbt(rtg, upd.ip, est_fdblocks); - if (error) - do_error( - _("rtgroup %u rmap btree could not be rebuilt, error %d\n"), - rtg->rtg_rgno, error); + _("Couldn't commit new rtgroup %u %s inode %llu, error %d\n"), + rtg->rtg_rgno, name, (unsigned long long)upd.ip->i_ino, + error); - libxfs_imeta_free_path(path); - libxfs_irele(upd.ip); + return upd.ip; } static void -ensure_rtgroup_refcountbt( +ensure_rtgroup_rmapbt( struct xfs_rtgroup *rtg, xfs_filblks_t est_fdblocks) { - struct xfs_imeta_update upd = { }; - struct xfs_mount *mp = rtg->rtg_mount; struct xfs_imeta_path *path; - xfs_ino_t ino; - int error; + struct xfs_inode *ip; - if (!xfs_has_rtreflink(mp)) + if (!xfs_has_rtrmapbt(rtg->rtg_mount)) return; - ino = rtgroup_refcount_ino(rtg); - if (no_modify) { - if (ino == NULLFSINO) - do_warn(_("would reset rtgroup %u refcount btree\n"), - rtg->rtg_rgno); - return; - } - - if (ino == NULLFSINO) - do_warn(_("resetting rtgroup %u refcount btree\n"), - rtg->rtg_rgno); - - path = xfs_rtrefcountbt_create_path(mp, rtg->rtg_rgno); + path = xfs_rtrmapbt_create_path(rtg->rtg_mount, rtg->rtg_rgno); if (!path) do_error( - _("Couldn't create rtgroup %u refcount btree file path\n"), rtg->rtg_rgno); - - error = ensure_imeta_dirpath(mp, path); - if (error) - do_error( - _("Couldn't create rtgroup %u metadata directory, error %d\n"), - rtg->rtg_rgno, error); - - if (ino != NULLFSINO) { - struct xfs_trans *tp; - - /* - * We're still hanging on to our old inode pointer, so grab it - * and reconnect it to the metadata directory tree. If it - * can't be grabbed, create a new rtrefcount file. - */ - error = -libxfs_trans_alloc_empty(mp, &tp); - if (error) - do_error( - _("Couldn't allocate transaction to iget rtgroup %u refcountbt inode 0x%llx, error %d\n"), - rtg->rtg_rgno, (unsigned long long)ino, - error); - error = -libxfs_imeta_iget(tp, ino, S_IFREG, &upd.ip); - libxfs_trans_cancel(tp); - if (error) { - do_warn( - _("Couldn't iget rtgroup %u refcountbt inode 0x%llx, error %d\n"), - rtg->rtg_rgno, - (unsigned long long)ino, - error); - goto zap; - } - - /* - * Since we're reattaching this file to the metadata directory - * tree, try to remove all the parent pointers that might be - * attached. - */ - try_erase_parent_ptrs(upd.ip); - - error = -libxfs_imeta_start_link(mp, path, upd.ip, &upd); - if (error) - do_error( - _("Couldn't grab resources to reconnect rtgroup %u refcountbt, error %d\n"), - rtg->rtg_rgno, error); - - error = -libxfs_imeta_link(&upd); - if (error) - do_error( - _("Failed to link rtgroup %u refcountbt inode 0x%llx, error %d\n"), - rtg->rtg_rgno, - (unsigned long long)ino, - error); - - /* Reset the link count to something sane. */ - set_nlink(VFS_I(upd.ip), 1); - libxfs_trans_log_inode(upd.tp, upd.ip, XFS_ILOG_CORE); - } else { -zap: - /* - * The rtrefcount inode was bad or gone, so just make a new one - * and give our reference to the rtgroup structure. - */ - error = -libxfs_imeta_start_create(mp, path, &upd); - if (error) - do_error( - _("Couldn't grab resources to recreate rtgroup %u refcountbt, error %d\n"), - rtg->rtg_rgno, error); + _("Couldn't create rtgroup %u rmap file path\n"), + rtg->rtg_rgno); - error = -libxfs_rtrefcountbt_create(&upd); - if (error) - do_error( - _("Couldn't create rtgroup %u refcountbt inode, error %d\n"), - rtg->rtg_rgno, error); + ip = ensure_rtgroup_file(rtg, rtgroup_rmap_ino(rtg), path, "rmap", + libxfs_rtrmapbt_create); + if (ip) { + populate_rtgroup_rmapbt(rtg, ip, est_fdblocks); + libxfs_irele(ip); } + libxfs_imeta_free_path(path); +} - /* Mark the inode in use. */ - mark_ino_inuse(mp, upd.ip->i_ino, S_IFREG, upd.dp->i_ino); - mark_ino_metadata(mp, upd.ip->i_ino); +static void +ensure_rtgroup_refcountbt( + struct xfs_rtgroup *rtg, + xfs_filblks_t est_fdblocks) +{ + struct xfs_imeta_path *path; + struct xfs_inode *ip; - error = -libxfs_imeta_commit(&upd); - if (error) - do_error( - _("Couldn't commit new rtgroup %u refcountbt inode %llu, error %d\n"), - rtg->rtg_rgno, - (unsigned long long)upd.ip->i_ino, - error); + if (!xfs_has_rtreflink(rtg->rtg_mount)) + return; - /* Copy our incore refcount data to the ondisk refcount inode. */ - error = populate_rtgroup_refcountbt(rtg, upd.ip, est_fdblocks); - if (error) + path = xfs_rtrefcountbt_create_path(rtg->rtg_mount, rtg->rtg_rgno); + if (!path) do_error( - _("rtgroup %u refcount btree could not be rebuilt, error %d\n"), - rtg->rtg_rgno, error); + _("Couldn't create rtgroup %u refcount file path\n"), + rtg->rtg_rgno); + ip = ensure_rtgroup_file(rtg, rtgroup_refcount_ino(rtg), path, + "refcount", libxfs_rtrefcountbt_create); + if (ip) { + populate_rtgroup_refcountbt(rtg, ip, est_fdblocks); + libxfs_irele(ip); + } libxfs_imeta_free_path(path); - libxfs_irele(upd.ip); } /* Initialize a root directory. */ diff --git a/repair/rmap.h b/repair/rmap.h index adc3ae33a..49923500d 100644 --- a/repair/rmap.h +++ b/repair/rmap.h @@ -64,16 +64,16 @@ int rmap_get_mem_rec(struct xfs_btree_cur *rmcur, struct xfs_rmap_irec *irec); xfs_rgnumber_t rtgroup_for_rtrmap_inode(struct xfs_mount *mp, xfs_ino_t ino); bool is_rtrmap_inode(xfs_ino_t ino); xfs_ino_t rtgroup_rmap_ino(struct xfs_rtgroup *rtg); -int populate_rtgroup_rmapbt(struct xfs_rtgroup *rtg, struct xfs_inode *ip, - xfs_filblks_t fdblocks); +void populate_rtgroup_rmapbt(struct xfs_rtgroup *rtg, struct xfs_inode *ip, + xfs_filblks_t est_fdblocks); xfs_filblks_t estimate_rtrmapbt_blocks(struct xfs_rtgroup *rtg); xfs_rgnumber_t rtgroup_for_rtrefcount_inode(struct xfs_mount *mp, xfs_ino_t ino); bool is_rtrefcount_ino(xfs_ino_t ino); xfs_ino_t rtgroup_refcount_ino(struct xfs_rtgroup *rtg); -int populate_rtgroup_refcountbt(struct xfs_rtgroup *rtg, struct xfs_inode *ip, - xfs_filblks_t fdblocks); +void populate_rtgroup_refcountbt(struct xfs_rtgroup *rtg, struct xfs_inode *ip, + xfs_filblks_t est_fdblocks); xfs_filblks_t estimate_rtrefcountbt_blocks(struct xfs_rtgroup *rtg); #endif /* RMAP_H_ */ diff --git a/repair/rtrefcount_repair.c b/repair/rtrefcount_repair.c index 834bab2ec..fede5c725 100644 --- a/repair/rtrefcount_repair.c +++ b/repair/rtrefcount_repair.c @@ -219,14 +219,15 @@ err_newbt: } /* Store the realtime reference counts in the rtrefcbt. */ -int +void populate_rtgroup_refcountbt( struct xfs_rtgroup *rtg, struct xfs_inode *ip, xfs_filblks_t est_fdblocks) { + struct xfs_mount *mp = rtg->rtg_mount; struct repair_ctx sc = { - .mp = rtg->rtg_mount, + .mp = mp, .ip = ip, }; struct xrep_rtrefc rr = { @@ -234,24 +235,26 @@ populate_rtgroup_refcountbt( .rtg = rtg, .est_fdblocks = est_fdblocks, }; - struct xfs_mount *mp = rtg->rtg_mount; int error; if (!xfs_has_rtreflink(mp)) - return 0; + return; error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &sc.tp); if (error) - return error; + goto out; error = xrep_rtrefc_build_new_tree(&rr); - if (error) - goto out_cancel; - - return -libxfs_trans_commit(sc.tp); + if (error) { + libxfs_trans_cancel(sc.tp); + goto out; + } -out_cancel: - libxfs_trans_cancel(sc.tp); - return error; + error = -libxfs_trans_commit(sc.tp); +out: + if (error) + do_error( + _("rtgroup %u refcount btree could not be rebuilt, error %d\n"), + rtg->rtg_rgno, error); } diff --git a/repair/rtrmap_repair.c b/repair/rtrmap_repair.c index eab6ebe32..231213a87 100644 --- a/repair/rtrmap_repair.c +++ b/repair/rtrmap_repair.c @@ -224,14 +224,15 @@ err_newbt: } /* Store the realtime reverse-mappings in the rtrmapbt. */ -int +void populate_rtgroup_rmapbt( struct xfs_rtgroup *rtg, struct xfs_inode *ip, xfs_filblks_t est_fdblocks) { + struct xfs_mount *mp = rtg->rtg_mount; struct repair_ctx sc = { - .mp = rtg->rtg_mount, + .mp = mp, .ip = ip, }; struct xrep_rtrmap rr = { @@ -239,24 +240,26 @@ populate_rtgroup_rmapbt( .rtg = rtg, .est_fdblocks = est_fdblocks, }; - struct xfs_mount *mp = rtg->rtg_mount; int error; if (!xfs_has_rtrmapbt(mp)) - return 0; + return; error = -libxfs_trans_alloc(mp, &M_RES(mp)->tr_itruncate, 0, 0, 0, &sc.tp); if (error) - return error; + goto out; error = xrep_rtrmap_build_new_tree(&rr); - if (error) - goto out_cancel; - - return -libxfs_trans_commit(sc.tp); + if (error) { + libxfs_trans_cancel(sc.tp); + goto out; + } -out_cancel: - libxfs_trans_cancel(sc.tp); - return error; + error = -libxfs_trans_commit(sc.tp); +out: + if (error) + do_error( + _("rtgroup %u rmap btree could not be rebuilt, error %d\n"), + rtg->rtg_rgno, error); } -- 2.50.1