From: Darrick J. Wong Date: Thu, 15 Aug 2024 18:58:30 +0000 (-0700) Subject: xfs_repair: find and mark the rtrefcountbt inode X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=c1330c428acd0d3488069a1c3b8ba6643439c81c;p=users%2Fhch%2Fxfsprogs.git xfs_repair: find and mark the rtrefcountbt inode Make sure that we find the realtime refcountbt inode and mark it appropriately, just in case we find a rogue inode claiming to be an rtrefcount, or just plain garbage in the superblock field. Signed-off-by: Darrick J. Wong --- diff --git a/repair/dino_chunks.c b/repair/dino_chunks.c index fa4d065d3..3c60cedc4 100644 --- a/repair/dino_chunks.c +++ b/repair/dino_chunks.c @@ -1040,6 +1040,17 @@ next_readbuf: _("would clear rtgroup rmap inode %" PRIu64 "\n"), ino); } + } else if (is_rtrefcount_inode(ino)) { + refcount_avoid_check(mp); + if (!no_modify) { + do_warn( + _("cleared rtgroup refcount inode %" PRIu64 "\n"), + ino); + } else { + do_warn( + _("would clear rtgroup refcount inode %" PRIu64 "\n"), + ino); + } } else if (!no_modify) { do_warn(_("cleared inode %" PRIu64 "\n"), ino); diff --git a/repair/dinode.c b/repair/dinode.c index a02efcb94..3d55197c9 100644 --- a/repair/dinode.c +++ b/repair/dinode.c @@ -181,6 +181,9 @@ clear_dinode( if (is_rtrmap_inode(ino_num)) rmap_avoid_check(mp); + + if (is_rtrefcount_inode(ino_num)) + refcount_avoid_check(mp); } /* @@ -1122,6 +1125,12 @@ _("rtrefcount inode %" PRIu64 " not flagged as metadata\n"), lino); return 1; } + if (type != XR_INO_RTREFC) { + do_warn( +_("rtrefcount inode %" PRIu64 " was not found in the metadata directory tree\n"), + lino); + return 1; + } if (!is_rtrefcount_inode(lino)) { do_warn( @@ -1164,7 +1173,7 @@ _("computed size of rtrefcountbt root (%zu bytes) is greater than space in " error = process_rtrefc_reclist(mp, rp, numrecs, &priv, "rtrefcountbt root"); if (error) { - refcount_avoid_check(); + refcount_avoid_check(mp); return 1; } return 0; @@ -2122,6 +2131,9 @@ process_check_metadata_inodes( if (is_rtrmap_inode(lino)) return process_check_rt_inode(mp, dinoc, lino, type, dirty, XR_INO_RTRMAP, _("realtime rmap btree")); + if (is_rtrefcount_inode(lino)) + return process_check_rt_inode(mp, dinoc, lino, type, dirty, + XR_INO_RTREFC, _("realtime refcount btree")); return 0; } @@ -2232,6 +2244,18 @@ _("found inode %" PRIu64 " claiming to be a rtrmapbt file, but rmapbt is disable } break; + case XR_INO_RTREFC: + /* + * if we have no refcountbt, any inode claiming + * to be a real-time file is bogus + */ + if (!xfs_has_reflink(mp)) { + do_warn( +_("found inode %" PRIu64 " claiming to be a rtrefcountbt file, but reflink is disabled\n"), lino); + return 1; + } + break; + default: break; } @@ -2261,6 +2285,7 @@ _("bad attr fork offset %d in dev inode %" PRIu64 ", should be %d\n"), } break; case XFS_DINODE_FMT_RMAP: + case XFS_DINODE_FMT_REFCOUNT: if (!(xfs_has_metadir(mp) && xfs_has_parent(mp))) { do_warn( _("metadata inode %" PRIu64 " type %d cannot have attr fork\n"), @@ -3408,6 +3433,8 @@ _("bad (negative) size %" PRId64 " on inode %" PRIu64 "\n"), type = XR_INO_PQUOTA; else if (is_rtrmap_inode(lino)) type = XR_INO_RTRMAP; + else if (is_rtrefcount_inode(lino)) + type = XR_INO_RTREFC; else type = XR_INO_DATA; break; diff --git a/repair/dir2.c b/repair/dir2.c index affb556e6..d489a742a 100644 --- a/repair/dir2.c +++ b/repair/dir2.c @@ -282,6 +282,9 @@ process_sf_dir2( } else if (is_rtrmap_inode(lino)) { junkit = 1; junkreason = _("realtime rmap"); + } else if (is_rtrefcount_inode(lino)) { + junkit = 1; + junkreason = _("realtime refcount"); } else if ((irec_p = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, lino), XFS_INO_TO_AGINO(mp, lino))) != NULL) { @@ -761,6 +764,8 @@ process_dir2_data( clearreason = _("metadata directory root"); } else if (is_rtrmap_inode(ent_ino)) { clearreason = _("realtime rmap"); + } else if (is_rtrefcount_inode(ent_ino)) { + clearreason = _("realtime refcount"); } else { irec_p = find_inode_rec(mp, XFS_INO_TO_AGNO(mp, ent_ino), diff --git a/repair/incore.h b/repair/incore.h index 4add12615..57019148f 100644 --- a/repair/incore.h +++ b/repair/incore.h @@ -242,6 +242,7 @@ int count_bcnt_extents(xfs_agnumber_t); #define XR_INO_GQUOTA 13 /* group quota inode */ #define XR_INO_PQUOTA 14 /* project quota inode */ #define XR_INO_RTRMAP 15 /* realtime rmap */ +#define XR_INO_RTREFC 16 /* realtime refcount */ /* inode allocation tree */ diff --git a/repair/rmap.c b/repair/rmap.c index f3cff9767..04787c089 100644 --- a/repair/rmap.c +++ b/repair/rmap.c @@ -1691,8 +1691,11 @@ init_refcount_cursor( * Disable the refcount btree check. */ void -refcount_avoid_check(void) +refcount_avoid_check( + struct xfs_mount *mp) { + if (xfs_has_rtgroups(mp)) + mark_rtgroup_inodes_bad(mp, XFS_RTGI_REFCOUNT); refcbt_suspect = true; } diff --git a/repair/rmap.h b/repair/rmap.h index 23859bf6c..c0984d973 100644 --- a/repair/rmap.h +++ b/repair/rmap.h @@ -41,7 +41,7 @@ extern void rmap_high_key_from_rec(struct xfs_rmap_irec *rec, extern int compute_refcounts(struct xfs_mount *, xfs_agnumber_t); uint64_t refcount_record_count(struct xfs_mount *mp, xfs_agnumber_t agno); extern int init_refcount_cursor(xfs_agnumber_t, struct xfs_slab_cursor **); -extern void refcount_avoid_check(void); +extern void refcount_avoid_check(struct xfs_mount *mp); void check_refcounts(struct xfs_mount *mp, xfs_agnumber_t agno); extern void record_inode_reflink_flag(struct xfs_mount *, struct xfs_dinode *, diff --git a/repair/scan.c b/repair/scan.c index ecb43e645..c9aee32ea 100644 --- a/repair/scan.c +++ b/repair/scan.c @@ -1980,7 +1980,7 @@ _("extent (%u/%u) len %u claimed, state is %d\n"), libxfs_perag_put(pag); out: if (suspect) - refcount_avoid_check(); + refcount_avoid_check(mp); return; } @@ -2274,7 +2274,7 @@ _("%s btree block claimed (state %d), agno %d, agbno %d, suspect %d\n"), } out: if (suspect) { - refcount_avoid_check(); + refcount_avoid_check(mp); return 1; } @@ -3137,7 +3137,7 @@ validate_agf( if (levels == 0 || levels > mp->m_refc_maxlevels) { do_warn(_("bad levels %u for refcountbt root, agno %d\n"), levels, agno); - refcount_avoid_check(); + refcount_avoid_check(mp); } bno = be32_to_cpu(agf->agf_refcount_root); @@ -3155,7 +3155,7 @@ validate_agf( } else { do_warn(_("bad agbno %u for refcntbt root, agno %d\n"), bno, agno); - refcount_avoid_check(); + refcount_avoid_check(mp); } }