From: Christoph Hellwig Date: Tue, 12 Nov 2024 08:31:04 +0000 (+0100) Subject: xfs: use a single inode fork format for metadata btree inodes X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=refs%2Fheads%2Fxfs-meta-btree;p=users%2Fhch%2Fxfs.git xfs: use a single inode fork format for metadata btree inodes And instead switch based on the metatype for the detailed btree format. This could probably be done even nicer by sharing the same btree root structure. Signed-off-by: Christoph Hellwig --- diff --git a/fs/xfs/libxfs/xfs_format.h b/fs/xfs/libxfs/xfs_format.h index 707d96113037..b1007fb661ba 100644 --- a/fs/xfs/libxfs/xfs_format.h +++ b/fs/xfs/libxfs/xfs_format.h @@ -1002,8 +1002,7 @@ enum xfs_dinode_fmt { XFS_DINODE_FMT_EXTENTS, /* struct xfs_bmbt_rec */ XFS_DINODE_FMT_BTREE, /* struct xfs_bmdr_block */ XFS_DINODE_FMT_UUID, /* added long ago, but never used */ - XFS_DINODE_FMT_RMAP, /* reverse mapping btree */ - XFS_DINODE_FMT_REFCOUNT, /* reference count btree */ + XFS_DINODE_FMT_META_BTREE, /* metadata btree */ }; #define XFS_INODE_FORMAT_STR \ @@ -1012,8 +1011,7 @@ enum xfs_dinode_fmt { { XFS_DINODE_FMT_EXTENTS, "extent" }, \ { XFS_DINODE_FMT_BTREE, "btree" }, \ { XFS_DINODE_FMT_UUID, "uuid" }, \ - { XFS_DINODE_FMT_RMAP, "rmap" }, \ - { XFS_DINODE_FMT_REFCOUNT, "refcount" } + { XFS_DINODE_FMT_META_BTREE, "meta_btree" } /* * Max values for extnum and aextnum. diff --git a/fs/xfs/libxfs/xfs_inode_buf.c b/fs/xfs/libxfs/xfs_inode_buf.c index 12e5709f8bc0..794ed6155162 100644 --- a/fs/xfs/libxfs/xfs_inode_buf.c +++ b/fs/xfs/libxfs/xfs_inode_buf.c @@ -441,20 +441,11 @@ xfs_dinode_verify_fork( if (di_nextents > max_extents) return __this_address; break; - case XFS_DINODE_FMT_RMAP: + case XFS_DINODE_FMT_META_BTREE: /* - * growfs must create the rtrmap inodes before adding a - * realtime volume to the filesystem, so we cannot use the - * rtrmapbt predicate here. + * XXX: do we need a finer grained check here? */ - if (!xfs_has_rmapbt(mp)) - return __this_address; - if (!(dip->di_flags2 & cpu_to_be64(XFS_DIFLAG2_METADATA))) - return __this_address; - break; - case XFS_DINODE_FMT_REFCOUNT: - /* same comment about growfs and rmap inodes applies here */ - if (!xfs_has_reflink(mp)) + if (!xfs_has_metadir(mp)) return __this_address; if (!(dip->di_flags2 & cpu_to_be64(XFS_DIFLAG2_METADATA))) return __this_address; @@ -478,9 +469,8 @@ xfs_dinode_verify_forkoff( if (dip->di_forkoff != (roundup(sizeof(xfs_dev_t), 8) >> 3)) return __this_address; break; - case XFS_DINODE_FMT_RMAP: - case XFS_DINODE_FMT_REFCOUNT: - if (!(xfs_has_metadir(mp) && xfs_has_parent(mp))) + case XFS_DINODE_FMT_META_BTREE: + if (!xfs_has_metadir(mp) || !xfs_has_parent(mp)) return __this_address; fallthrough; case XFS_DINODE_FMT_LOCAL: /* fall through ... */ @@ -765,18 +755,10 @@ xfs_dinode_verify( } /* metadata inodes containing btrees always have zero extent count */ - if (flags2 & XFS_DIFLAG2_METADATA) { - switch (XFS_DFORK_FORMAT(dip, XFS_DATA_FORK)) { - case XFS_DINODE_FMT_RMAP: - case XFS_DINODE_FMT_REFCOUNT: - break; - default: - if (nextents + naextents == 0 && nblocks != 0) - return __this_address; - break; - } - } else if (nextents + naextents == 0 && nblocks != 0) - return __this_address; + if (XFS_DFORK_FORMAT(dip, XFS_DATA_FORK) != XFS_DINODE_FMT_META_BTREE) { + if (nextents + naextents == 0 && nblocks != 0) + return __this_address; + } return NULL; } diff --git a/fs/xfs/libxfs/xfs_inode_fork.c b/fs/xfs/libxfs/xfs_inode_fork.c index 5c5deb9a77c9..28b0f3ec817d 100644 --- a/fs/xfs/libxfs/xfs_inode_fork.c +++ b/fs/xfs/libxfs/xfs_inode_fork.c @@ -270,24 +270,16 @@ xfs_iformat_data_fork( return xfs_iformat_extents(ip, dip, XFS_DATA_FORK); case XFS_DINODE_FMT_BTREE: return xfs_iformat_btree(ip, dip, XFS_DATA_FORK); - case XFS_DINODE_FMT_RMAP: - /* - * growfs must create the rtrmap inodes before adding a - * realtime volume to the filesystem, so we cannot use - * the rtrmapbt predicate here. - */ - if (!xfs_has_rmapbt(ip->i_mount)) { - xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE); - return -EFSCORRUPTED; - } - return xfs_iformat_rtrmap(ip, dip); - case XFS_DINODE_FMT_REFCOUNT: - /* same comment about growfs and rmap inodes applies */ - if (!xfs_has_reflink(ip->i_mount)) { - xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE); - return -EFSCORRUPTED; + case XFS_DINODE_FMT_META_BTREE: + switch (ip->i_metatype) { + case XFS_METAFILE_RTRMAP: + return xfs_iformat_rtrmap(ip, dip); + case XFS_METAFILE_RTREFCOUNT: + return xfs_iformat_rtrefcount(ip, dip); + default: + break; } - return xfs_iformat_rtrefcount(ip, dip); + fallthrough; default: xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, dip, sizeof(*dip), __this_address); @@ -607,16 +599,22 @@ xfs_iflush_fork( } break; - case XFS_DINODE_FMT_RMAP: + case XFS_DINODE_FMT_META_BTREE: ASSERT(whichfork == XFS_DATA_FORK); - if (iip->ili_fields & brootflag[whichfork]) - xfs_iflush_rtrmap(ip, dip); - break; - case XFS_DINODE_FMT_REFCOUNT: - ASSERT(whichfork == XFS_DATA_FORK); - if (iip->ili_fields & brootflag[whichfork]) + if (!(iip->ili_fields & brootflag[whichfork])) + break; + + switch (ip->i_metatype) { + case XFS_METAFILE_RTRMAP: + xfs_iflush_rtrmap(ip, dip); + break; + case XFS_METAFILE_RTREFCOUNT: xfs_iflush_rtrefcount(ip, dip); + break; + default: + ASSERT(0); + } break; default: diff --git a/fs/xfs/libxfs/xfs_rtgroup.c b/fs/xfs/libxfs/xfs_rtgroup.c index 2638d7bd4175..1dbd84f53628 100644 --- a/fs/xfs/libxfs/xfs_rtgroup.c +++ b/fs/xfs/libxfs/xfs_rtgroup.c @@ -311,17 +311,8 @@ xfs_rtginode_ilock_print_fn( const struct xfs_inode *ip = container_of(m, struct xfs_inode, i_lock.dep_map); - switch (ip->i_df.if_format) { - case XFS_DINODE_FMT_RMAP: - printk(KERN_CONT " rgno=%u rmapbt", ip->i_projid); - break; - case XFS_DINODE_FMT_REFCOUNT: - printk(KERN_CONT " rgno=%u refcountbt", ip->i_projid); - break; - default: - printk(KERN_CONT " rgno=%u", ip->i_projid); - break; - } + /* XXX: pretty print metatype */ + printk(KERN_CONT " rgno=%u metatype %u", ip->i_projid, ip->i_metatype); } /* @@ -386,7 +377,7 @@ static const struct xfs_rtginode_ops xfs_rtginode_ops[XFS_RTGI_MAX] = { .name = "rmap", .metafile_type = XFS_METAFILE_RTRMAP, .sick = XFS_SICK_RG_RMAPBT, - .fmt_mask = 1U << XFS_DINODE_FMT_RMAP, + .fmt_mask = 1U << XFS_DINODE_FMT_META_BTREE, /* * growfs must create the rtrmap inodes before adding a * realtime volume to the filesystem, so we cannot use the @@ -399,7 +390,7 @@ static const struct xfs_rtginode_ops xfs_rtginode_ops[XFS_RTGI_MAX] = { .name = "refcount", .metafile_type = XFS_METAFILE_RTREFCOUNT, .sick = XFS_SICK_RG_REFCNTBT, - .fmt_mask = 1U << XFS_DINODE_FMT_REFCOUNT, + .fmt_mask = 1U << XFS_DINODE_FMT_META_BTREE, /* same comment about growfs and rmap inodes applies here */ .enabled = xfs_has_reflink, .create = xfs_rtrefcountbt_create, diff --git a/fs/xfs/libxfs/xfs_rtrefcount_btree.c b/fs/xfs/libxfs/xfs_rtrefcount_btree.c index 2fe58aaceba6..ef7294cfb5f6 100644 --- a/fs/xfs/libxfs/xfs_rtrefcount_btree.c +++ b/fs/xfs/libxfs/xfs_rtrefcount_btree.c @@ -437,7 +437,7 @@ xfs_rtrefcountbt_commit_staged_btree( int flags = XFS_ILOG_CORE | XFS_ILOG_DBROOT; ASSERT(cur->bc_flags & XFS_BTREE_STAGING); - ASSERT(ifake->if_fork->if_format == XFS_DINODE_FMT_REFCOUNT); + ASSERT(ifake->if_fork->if_format == XFS_DINODE_FMT_META_BTREE); /* * Free any resources hanging off the real fork, then shallow-copy the @@ -639,6 +639,11 @@ xfs_iformat_rtrefcount( unsigned int level; int dsize; + if (!xfs_has_reflink(mp)) { + xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE); + return -EFSCORRUPTED; + } + dsize = XFS_DFORK_SIZE(dip, mp, XFS_DATA_FORK); numrecs = be16_to_cpu(dfp->bb_numrecs); level = be16_to_cpu(dfp->bb_level); @@ -734,7 +739,7 @@ xfs_rtrefcountbt_create( struct xfs_mount *mp = ip->i_mount; struct xfs_btree_block *broot; - ifp->if_format = XFS_DINODE_FMT_REFCOUNT; + ifp->if_format = XFS_DINODE_FMT_META_BTREE; ASSERT(ifp->if_broot_bytes == 0); ASSERT(ifp->if_bytes == 0); diff --git a/fs/xfs/libxfs/xfs_rtrmap_btree.c b/fs/xfs/libxfs/xfs_rtrmap_btree.c index 86ede1517dde..1f83a361c6f9 100644 --- a/fs/xfs/libxfs/xfs_rtrmap_btree.c +++ b/fs/xfs/libxfs/xfs_rtrmap_btree.c @@ -675,7 +675,7 @@ xfs_rtrmapbt_commit_staged_btree( int flags = XFS_ILOG_CORE | XFS_ILOG_DBROOT; ASSERT(cur->bc_flags & XFS_BTREE_STAGING); - ASSERT(ifake->if_fork->if_format == XFS_DINODE_FMT_RMAP); + ASSERT(ifake->if_fork->if_format == XFS_DINODE_FMT_META_BTREE); /* * Free any resources hanging off the real fork, then shallow-copy the @@ -896,6 +896,11 @@ xfs_iformat_rtrmap( unsigned int level; int dsize; + if (!xfs_has_rmapbt(mp)) { + xfs_inode_mark_sick(ip, XFS_SICK_INO_CORE); + return -EFSCORRUPTED; + } + dsize = XFS_DFORK_SIZE(dip, mp, XFS_DATA_FORK); numrecs = be16_to_cpu(dfp->bb_numrecs); level = be16_to_cpu(dfp->bb_level); @@ -987,7 +992,7 @@ xfs_rtrmapbt_create( struct xfs_mount *mp = ip->i_mount; struct xfs_btree_block *broot; - ifp->if_format = XFS_DINODE_FMT_RMAP; + ifp->if_format = XFS_DINODE_FMT_META_BTREE; ASSERT(ifp->if_broot_bytes == 0); ASSERT(ifp->if_bytes == 0); diff --git a/fs/xfs/scrub/bmap.c b/fs/xfs/scrub/bmap.c index 7631bcbe3ecf..66da7d4d56ba 100644 --- a/fs/xfs/scrub/bmap.c +++ b/fs/xfs/scrub/bmap.c @@ -1064,8 +1064,7 @@ xchk_bmap( case XFS_DINODE_FMT_UUID: case XFS_DINODE_FMT_DEV: case XFS_DINODE_FMT_LOCAL: - case XFS_DINODE_FMT_RMAP: - case XFS_DINODE_FMT_REFCOUNT: + case XFS_DINODE_FMT_META_BTREE: /* No mappings to check. */ if (whichfork == XFS_COW_FORK) xchk_fblock_set_corrupt(sc, whichfork, 0); diff --git a/fs/xfs/scrub/bmap_repair.c b/fs/xfs/scrub/bmap_repair.c index 58fde2812527..1084213b8e9b 100644 --- a/fs/xfs/scrub/bmap_repair.c +++ b/fs/xfs/scrub/bmap_repair.c @@ -864,8 +864,7 @@ xrep_bmap_check_inputs( case XFS_DINODE_FMT_DEV: case XFS_DINODE_FMT_LOCAL: case XFS_DINODE_FMT_UUID: - case XFS_DINODE_FMT_RMAP: - case XFS_DINODE_FMT_REFCOUNT: + case XFS_DINODE_FMT_META_BTREE: return -ECANCELED; case XFS_DINODE_FMT_EXTENTS: case XFS_DINODE_FMT_BTREE: diff --git a/fs/xfs/scrub/common.c b/fs/xfs/scrub/common.c index 299c9f841ffa..6ee544fc9b20 100644 --- a/fs/xfs/scrub/common.c +++ b/fs/xfs/scrub/common.c @@ -1679,6 +1679,42 @@ xchk_inode_rootdir_inum(const struct xfs_inode *ip) return mp->m_rootip->i_ino; } +static int +xchk_meta_btree_count_blocks( + struct xfs_scrub *sc, + xfs_extnum_t *nextents, + xfs_filblks_t *count) +{ + struct xfs_btree_cur *cur; + xfs_extlen_t btblocks; + int error; + + if (!sc->sr.rtg) { + ASSERT(0); + return -EFSCORRUPTED; + } + + switch (sc->ip->i_metatype) { + case XFS_METAFILE_RTRMAP: + cur = xfs_rtrmapbt_init_cursor(sc->tp, sc->sr.rtg); + break; + case XFS_METAFILE_RTREFCOUNT: + cur = xfs_rtrefcountbt_init_cursor(sc->tp, sc->sr.rtg); + break; + default: + ASSERT(0); + return -EFSCORRUPTED; + } + + error = xfs_btree_count_blocks(cur, &btblocks); + xfs_btree_del_cursor(cur, error); + if (!error) { + *nextents = 0; + *count = btblocks - 1; + } + return error; +} + /* Count the blocks used by a file, even if it's a metadata inode. */ int xchk_inode_count_blocks( @@ -1688,9 +1724,6 @@ xchk_inode_count_blocks( xfs_filblks_t *count) { struct xfs_ifork *ifp = xfs_ifork_ptr(sc->ip, whichfork); - struct xfs_btree_cur *cur; - xfs_extlen_t btblocks; - int error; if (!ifp) { *nextents = 0; @@ -1698,32 +1731,10 @@ xchk_inode_count_blocks( return 0; } - switch (ifp->if_format) { - case XFS_DINODE_FMT_RMAP: - if (!sc->sr.rtg) { - ASSERT(0); - return -EFSCORRUPTED; - } - cur = xfs_rtrmapbt_init_cursor(sc->tp, sc->sr.rtg); - goto meta_btree; - case XFS_DINODE_FMT_REFCOUNT: - if (!sc->sr.rtg) { - ASSERT(0); - return -EFSCORRUPTED; - } - cur = xfs_rtrefcountbt_init_cursor(sc->tp, sc->sr.rtg); - goto meta_btree; + if (ifp->if_format == XFS_DINODE_FMT_META_BTREE) { + ASSERT(whichfork == XFS_DATA_FORK); + return xchk_meta_btree_count_blocks(sc, nextents, count); } - return xfs_bmap_count_blocks(sc->tp, sc->ip, whichfork, nextents, count); -meta_btree: - error = xfs_btree_count_blocks(cur, &btblocks); - xfs_btree_del_cursor(cur, error); - if (error) - return error; - - *nextents = 0; - *count = btblocks - 1; - return 0; } diff --git a/fs/xfs/scrub/inode.c b/fs/xfs/scrub/inode.c index 53788a699fa5..db6edd5a5fe5 100644 --- a/fs/xfs/scrub/inode.c +++ b/fs/xfs/scrub/inode.c @@ -511,8 +511,7 @@ xchk_dinode( if (!S_ISREG(mode) && !S_ISDIR(mode)) xchk_ino_set_corrupt(sc, ino); break; - case XFS_DINODE_FMT_RMAP: - case XFS_DINODE_FMT_REFCOUNT: + case XFS_DINODE_FMT_META_BTREE: if (!S_ISREG(mode)) xchk_ino_set_corrupt(sc, ino); break; diff --git a/fs/xfs/scrub/inode_repair.c b/fs/xfs/scrub/inode_repair.c index 4deaaf24c318..cd51be00595c 100644 --- a/fs/xfs/scrub/inode_repair.c +++ b/fs/xfs/scrub/inode_repair.c @@ -948,19 +948,16 @@ STATIC bool xrep_dinode_bad_rmapbt_fork( struct xfs_scrub *sc, struct xfs_dinode *dip, - unsigned int dfork_size, - int whichfork) + unsigned int dfork_size) { struct xfs_rtrmap_root *dfp; unsigned int nrecs; unsigned int level; - if (whichfork != XFS_DATA_FORK) - return true; if (dfork_size < sizeof(struct xfs_rtrmap_root)) return true; - dfp = XFS_DFORK_PTR(dip, whichfork); + dfp = XFS_DFORK_PTR(dip, XFS_DATA_FORK); nrecs = be16_to_cpu(dfp->bb_numrecs); level = be16_to_cpu(dfp->bb_level); @@ -979,19 +976,16 @@ STATIC bool xrep_dinode_bad_refcountbt_fork( struct xfs_scrub *sc, struct xfs_dinode *dip, - unsigned int dfork_size, - int whichfork) + unsigned int dfork_size) { struct xfs_rtrefcount_root *dfp; unsigned int nrecs; unsigned int level; - if (whichfork != XFS_DATA_FORK) - return true; if (dfork_size < sizeof(struct xfs_rtrefcount_root)) return true; - dfp = XFS_DFORK_PTR(dip, whichfork); + dfp = XFS_DFORK_PTR(dip, XFS_DATA_FORK); nrecs = be16_to_cpu(dfp->bb_numrecs); level = be16_to_cpu(dfp->bb_level); @@ -1005,6 +999,26 @@ xrep_dinode_bad_refcountbt_fork( return false; } +STATIC bool +xrep_dinode_bad_metabt_fork( + struct xfs_scrub *sc, + struct xfs_dinode *dip, + unsigned int dfork_size, + int whichfork) +{ + if (whichfork != XFS_DATA_FORK) + return true; + + switch (be16_to_cpu(dip->di_metatype)) { + case XFS_METAFILE_RTRMAP: + return xrep_dinode_bad_rmapbt_fork(sc, dip, dfork_size); + case XFS_METAFILE_RTREFCOUNT: + return xrep_dinode_bad_refcountbt_fork(sc, dip, dfork_size); + default: + return true; + } +} + /* * Check the data fork for things that will fail the ifork verifiers or the * ifork formatters. @@ -1085,13 +1099,8 @@ xrep_dinode_check_dfork( XFS_DATA_FORK)) return true; break; - case XFS_DINODE_FMT_RMAP: - if (xrep_dinode_bad_rmapbt_fork(sc, dip, dfork_size, - XFS_DATA_FORK)) - return true; - break; - case XFS_DINODE_FMT_REFCOUNT: - if (xrep_dinode_bad_refcountbt_fork(sc, dip, dfork_size, + case XFS_DINODE_FMT_META_BTREE: + if (xrep_dinode_bad_metabt_fork(sc, dip, dfork_size, XFS_DATA_FORK)) return true; break; @@ -1215,13 +1224,8 @@ xrep_dinode_check_afork( XFS_ATTR_FORK)) return true; break; - case XFS_DINODE_FMT_RMAP: - if (xrep_dinode_bad_rmapbt_fork(sc, dip, afork_size, - XFS_ATTR_FORK)) - return true; - break; - case XFS_DINODE_FMT_REFCOUNT: - if (xrep_dinode_bad_refcountbt_fork(sc, dip, afork_size, + case XFS_DINODE_FMT_META_BTREE: + if (xrep_dinode_bad_metabt_fork(sc, dip, afork_size, XFS_ATTR_FORK)) return true; break; @@ -1380,13 +1384,19 @@ xrep_dinode_ensure_forkoff( bmdr = XFS_DFORK_PTR(dip, XFS_DATA_FORK); dfork_min = xfs_bmap_broot_space(sc->mp, bmdr); break; - case XFS_DINODE_FMT_RMAP: - rmdr = XFS_DFORK_PTR(dip, XFS_DATA_FORK); - dfork_min = xfs_rtrmap_broot_space(sc->mp, rmdr); - break; - case XFS_DINODE_FMT_REFCOUNT: - rcdr = XFS_DFORK_PTR(dip, XFS_DATA_FORK); - dfork_min = xfs_rtrefcount_broot_space(sc->mp, rcdr); + case XFS_DINODE_FMT_META_BTREE: + switch (be16_to_cpu(dip->di_metatype)) { + case XFS_METAFILE_RTRMAP: + rmdr = XFS_DFORK_PTR(dip, XFS_DATA_FORK); + dfork_min = xfs_rtrmap_broot_space(sc->mp, rmdr); + break; + case XFS_METAFILE_RTREFCOUNT: + rcdr = XFS_DFORK_PTR(dip, XFS_DATA_FORK); + dfork_min = xfs_rtrefcount_broot_space(sc->mp, rcdr); + break; + default: + break; + } break; default: dfork_min = 0; diff --git a/fs/xfs/scrub/rmap_repair.c b/fs/xfs/scrub/rmap_repair.c index 5f93aaa4fcfe..7f735b361191 100644 --- a/fs/xfs/scrub/rmap_repair.c +++ b/fs/xfs/scrub/rmap_repair.c @@ -503,62 +503,35 @@ xrep_rmap_scan_iext( } static int -xrep_rmap_scan_rtrmapbt( +xrep_rmap_scan_meta_btree( struct xrep_rmap_ifork *rf, struct xfs_inode *ip) { struct xfs_scrub *sc = rf->rr->sc; struct xfs_rtgroup *rtg = NULL; struct xfs_btree_cur *cur; + enum xfs_rtg_inodes type; int error; if (rf->whichfork != XFS_DATA_FORK) return -EFSCORRUPTED; - while ((rtg = xfs_rtgroup_next(sc->mp, rtg))) { - if (ip == rtg->rtg_inodes[XFS_RTGI_RMAP]) { - cur = xfs_rtrmapbt_init_cursor(sc->tp, rtg); - error = xrep_rmap_scan_iroot_btree(rf, cur); - xfs_btree_del_cursor(cur, error); - xfs_rtgroup_rele(rtg); - return error; - } - } - - /* - * We shouldn't find an rmap format inode that isn't associated with - * an rtgroup and has ondisk blocks allocated to it. - */ - if (ip->i_nblocks) { + switch (ip->i_metatype) { + case XFS_METAFILE_RTRMAP: + type = XFS_RTGI_RMAP; + break; + case XFS_METAFILE_RTREFCOUNT: + type = XFS_RTGI_REFCOUNT; + break; + default: ASSERT(0); return -EFSCORRUPTED; } - return 0; -} -static int -xrep_rmap_scan_rtrefcountbt( - struct xrep_rmap_ifork *rf, - struct xfs_inode *ip) -{ - struct xfs_scrub *sc = rf->rr->sc; - struct xfs_rtgroup *rtg = NULL; - struct xfs_btree_cur *cur; - int error; - - if (rf->whichfork != XFS_DATA_FORK) - return -EFSCORRUPTED; - - while ((rtg = xfs_rtgroup_next(sc->mp, rtg))) { - if (ip == rtg->rtg_inodes[XFS_RTGI_REFCOUNT]) { - cur = xfs_rtrefcountbt_init_cursor(sc->tp, rtg); - error = xrep_rmap_scan_iroot_btree(rf, cur); - xfs_btree_del_cursor(cur, error); - xfs_rtgroup_rele(rtg); - return error; - } - } + while ((rtg = xfs_rtgroup_next(sc->mp, rtg))) + if (ip == rtg->rtg_inodes[type]) + goto found; /* * We shouldn't find a refcount format inode that isn't associated with @@ -570,6 +543,16 @@ xrep_rmap_scan_rtrefcountbt( } return 0; + +found: + if (ip->i_metatype == XFS_METAFILE_RTRMAP) + cur = xfs_rtrmapbt_init_cursor(sc->tp, rtg); + else + cur = xfs_rtrefcountbt_init_cursor(sc->tp, rtg); + error = xrep_rmap_scan_iroot_btree(rf, cur); + xfs_btree_del_cursor(cur, error); + xfs_rtgroup_rele(rtg); + return error; } /* Find all the extents from a given AG in an inode fork. */ @@ -585,14 +568,14 @@ xrep_rmap_scan_ifork( .whichfork = whichfork, }; struct xfs_ifork *ifp = xfs_ifork_ptr(ip, whichfork); + bool mappings_done; int error = 0; if (!ifp) return 0; - if (ifp->if_format == XFS_DINODE_FMT_BTREE) { - bool mappings_done; - + switch (ifp->if_format) { + case XFS_DINODE_FMT_BTREE: /* * Scan the bmap btree for data device mappings. This includes * the btree blocks themselves, even if this is a realtime @@ -601,19 +584,17 @@ xrep_rmap_scan_ifork( error = xrep_rmap_scan_bmbt(&rf, ip, &mappings_done); if (error || mappings_done) return error; - } else if (ifp->if_format == XFS_DINODE_FMT_RMAP) { - return xrep_rmap_scan_rtrmapbt(&rf, ip); - } else if (ifp->if_format == XFS_DINODE_FMT_REFCOUNT) { - return xrep_rmap_scan_rtrefcountbt(&rf, ip); - } else if (ifp->if_format != XFS_DINODE_FMT_EXTENTS) { + fallthrough; + case XFS_DINODE_FMT_EXTENTS: + /* Scan incore extent cache if this isn't a realtime file. */ + if (xfs_ifork_is_realtime(ip, whichfork)) + return 0; + return xrep_rmap_scan_iext(&rf, ifp); + case XFS_DINODE_FMT_META_BTREE: + return xrep_rmap_scan_meta_btree(&rf, ip); + default: return 0; } - - /* Scan incore extent cache if this isn't a realtime file. */ - if (xfs_ifork_is_realtime(ip, whichfork)) - return 0; - - return xrep_rmap_scan_iext(&rf, ifp); } /* diff --git a/fs/xfs/scrub/rtrefcount_repair.c b/fs/xfs/scrub/rtrefcount_repair.c index 179ce9239445..ab9315c5d69d 100644 --- a/fs/xfs/scrub/rtrefcount_repair.c +++ b/fs/xfs/scrub/rtrefcount_repair.c @@ -671,7 +671,7 @@ xrep_rtrefc_build_new_tree( goto err_cur; /* Add all observed refcount records. */ - rr->new_btree.ifake.if_fork->if_format = XFS_DINODE_FMT_REFCOUNT; + rr->new_btree.ifake.if_fork->if_format = XFS_DINODE_FMT_META_BTREE; rr->array_cur = XFARRAY_CURSOR_INIT; error = xfs_btree_bload(refc_cur, &rr->new_btree.bload, rr); if (error) diff --git a/fs/xfs/scrub/rtrmap_repair.c b/fs/xfs/scrub/rtrmap_repair.c index 4de2a5335af5..e70f6f9918e8 100644 --- a/fs/xfs/scrub/rtrmap_repair.c +++ b/fs/xfs/scrub/rtrmap_repair.c @@ -772,7 +772,7 @@ xrep_rtrmap_build_new_tree( goto err_mcur; /* Add all observed rmap records. */ - rr->new_btree.ifake.if_fork->if_format = XFS_DINODE_FMT_RMAP; + rr->new_btree.ifake.if_fork->if_format = XFS_DINODE_FMT_META_BTREE; error = xfs_btree_bload(rmap_cur, &rr->new_btree.bload, rr); if (error) goto err_mcur; diff --git a/fs/xfs/xfs_inode.c b/fs/xfs/xfs_inode.c index f39db43f5bf0..71ec46991e84 100644 --- a/fs/xfs/xfs_inode.c +++ b/fs/xfs/xfs_inode.c @@ -2382,19 +2382,11 @@ xfs_iflush( __func__, ip->i_ino, be16_to_cpu(dip->di_magic), dip); goto flush_out; } - if (ip->i_df.if_format == XFS_DINODE_FMT_RMAP) { + if (ip->i_df.if_format == XFS_DINODE_FMT_META_BTREE) { if (!S_ISREG(VFS_I(ip)->i_mode) || !(ip->i_diflags2 & XFS_DIFLAG2_METADATA)) { xfs_alert_tag(mp, XFS_PTAG_IFLUSH, - "%s: Bad rt rmapbt inode %Lu, ptr "PTR_FMT, - __func__, ip->i_ino, ip); - goto flush_out; - } - } else if (ip->i_df.if_format == XFS_DINODE_FMT_REFCOUNT) { - if (!S_ISREG(VFS_I(ip)->i_mode) || - !(ip->i_diflags2 & XFS_DIFLAG2_METADATA)) { - xfs_alert_tag(mp, XFS_PTAG_IFLUSH, - "%s: Bad rt refcountbt inode %Lu, ptr "PTR_FMT, + "%s: Bad meta btree inode %Lu, ptr "PTR_FMT, __func__, ip->i_ino, ip); goto flush_out; } @@ -2438,18 +2430,12 @@ xfs_iflush( goto flush_out; } - if (xfs_inode_has_attr_fork(ip)) { - if (ip->i_af.if_format == XFS_DINODE_FMT_RMAP) { - xfs_alert_tag(mp, XFS_PTAG_IFLUSH, - "%s: rt rmapbt in inode %Lu attr fork, ptr "PTR_FMT, - __func__, ip->i_ino, ip); - goto flush_out; - } else if (ip->i_af.if_format == XFS_DINODE_FMT_REFCOUNT) { - xfs_alert_tag(mp, XFS_PTAG_IFLUSH, - "%s: rt refcountbt in inode %Lu attr fork, ptr "PTR_FMT, - __func__, ip->i_ino, ip); - goto flush_out; - } + if (xfs_inode_has_attr_fork(ip) && + ip->i_af.if_format == XFS_DINODE_FMT_META_BTREE) { + xfs_alert_tag(mp, XFS_PTAG_IFLUSH, + "%s: meta btree in inode %Lu attr fork, ptr "PTR_FMT, + __func__, ip->i_ino, ip); + goto flush_out; } /* diff --git a/fs/xfs/xfs_inode_item.c b/fs/xfs/xfs_inode_item.c index 5338c7fa12c9..70283c6419fd 100644 --- a/fs/xfs/xfs_inode_item.c +++ b/fs/xfs/xfs_inode_item.c @@ -256,8 +256,7 @@ xfs_inode_item_data_fork_size( } break; case XFS_DINODE_FMT_BTREE: - case XFS_DINODE_FMT_RMAP: - case XFS_DINODE_FMT_REFCOUNT: + case XFS_DINODE_FMT_META_BTREE: if ((iip->ili_fields & XFS_ILOG_DBROOT) && ip->i_df.if_broot_bytes > 0) { *nbytes += ip->i_df.if_broot_bytes; @@ -378,8 +377,7 @@ xfs_inode_item_format_data_fork( } break; case XFS_DINODE_FMT_BTREE: - case XFS_DINODE_FMT_RMAP: - case XFS_DINODE_FMT_REFCOUNT: + case XFS_DINODE_FMT_META_BTREE: iip->ili_fields &= ~(XFS_ILOG_DDATA | XFS_ILOG_DEXT | XFS_ILOG_DEV); diff --git a/fs/xfs/xfs_inode_item_recover.c b/fs/xfs/xfs_inode_item_recover.c index ee8ea8cfa3fe..5c77fcad4342 100644 --- a/fs/xfs/xfs_inode_item_recover.c +++ b/fs/xfs/xfs_inode_item_recover.c @@ -281,19 +281,23 @@ xlog_recover_inode_dbroot( switch (dip->di_format) { case XFS_DINODE_FMT_BTREE: xfs_bmbt_to_bmdr(mp, src, len, dfork, dsize); - break; - case XFS_DINODE_FMT_RMAP: - xfs_rtrmapbt_to_disk(mp, src, len, dfork, dsize); - break; - case XFS_DINODE_FMT_REFCOUNT: - xfs_rtrefcountbt_to_disk(mp, src, len, dfork, dsize); - break; + return 0; + case XFS_DINODE_FMT_META_BTREE: + switch (be16_to_cpu(dip->di_metatype)) { + case XFS_METAFILE_RTRMAP: + xfs_rtrmapbt_to_disk(mp, src, len, dfork, dsize); + return 0; + case XFS_METAFILE_RTREFCOUNT: + xfs_rtrefcountbt_to_disk(mp, src, len, dfork, dsize); + return 0; + default: + ASSERT(0); + return -EFSCORRUPTED; + } default: ASSERT(0); return -EFSCORRUPTED; } - - return 0; } STATIC int @@ -424,8 +428,7 @@ xlog_recover_inode_commit_pass2( if (unlikely(S_ISREG(ldip->di_mode))) { if ((ldip->di_format != XFS_DINODE_FMT_EXTENTS) && - (ldip->di_format != XFS_DINODE_FMT_RMAP) && - (ldip->di_format != XFS_DINODE_FMT_REFCOUNT) && + (ldip->di_format != XFS_DINODE_FMT_META_BTREE) && (ldip->di_format != XFS_DINODE_FMT_BTREE)) { XFS_CORRUPTION_ERROR( "Bad log dinode data fork format for regular file", diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h index 64fa36806dca..c92129ebd102 100644 --- a/fs/xfs/xfs_trace.h +++ b/fs/xfs/xfs_trace.h @@ -2295,8 +2295,7 @@ TRACE_DEFINE_ENUM(XFS_DINODE_FMT_LOCAL); TRACE_DEFINE_ENUM(XFS_DINODE_FMT_EXTENTS); TRACE_DEFINE_ENUM(XFS_DINODE_FMT_BTREE); TRACE_DEFINE_ENUM(XFS_DINODE_FMT_UUID); -TRACE_DEFINE_ENUM(XFS_DINODE_FMT_RMAP); -TRACE_DEFINE_ENUM(XFS_DINODE_FMT_REFCOUNT); +TRACE_DEFINE_ENUM(XFS_DINODE_FMT_META_BTREE); DECLARE_EVENT_CLASS(xfs_swap_extent_class, TP_PROTO(struct xfs_inode *ip, int which),