diff mbox

[015/119] xfs: refactor btree owner change into a separate visit-blocks function

Message ID 146612636805.12839.15108503251791000478.stgit@birch.djwong.org (mailing list archive)
State New, archived
Headers show

Commit Message

Darrick J. Wong June 17, 2016, 1:19 a.m. UTC
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: Darrick J. Wong <darrick.wong@oracle.com>
---
 fs/xfs/libxfs/xfs_btree.c |  141 +++++++++++++++++++++++++++++----------------
 fs/xfs/libxfs/xfs_btree.h |    5 ++
 2 files changed, 96 insertions(+), 50 deletions(-)



--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Comments

Brian Foster June 23, 2016, 5:19 p.m. UTC | #1
On Thu, Jun 16, 2016 at 06:19:28PM -0700, Darrick J. Wong wrote:
> 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: Darrick J. Wong <darrick.wong@oracle.com>
> ---

Reviewed-by: Brian Foster <bfoster@redhat.com>

>  fs/xfs/libxfs/xfs_btree.c |  141 +++++++++++++++++++++++++++++----------------
>  fs/xfs/libxfs/xfs_btree.h |    5 ++
>  2 files changed, 96 insertions(+), 50 deletions(-)
> 
> 
> diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c
> index 5f5cf23..eac876a 100644
> --- a/fs/xfs/libxfs/xfs_btree.c
> +++ b/fs/xfs/libxfs/xfs_btree.c
> @@ -4289,6 +4289,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.
>   *
> @@ -4313,26 +4388,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
> @@ -4346,19 +4422,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
> @@ -4367,43 +4438,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);
>  }
>  
>  /**
> diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h
> index 898fee5..0ec3055 100644
> --- a/fs/xfs/libxfs/xfs_btree.h
> +++ b/fs/xfs/libxfs/xfs_btree.h
> @@ -506,4 +506,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__ */
> 
> _______________________________________________
> xfs mailing list
> xfs@oss.sgi.com
> http://oss.sgi.com/mailman/listinfo/xfs
--
To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/fs/xfs/libxfs/xfs_btree.c b/fs/xfs/libxfs/xfs_btree.c
index 5f5cf23..eac876a 100644
--- a/fs/xfs/libxfs/xfs_btree.c
+++ b/fs/xfs/libxfs/xfs_btree.c
@@ -4289,6 +4289,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.
  *
@@ -4313,26 +4388,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
@@ -4346,19 +4422,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
@@ -4367,43 +4438,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);
 }
 
 /**
diff --git a/fs/xfs/libxfs/xfs_btree.h b/fs/xfs/libxfs/xfs_btree.h
index 898fee5..0ec3055 100644
--- a/fs/xfs/libxfs/xfs_btree.h
+++ b/fs/xfs/libxfs/xfs_btree.h
@@ -506,4 +506,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__ */