From 95833f0c1628a0b6d66e6683a7f6d6e31f6873b2 Mon Sep 17 00:00:00 2001 From: "Darrick J. Wong" Date: Fri, 9 Aug 2024 13:57:58 +0200 Subject: [PATCH] xfs: add realtime reverse map inode to metadata directory Source kernel commit: 5d061b9bf74b67573a4f6a0c223a935a7c1cbbe9 Add a metadir path to select the realtime rmap btree inode and load it at mount time. The rtrmapbt inode will have a unique extent format code, which means that we also have to update the inode validation and flush routines to look for it. Signed-off-by: Darrick J. Wong Signed-off-by: Christoph Hellwig --- libxfs/xfs_format.h | 6 ++++-- libxfs/xfs_inode_buf.c | 10 ++++++++++ libxfs/xfs_inode_fork.c | 9 +++++++++ libxfs/xfs_rtgroup.c | 23 ++++++++++++++++++++++- libxfs/xfs_rtgroup.h | 3 +++ libxfs/xfs_rtrmap_btree.c | 2 ++ 6 files changed, 50 insertions(+), 3 deletions(-) diff --git a/libxfs/xfs_format.h b/libxfs/xfs_format.h index ef2232171..28501fae2 100644 --- a/libxfs/xfs_format.h +++ b/libxfs/xfs_format.h @@ -986,7 +986,8 @@ enum xfs_dinode_fmt { XFS_DINODE_FMT_LOCAL, /* bulk data */ 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_UUID, /* added long ago, but never used */ + XFS_DINODE_FMT_RMAP, /* reverse mapping btree */ }; #define XFS_INODE_FORMAT_STR \ @@ -994,7 +995,8 @@ enum xfs_dinode_fmt { { XFS_DINODE_FMT_LOCAL, "local" }, \ { XFS_DINODE_FMT_EXTENTS, "extent" }, \ { XFS_DINODE_FMT_BTREE, "btree" }, \ - { XFS_DINODE_FMT_UUID, "uuid" } + { XFS_DINODE_FMT_UUID, "uuid" }, \ + { XFS_DINODE_FMT_RMAP, "rmap" } /* * Max values for extnum and aextnum. diff --git a/libxfs/xfs_inode_buf.c b/libxfs/xfs_inode_buf.c index 98a39e071..192d3202d 100644 --- a/libxfs/xfs_inode_buf.c +++ b/libxfs/xfs_inode_buf.c @@ -431,6 +431,12 @@ xfs_dinode_verify_fork( if (di_nextents > max_extents) return __this_address; break; + case XFS_DINODE_FMT_RMAP: + if (!xfs_has_rtrmapbt(mp)) + return __this_address; + if (!(dip->di_flags2 & cpu_to_be64(XFS_DIFLAG2_METADATA))) + return __this_address; + break; default: return __this_address; } @@ -450,6 +456,10 @@ xfs_dinode_verify_forkoff( if (dip->di_forkoff != (roundup(sizeof(xfs_dev_t), 8) >> 3)) return __this_address; break; + case XFS_DINODE_FMT_RMAP: + if (!(xfs_has_metadir(mp) && xfs_has_parent(mp))) + return __this_address; + fallthrough; case XFS_DINODE_FMT_LOCAL: /* fall through ... */ case XFS_DINODE_FMT_EXTENTS: /* fall through ... */ case XFS_DINODE_FMT_BTREE: diff --git a/libxfs/xfs_inode_fork.c b/libxfs/xfs_inode_fork.c index 98f788901..1e7f81eea 100644 --- a/libxfs/xfs_inode_fork.c +++ b/libxfs/xfs_inode_fork.c @@ -266,6 +266,11 @@ 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: + if (!xfs_has_rtrmapbt(ip->i_mount)) + return -EFSCORRUPTED; + ASSERT(0); /* to be implemented later */ + return -EFSCORRUPTED; default: xfs_inode_verifier_error(ip, -EFSCORRUPTED, __func__, dip, sizeof(*dip), __this_address); @@ -652,6 +657,10 @@ xfs_iflush_fork( } break; + case XFS_DINODE_FMT_RMAP: + ASSERT(0); /* to be implemented later */ + break; + default: ASSERT(0); break; diff --git a/libxfs/xfs_rtgroup.c b/libxfs/xfs_rtgroup.c index d777e4945..f4c7f0d9f 100644 --- a/libxfs/xfs_rtgroup.c +++ b/libxfs/xfs_rtgroup.c @@ -308,7 +308,14 @@ xfs_rtginode_ilock_print_fn( const struct xfs_inode *ip = container_of(m, struct xfs_inode, i_lock.dep_map); - printk(KERN_CONT " rgno=%u", ip->i_projid); + switch (ip->i_df.if_format) { + case XFS_DINODE_FMT_RMAP: + printk(KERN_CONT " rgno=%u rmapbt", ip->i_projid); + break; + default: + printk(KERN_CONT " rgno=%u", ip->i_projid); + break; + } } /* @@ -336,6 +343,7 @@ xfs_rtginode_lockdep_setup( struct xfs_rtginode_ops { const char *name; /* short name */ unsigned int sick; /* rtgroup sickness flag */ + int8_t format; /* data fork format */ /* Does the fs have this feature? */ bool (*enabled)(struct xfs_mount *mp); @@ -357,6 +365,11 @@ static const struct xfs_rtginode_ops xfs_rtginode_ops[XFS_RTG_MAX] = { .sick = XFS_SICK_RG_SUMMARY, .create = xfs_rtsummary_create, }, + [XFS_RTG_RMAP] = { + .name = "rmap", + .format = XFS_DINODE_FMT_RMAP, + .enabled = xfs_has_rtrmapbt, + }, }; /* Return the shortname of this rtgroup inode. */ @@ -397,6 +410,7 @@ xfs_rtginode_load( enum xfs_rtg_inodes type, struct xfs_trans *tp) { + const struct xfs_rtginode_ops *ops = &xfs_rtginode_ops[type]; struct xfs_mount *mp = tp->t_mountp; struct xfs_inode *ip; int error; @@ -435,6 +449,13 @@ xfs_rtginode_load( return error; } + if (ops->format && + XFS_IS_CORRUPT(mp, ip->i_df.if_format != ops->format)) { + xfs_irele(ip); + xfs_rtgroup_mark_sick(rtg, ops->sick); + return -EFSCORRUPTED; + } + if (XFS_IS_CORRUPT(mp, ip->i_projid != rtg->rtg_rgno)) { xfs_irele(ip); xfs_rtginode_mark_sick(rtg, type); diff --git a/libxfs/xfs_rtgroup.h b/libxfs/xfs_rtgroup.h index de72541ef..0c495df60 100644 --- a/libxfs/xfs_rtgroup.h +++ b/libxfs/xfs_rtgroup.h @@ -12,6 +12,7 @@ struct xfs_trans; enum xfs_rtg_inodes { XFS_RTG_BITMAP, /* allocation bitmap */ XFS_RTG_SUMMARY, /* allocation summary */ + XFS_RTG_RMAP, /* rmap btree inode */ XFS_RTG_MAX, }; @@ -264,6 +265,8 @@ int xfs_rtginode_create(struct xfs_rtgroup *rtg, enum xfs_rtg_inodes type, bool init); void xfs_rtginode_irele(struct xfs_inode **ipp); +void xfs_rtginode_irele(struct xfs_inode **ipp); + static inline const char *xfs_rtginode_path(xfs_rgnumber_t rgno, enum xfs_rtg_inodes type) { diff --git a/libxfs/xfs_rtrmap_btree.c b/libxfs/xfs_rtrmap_btree.c index 2e1232155..e421635af 100644 --- a/libxfs/xfs_rtrmap_btree.c +++ b/libxfs/xfs_rtrmap_btree.c @@ -18,6 +18,7 @@ #include "xfs_alloc.h" #include "xfs_btree.h" #include "xfs_btree_staging.h" +#include "xfs_metafile.h" #include "xfs_rmap.h" #include "xfs_rtrmap_btree.h" #include "xfs_trace.h" @@ -441,6 +442,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); /* * Free any resources hanging off the real fork, then shallow-copy the -- 2.50.1