Skip to content

Commit

Permalink
xfs: add support for inode btree staging cursors
Browse files Browse the repository at this point in the history
Add support for btree staging cursors for the inode 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 <[email protected]>
Reviewed-by: Brian Foster <[email protected]>
  • Loading branch information
djwong committed Mar 18, 2020
1 parent e6eb33d commit c29ce8f
Show file tree
Hide file tree
Showing 2 changed files with 76 additions and 12 deletions.
82 changes: 70 additions & 12 deletions fs/xfs/libxfs/xfs_ialloc_btree.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include "xfs_bit.h"
#include "xfs_mount.h"
#include "xfs_btree.h"
#include "xfs_btree_staging.h"
#include "xfs_ialloc.h"
#include "xfs_ialloc_btree.h"
#include "xfs_alloc.h"
Expand All @@ -20,7 +21,6 @@
#include "xfs_trans.h"
#include "xfs_rmap.h"


STATIC int
xfs_inobt_get_minrecs(
struct xfs_btree_cur *cur,
Expand Down Expand Up @@ -400,45 +400,103 @@ static const struct xfs_btree_ops xfs_finobt_ops = {
};

/*
* Allocate a new inode btree cursor.
* Initialize a new inode btree cursor.
*/
struct xfs_btree_cur * /* new inode btree cursor */
xfs_inobt_init_cursor(
static struct xfs_btree_cur *
xfs_inobt_init_common(
struct xfs_mount *mp, /* file system mount point */
struct xfs_trans *tp, /* transaction pointer */
struct xfs_buf *agbp, /* buffer for agi structure */
xfs_agnumber_t agno, /* allocation group number */
xfs_btnum_t btnum) /* ialloc or free ino btree */
{
struct xfs_agi *agi = agbp->b_addr;
struct xfs_btree_cur *cur;

cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_NOFS);

cur->bc_tp = tp;
cur->bc_mp = mp;
cur->bc_btnum = btnum;
if (btnum == XFS_BTNUM_INO) {
cur->bc_nlevels = be32_to_cpu(agi->agi_level);
cur->bc_ops = &xfs_inobt_ops;
cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_ibt_2);
cur->bc_ops = &xfs_inobt_ops;
} else {
cur->bc_nlevels = be32_to_cpu(agi->agi_free_level);
cur->bc_ops = &xfs_finobt_ops;
cur->bc_statoff = XFS_STATS_CALC_INDEX(xs_fibt_2);
cur->bc_ops = &xfs_finobt_ops;
}

cur->bc_blocklog = mp->m_sb.sb_blocklog;

if (xfs_sb_version_hascrc(&mp->m_sb))
cur->bc_flags |= XFS_BTREE_CRC_BLOCKS;

cur->bc_ag.agbp = agbp;
cur->bc_ag.agno = agno;
return cur;
}

/* Create an inode btree cursor. */
struct xfs_btree_cur *
xfs_inobt_init_cursor(
struct xfs_mount *mp,
struct xfs_trans *tp,
struct xfs_buf *agbp,
xfs_agnumber_t agno,
xfs_btnum_t btnum)
{
struct xfs_btree_cur *cur;
struct xfs_agi *agi = agbp->b_addr;

cur = xfs_inobt_init_common(mp, tp, agno, btnum);
if (btnum == XFS_BTNUM_INO)
cur->bc_nlevels = be32_to_cpu(agi->agi_level);
else
cur->bc_nlevels = be32_to_cpu(agi->agi_free_level);
cur->bc_ag.agbp = agbp;
return cur;
}

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

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

/*
* Install a new inobt btree root. Caller is responsible for invalidating
* and freeing the old btree blocks.
*/
void
xfs_inobt_commit_staged_btree(
struct xfs_btree_cur *cur,
struct xfs_trans *tp,
struct xfs_buf *agbp)
{
struct xfs_agi *agi = agbp->b_addr;
struct xbtree_afakeroot *afake = cur->bc_ag.afake;

ASSERT(cur->bc_flags & XFS_BTREE_STAGING);

if (cur->bc_btnum == XFS_BTNUM_INO) {
agi->agi_root = cpu_to_be32(afake->af_root);
agi->agi_level = cpu_to_be32(afake->af_levels);
xfs_ialloc_log_agi(tp, agbp, XFS_AGI_ROOT | XFS_AGI_LEVEL);
xfs_btree_commit_afakeroot(cur, tp, agbp, &xfs_inobt_ops);
} else {
agi->agi_free_root = cpu_to_be32(afake->af_root);
agi->agi_free_level = cpu_to_be32(afake->af_levels);
xfs_ialloc_log_agi(tp, agbp, XFS_AGI_FREE_ROOT |
XFS_AGI_FREE_LEVEL);
xfs_btree_commit_afakeroot(cur, tp, agbp, &xfs_finobt_ops);
}
}

/*
* Calculate number of records in an inobt btree block.
*/
Expand Down
6 changes: 6 additions & 0 deletions fs/xfs/libxfs/xfs_ialloc_btree.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,9 @@ struct xfs_mount;
extern struct xfs_btree_cur *xfs_inobt_init_cursor(struct xfs_mount *,
struct xfs_trans *, struct xfs_buf *, xfs_agnumber_t,
xfs_btnum_t);
struct xfs_btree_cur *xfs_inobt_stage_cursor(struct xfs_mount *mp,
struct xbtree_afakeroot *afake, xfs_agnumber_t agno,
xfs_btnum_t btnum);
extern int xfs_inobt_maxrecs(struct xfs_mount *, int, int);

/* ir_holemask to inode allocation bitmap conversion */
Expand All @@ -68,4 +71,7 @@ int xfs_inobt_cur(struct xfs_mount *mp, struct xfs_trans *tp,
xfs_agnumber_t agno, xfs_btnum_t btnum,
struct xfs_btree_cur **curpp, struct xfs_buf **agi_bpp);

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

#endif /* __XFS_IALLOC_BTREE_H__ */

0 comments on commit c29ce8f

Please sign in to comment.