From 94835bc6000bb4ad41930f5d53448bc6ea4d5e7b 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 | 219 +++++++++++-------------------------- repair/rmap.h | 8 +- repair/rtrefcount_repair.c | 32 +++--- repair/rtrmap_repair.c | 32 +++--- 4 files changed, 102 insertions(+), 189 deletions(-) diff --git a/repair/phase6.c b/repair/phase6.c index f6a85c577..f0d8ded84 100644 --- a/repair/phase6.c +++ b/repair/phase6.c @@ -882,36 +882,31 @@ ensure_imeta_dirpath( } static void -ensure_rtgroup_rmapbt( +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), + void (*populate)(struct xfs_rtgroup *rtg, + struct xfs_inode *ip, + void *private), + void *private) { - 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); + do_warn(_("would reset rtgroup %u %s btree\n"), + rtg->rtg_rgno, name); return; } 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 btree\n"), + rtg->rtg_rgno, name); error = ensure_imeta_dirpath(mp, path); if (error) @@ -925,21 +920,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 +948,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 +964,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 +987,59 @@ 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); + _("Couldn't commit new rtgroup %u %s inode %llu, error %d\n"), + rtg->rtg_rgno, name, (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); + populate(rtg, upd.ip, private); - libxfs_imeta_free_path(path); libxfs_irele(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; - 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); + _("Couldn't create rtgroup %u rmap file path\n"), + rtg->rtg_rgno); - 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); + ensure_rtgroup_file(rtg, rtgroup_rmap_ino(rtg), path, "rmap", + libxfs_rtrmapbt_create, populate_rtgroup_rmapbt, + &est_fdblocks); - /* 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); + libxfs_imeta_free_path(path); +} - error = -libxfs_rtrefcountbt_create(&upd); - if (error) - do_error( - _("Couldn't create rtgroup %u refcountbt inode, error %d\n"), - rtg->rtg_rgno, error); - } +static void +ensure_rtgroup_refcountbt( + struct xfs_rtgroup *rtg, + xfs_filblks_t est_fdblocks) +{ + struct xfs_imeta_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); + if (!xfs_has_rtreflink(rtg->rtg_mount)) + return; - error = -libxfs_imeta_commit(&upd); - if (error) + path = xfs_rtrefcountbt_create_path(rtg->rtg_mount, rtg->rtg_rgno); + if (!path) 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); + _("Couldn't create rtgroup %u refcount btree file path\n"), + rtg->rtg_rgno); - /* Copy our incore refcount data to the ondisk refcount inode. */ - error = populate_rtgroup_refcountbt(rtg, upd.ip, est_fdblocks); - if (error) - do_error( - _("rtgroup %u refcount btree could not be rebuilt, error %d\n"), - rtg->rtg_rgno, error); + ensure_rtgroup_file(rtg, rtgroup_refcount_ino(rtg), path, "refcount", + libxfs_rtrefcountbt_create, populate_rtgroup_refcountbt, + &est_fdblocks); 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..17336042d 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, + void *private); 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, + void *private); 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..3feaf2fb9 100644 --- a/repair/rtrefcount_repair.c +++ b/repair/rtrefcount_repair.c @@ -219,39 +219,43 @@ 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) + void *private) { + struct xfs_mount *mp = rtg->rtg_mount; + xfs_filblks_t *est_fdblocks = private; struct repair_ctx sc = { - .mp = rtg->rtg_mount, + .mp = mp, .ip = ip, }; struct xrep_rtrefc rr = { .sc = &sc, .rtg = rtg, - .est_fdblocks = est_fdblocks, + .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..0cfa9d6c8 100644 --- a/repair/rtrmap_repair.c +++ b/repair/rtrmap_repair.c @@ -224,39 +224,43 @@ 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) + void *private) { + struct xfs_mount *mp = rtg->rtg_mount; + xfs_filblks_t *est_fdblocks = private; struct repair_ctx sc = { - .mp = rtg->rtg_mount, + .mp = mp, .ip = ip, }; struct xrep_rtrmap rr = { .sc = &sc, .rtg = rtg, - .est_fdblocks = est_fdblocks, + .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