On Sun, Mar 15, 2020 at 04:51:06PM -0700, Darrick J. Wong wrote: > From: Darrick J. Wong <darrick.wong@xxxxxxxxxx> > > Add support for btree staging cursors for the free space btrees. This > is needed both for online repair and also to convert xfs_repair to use > btree bulk loading. > > Signed-off-by: Darrick J. Wong <darrick.wong@xxxxxxxxxx> > --- > fs/xfs/libxfs/xfs_alloc_btree.c | 98 +++++++++++++++++++++++++++++++-------- > fs/xfs/libxfs/xfs_alloc_btree.h | 7 +++ > 2 files changed, 86 insertions(+), 19 deletions(-) > > > diff --git a/fs/xfs/libxfs/xfs_alloc_btree.c b/fs/xfs/libxfs/xfs_alloc_btree.c > index a28041fdf4c0..93792ee7924e 100644 > --- a/fs/xfs/libxfs/xfs_alloc_btree.c > +++ b/fs/xfs/libxfs/xfs_alloc_btree.c ... > @@ -485,36 +520,61 @@ xfs_allocbt_init_cursor( ... > > +/* > + * Install a new free space btree root. Caller is responsible for invalidating > + * and freeing the old btree blocks. > + */ > +void > +xfs_allocbt_commit_staged_btree( > + struct xfs_btree_cur *cur, > + struct xfs_trans *tp, > + struct xfs_buf *agbp) > +{ > + struct xfs_agf *agf = agbp->b_addr; > + struct xbtree_afakeroot *afake = cur->bc_ag.afake; > + > + ASSERT(cur->bc_flags & XFS_BTREE_STAGING); > + > + agf->agf_roots[cur->bc_btnum] = cpu_to_be32(afake->af_root); > + agf->agf_levels[cur->bc_btnum] = cpu_to_be32(afake->af_levels); > + xfs_alloc_log_agf(tp, agbp, XFS_AGF_ROOTS | XFS_AGF_LEVELS); > + > + if (cur->bc_btnum == XFS_BTNUM_BNO) { > + xfs_btree_commit_afakeroot(cur, tp, agbp, &xfs_bnobt_ops); > + } else { > + cur->bc_flags |= XFS_BTREE_LASTREC_UPDATE; Any reason this is set here and not at init time for the staging cursor? Brian > + xfs_btree_commit_afakeroot(cur, tp, agbp, &xfs_cntbt_ops); > + } > +} > + > /* > * Calculate number of records in an alloc btree block. > */ > diff --git a/fs/xfs/libxfs/xfs_alloc_btree.h b/fs/xfs/libxfs/xfs_alloc_btree.h > index c9305ebb69f6..047f09f0be3c 100644 > --- a/fs/xfs/libxfs/xfs_alloc_btree.h > +++ b/fs/xfs/libxfs/xfs_alloc_btree.h > @@ -13,6 +13,7 @@ > struct xfs_buf; > struct xfs_btree_cur; > struct xfs_mount; > +struct xbtree_afakeroot; > > /* > * Btree block header size depends on a superblock flag. > @@ -48,8 +49,14 @@ struct xfs_mount; > extern struct xfs_btree_cur *xfs_allocbt_init_cursor(struct xfs_mount *, > struct xfs_trans *, struct xfs_buf *, > xfs_agnumber_t, xfs_btnum_t); > +struct xfs_btree_cur *xfs_allocbt_stage_cursor(struct xfs_mount *mp, > + struct xbtree_afakeroot *afake, xfs_agnumber_t agno, > + xfs_btnum_t btnum); > extern int xfs_allocbt_maxrecs(struct xfs_mount *, int, int); > extern xfs_extlen_t xfs_allocbt_calc_size(struct xfs_mount *mp, > unsigned long long len); > > +void xfs_allocbt_commit_staged_btree(struct xfs_btree_cur *cur, > + struct xfs_trans *tp, struct xfs_buf *agbp); > + > #endif /* __XFS_ALLOC_BTREE_H__ */ >