Skip to content

Commit

Permalink
xfs: add support for refcount btree staging cursors
Browse files Browse the repository at this point in the history
Add support for btree staging cursors for the refcount 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@oracle.com>
Reviewed-by: Brian Foster <bfoster@redhat.com>
  • Loading branch information
Darrick J. Wong committed Mar 18, 2020
1 parent c29ce8f commit 56e9816
Show file tree
Hide file tree
Showing 2 changed files with 66 additions and 10 deletions.
70 changes: 60 additions & 10 deletions fs/xfs/libxfs/xfs_refcount_btree.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "xfs_sb.h"
#include "xfs_mount.h"
#include "xfs_btree.h"
#include "xfs_btree_staging.h"
#include "xfs_refcount_btree.h"
#include "xfs_alloc.h"
#include "xfs_error.h"
Expand Down Expand Up @@ -311,41 +312,90 @@ static const struct xfs_btree_ops xfs_refcountbt_ops = {
};

/*
* Allocate a new refcount btree cursor.
* Initialize a new refcount btree cursor.
*/
struct xfs_btree_cur *
xfs_refcountbt_init_cursor(
static struct xfs_btree_cur *
xfs_refcountbt_init_common(
struct xfs_mount *mp,
struct xfs_trans *tp,
struct xfs_buf *agbp,
xfs_agnumber_t agno)
{
struct xfs_agf *agf = agbp->b_addr;
struct xfs_btree_cur *cur;

ASSERT(agno != NULLAGNUMBER);
ASSERT(agno < mp->m_sb.sb_agcount);
cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_NOFS);

cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_NOFS);
cur->bc_tp = tp;
cur->bc_mp = mp;
cur->bc_btnum = XFS_BTNUM_REFC;
cur->bc_blocklog = mp->m_sb.sb_blocklog;
cur->bc_ops = &xfs_refcountbt_ops;
cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_refcbt_2);

cur->bc_nlevels = be32_to_cpu(agf->agf_refcount_level);

cur->bc_ag.agbp = agbp;
cur->bc_ag.agno = agno;
cur->bc_flags |= XFS_BTREE_CRC_BLOCKS;

cur->bc_ag.refc.nr_ops = 0;
cur->bc_ag.refc.shape_changes = 0;
cur->bc_ops = &xfs_refcountbt_ops;
return cur;
}

/* Create a btree cursor. */
struct xfs_btree_cur *
xfs_refcountbt_init_cursor(
struct xfs_mount *mp,
struct xfs_trans *tp,
struct xfs_buf *agbp,
xfs_agnumber_t agno)
{
struct xfs_agf *agf = agbp->b_addr;
struct xfs_btree_cur *cur;

cur = xfs_refcountbt_init_common(mp, tp, agno);
cur->bc_nlevels = be32_to_cpu(agf->agf_refcount_level);
cur->bc_ag.agbp = agbp;
return cur;
}

/* Create a btree cursor with a fake root for staging. */
struct xfs_btree_cur *
xfs_refcountbt_stage_cursor(
struct xfs_mount *mp,
struct xbtree_afakeroot *afake,
xfs_agnumber_t agno)
{
struct xfs_btree_cur *cur;

cur = xfs_refcountbt_init_common(mp, NULL, agno);
xfs_btree_stage_afakeroot(cur, afake);
return cur;
}

/*
* Swap in the new btree root. Once we pass this point the newly rebuilt btree
* is in place and we have to kill off all the old btree blocks.
*/
void
xfs_refcountbt_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_refcount_root = cpu_to_be32(afake->af_root);
agf->agf_refcount_level = cpu_to_be32(afake->af_levels);
agf->agf_refcount_blocks = cpu_to_be32(afake->af_blocks);
xfs_alloc_log_agf(tp, agbp, XFS_AGF_REFCOUNT_BLOCKS |
XFS_AGF_REFCOUNT_ROOT |
XFS_AGF_REFCOUNT_LEVEL);
xfs_btree_commit_afakeroot(cur, tp, agbp, &xfs_refcountbt_ops);
}

/*
* Calculate the number of records in a refcount btree block.
*/
Expand Down
6 changes: 6 additions & 0 deletions fs/xfs/libxfs/xfs_refcount_btree.h
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
struct xfs_buf;
struct xfs_btree_cur;
struct xfs_mount;
struct xbtree_afakeroot;

/*
* Btree block header size
Expand Down Expand Up @@ -46,6 +47,8 @@ struct xfs_mount;
extern struct xfs_btree_cur *xfs_refcountbt_init_cursor(struct xfs_mount *mp,
struct xfs_trans *tp, struct xfs_buf *agbp,
xfs_agnumber_t agno);
struct xfs_btree_cur *xfs_refcountbt_stage_cursor(struct xfs_mount *mp,
struct xbtree_afakeroot *afake, xfs_agnumber_t agno);
extern int xfs_refcountbt_maxrecs(int blocklen, bool leaf);
extern void xfs_refcountbt_compute_maxlevels(struct xfs_mount *mp);

Expand All @@ -58,4 +61,7 @@ extern int xfs_refcountbt_calc_reserves(struct xfs_mount *mp,
struct xfs_trans *tp, xfs_agnumber_t agno, xfs_extlen_t *ask,
xfs_extlen_t *used);

void xfs_refcountbt_commit_staged_btree(struct xfs_btree_cur *cur,
struct xfs_trans *tp, struct xfs_buf *agbp);

#endif /* __XFS_REFCOUNT_BTREE_H__ */

0 comments on commit 56e9816

Please sign in to comment.