Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 28a89567 authored by Darrick J. Wong's avatar Darrick J. Wong Committed by Dave Chinner
Browse files

xfs: refactor btree owner change into a separate visit-blocks function



Refactor the btree_change_owner function into a more generic apparatus
which visits all blocks in a btree.  We'll use this in a subsequent
patch for counting btree blocks for AG reservations.

Signed-off-by: default avatarDarrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: default avatarBrian Foster <bfoster@redhat.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarDave Chinner <david@fromorbit.com>
parent 105f7d83
Loading
Loading
Loading
Loading
+91 −50
Original line number Diff line number Diff line
@@ -4328,6 +4328,81 @@ xfs_btree_get_rec(
	return 0;
}

/* Visit a block in a btree. */
STATIC int
xfs_btree_visit_block(
	struct xfs_btree_cur		*cur,
	int				level,
	xfs_btree_visit_blocks_fn	fn,
	void				*data)
{
	struct xfs_btree_block		*block;
	struct xfs_buf			*bp;
	union xfs_btree_ptr		rptr;
	int				error;

	/* do right sibling readahead */
	xfs_btree_readahead(cur, level, XFS_BTCUR_RIGHTRA);
	block = xfs_btree_get_block(cur, level, &bp);

	/* process the block */
	error = fn(cur, level, data);
	if (error)
		return error;

	/* now read rh sibling block for next iteration */
	xfs_btree_get_sibling(cur, block, &rptr, XFS_BB_RIGHTSIB);
	if (xfs_btree_ptr_is_null(cur, &rptr))
		return -ENOENT;

	return xfs_btree_lookup_get_block(cur, level, &rptr, &block);
}


/* Visit every block in a btree. */
int
xfs_btree_visit_blocks(
	struct xfs_btree_cur		*cur,
	xfs_btree_visit_blocks_fn	fn,
	void				*data)
{
	union xfs_btree_ptr		lptr;
	int				level;
	struct xfs_btree_block		*block = NULL;
	int				error = 0;

	cur->bc_ops->init_ptr_from_cur(cur, &lptr);

	/* for each level */
	for (level = cur->bc_nlevels - 1; level >= 0; level--) {
		/* grab the left hand block */
		error = xfs_btree_lookup_get_block(cur, level, &lptr, &block);
		if (error)
			return error;

		/* readahead the left most block for the next level down */
		if (level > 0) {
			union xfs_btree_ptr     *ptr;

			ptr = xfs_btree_ptr_addr(cur, 1, block);
			xfs_btree_readahead_ptr(cur, ptr, 1);

			/* save for the next iteration of the loop */
			lptr = *ptr;
		}

		/* for each buffer in the level */
		do {
			error = xfs_btree_visit_block(cur, level, fn, data);
		} while (!error);

		if (error != -ENOENT)
			return error;
	}

	return 0;
}

/*
 * Change the owner of a btree.
 *
@@ -4352,26 +4427,27 @@ xfs_btree_get_rec(
 * just queue the modified buffer as delayed write buffer so the transaction
 * recovery completion writes the changes to disk.
 */
struct xfs_btree_block_change_owner_info {
	__uint64_t		new_owner;
	struct list_head	*buffer_list;
};

static int
xfs_btree_block_change_owner(
	struct xfs_btree_cur	*cur,
	int			level,
	__uint64_t		new_owner,
	struct list_head	*buffer_list)
	void			*data)
{
	struct xfs_btree_block_change_owner_info	*bbcoi = data;
	struct xfs_btree_block	*block;
	struct xfs_buf		*bp;
	union xfs_btree_ptr     rptr;

	/* do right sibling readahead */
	xfs_btree_readahead(cur, level, XFS_BTCUR_RIGHTRA);

	/* modify the owner */
	block = xfs_btree_get_block(cur, level, &bp);
	if (cur->bc_flags & XFS_BTREE_LONG_PTRS)
		block->bb_u.l.bb_owner = cpu_to_be64(new_owner);
		block->bb_u.l.bb_owner = cpu_to_be64(bbcoi->new_owner);
	else
		block->bb_u.s.bb_owner = cpu_to_be32(new_owner);
		block->bb_u.s.bb_owner = cpu_to_be32(bbcoi->new_owner);

	/*
	 * If the block is a root block hosted in an inode, we might not have a
@@ -4385,19 +4461,14 @@ xfs_btree_block_change_owner(
			xfs_trans_ordered_buf(cur->bc_tp, bp);
			xfs_btree_log_block(cur, bp, XFS_BB_OWNER);
		} else {
			xfs_buf_delwri_queue(bp, buffer_list);
			xfs_buf_delwri_queue(bp, bbcoi->buffer_list);
		}
	} else {
		ASSERT(cur->bc_flags & XFS_BTREE_ROOT_IN_INODE);
		ASSERT(level == cur->bc_nlevels - 1);
	}

	/* now read rh sibling block for next iteration */
	xfs_btree_get_sibling(cur, block, &rptr, XFS_BB_RIGHTSIB);
	if (xfs_btree_ptr_is_null(cur, &rptr))
		return -ENOENT;

	return xfs_btree_lookup_get_block(cur, level, &rptr, &block);
	return 0;
}

int
@@ -4406,43 +4477,13 @@ xfs_btree_change_owner(
	__uint64_t		new_owner,
	struct list_head	*buffer_list)
{
	union xfs_btree_ptr     lptr;
	int			level;
	struct xfs_btree_block	*block = NULL;
	int			error = 0;
	struct xfs_btree_block_change_owner_info	bbcoi;

	cur->bc_ops->init_ptr_from_cur(cur, &lptr);
	bbcoi.new_owner = new_owner;
	bbcoi.buffer_list = buffer_list;

	/* for each level */
	for (level = cur->bc_nlevels - 1; level >= 0; level--) {
		/* grab the left hand block */
		error = xfs_btree_lookup_get_block(cur, level, &lptr, &block);
		if (error)
			return error;

		/* readahead the left most block for the next level down */
		if (level > 0) {
			union xfs_btree_ptr     *ptr;

			ptr = xfs_btree_ptr_addr(cur, 1, block);
			xfs_btree_readahead_ptr(cur, ptr, 1);

			/* save for the next iteration of the loop */
			lptr = *ptr;
		}

		/* for each buffer in the level */
		do {
			error = xfs_btree_block_change_owner(cur, level,
							     new_owner,
							     buffer_list);
		} while (!error);

		if (error != -ENOENT)
			return error;
	}

	return 0;
	return xfs_btree_visit_blocks(cur, xfs_btree_block_change_owner,
			&bbcoi);
}

/**
+5 −0
Original line number Diff line number Diff line
@@ -536,4 +536,9 @@ int xfs_btree_query_range(struct xfs_btree_cur *cur,
		union xfs_btree_irec *low_rec, union xfs_btree_irec *high_rec,
		xfs_btree_query_range_fn fn, void *priv);

typedef int (*xfs_btree_visit_blocks_fn)(struct xfs_btree_cur *cur, int level,
		void *data);
int xfs_btree_visit_blocks(struct xfs_btree_cur *cur,
		xfs_btree_visit_blocks_fn fn, void *data);

#endif	/* __XFS_BTREE_H__ */