Skip to content

Commit

Permalink
xfs: dynamically allocate btree scrub context structure
Browse files Browse the repository at this point in the history
Reorganize struct xchk_btree so that we can dynamically size the context
structure to fit the type of btree cursor that we have.  This will
enable us to use memory more efficiently once we start adding very tall
btree types.  Right-size the lastkey array to match the number of *node*
levels in the tree so that we stop wasting space.

Signed-off-by: Darrick J. Wong <[email protected]>
Reviewed-by: Dave Chinner <[email protected]>
  • Loading branch information
Darrick J. Wong committed Oct 19, 2021
1 parent d47fef9 commit eae5db4
Show file tree
Hide file tree
Showing 2 changed files with 26 additions and 12 deletions.
23 changes: 12 additions & 11 deletions fs/xfs/scrub/btree.c
Original file line number Diff line number Diff line change
Expand Up @@ -189,9 +189,9 @@ xchk_btree_key(

/* If this isn't the first key, are they in order? */
if (cur->bc_ptrs[level] > 1 &&
!cur->bc_ops->keys_inorder(cur, &bs->lastkey[level], key))
!cur->bc_ops->keys_inorder(cur, &bs->lastkey[level - 1], key))
xchk_btree_set_corrupt(bs->sc, cur, level);
memcpy(&bs->lastkey[level], key, cur->bc_ops->key_len);
memcpy(&bs->lastkey[level - 1], key, cur->bc_ops->key_len);

if (level + 1 >= cur->bc_nlevels)
return;
Expand Down Expand Up @@ -631,17 +631,24 @@ xchk_btree(
union xfs_btree_ptr *pp;
union xfs_btree_rec *recp;
struct xfs_btree_block *block;
int level;
struct xfs_buf *bp;
struct check_owner *co;
struct check_owner *n;
size_t cur_sz;
int level;
int error = 0;

/*
* Allocate the btree scrub context from the heap, because this
* structure can get rather large.
* structure can get rather large. Don't let a caller feed us a
* totally absurd size.
*/
bs = kmem_zalloc(sizeof(struct xchk_btree), KM_NOFS | KM_MAYFAIL);
cur_sz = xchk_btree_sizeof(cur->bc_nlevels);
if (cur_sz > PAGE_SIZE) {
xchk_btree_set_corrupt(sc, cur, 0);
return 0;
}
bs = kmem_zalloc(cur_sz, KM_NOFS | KM_MAYFAIL);
if (!bs)
return -ENOMEM;
bs->cur = cur;
Expand All @@ -653,12 +660,6 @@ xchk_btree(
/* Initialize scrub state */
INIT_LIST_HEAD(&bs->to_check);

/* Don't try to check a tree with a height we can't handle. */
if (cur->bc_nlevels > XFS_BTREE_MAXLEVELS) {
xchk_btree_set_corrupt(sc, cur, 0);
goto out;
}

/*
* Load the root of the btree. The helper function absorbs
* error codes for us.
Expand Down
15 changes: 14 additions & 1 deletion fs/xfs/scrub/btree.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,22 @@ struct xchk_btree {

/* internal scrub state */
union xfs_btree_rec lastrec;
union xfs_btree_key lastkey[XFS_BTREE_MAXLEVELS];
struct list_head to_check;

/* this element must come last! */
union xfs_btree_key lastkey[];
};

/*
* Calculate the size of a xchk_btree structure. There are nlevels-1 slots for
* keys because we track leaf records separately in lastrec.
*/
static inline size_t
xchk_btree_sizeof(unsigned int nlevels)
{
return struct_size((struct xchk_btree *)NULL, lastkey, nlevels - 1);
}

int xchk_btree(struct xfs_scrub *sc, struct xfs_btree_cur *cur,
xchk_btree_rec_fn scrub_fn, const struct xfs_owner_info *oinfo,
void *private);
Expand Down

0 comments on commit eae5db4

Please sign in to comment.