xfs: refactor btree owner change into a separate visit-blocks function
authorDarrick J. Wong <darrick.wong@oracle.com>
Wed, 3 Aug 2016 01:10:55 +0000 (11:10 +1000)
committerDave Chinner <david@fromorbit.com>
Wed, 3 Aug 2016 01:10:55 +0000 (11:10 +1000)
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>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Dave Chinner <david@fromorbit.com>
fs/xfs/libxfs/xfs_btree.c
fs/xfs/libxfs/xfs_btree.h

index d79dcb08ed1845385fa5bf02b4a3ebf425f8b569..b5be7f41c856eeebf0396afc4d1a05c0a743aaa0 100644 (file)
@@ -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);
 }
 
 /**
index 34c13616d255b87ca8a687e0f4bda1dbd35a18d6..69f564029f56b18d177ea75053147884d821aaa1 100644 (file)
@@ -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__ */