From: Christoph Hellwig <hch@lst.de> Date: Wed, 22 Jan 2020 16:29:41 +0000 (-0500) Subject: xfs: add a btree entries pointer to struct xfs_da3_icnode_hdr X-Git-Tag: v5.5.0-rc0~72 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=8faa51a8d04a090dae7f36ba197ca382b7ecb888;p=users%2Fhch%2Fxfsprogs.git xfs: add a btree entries pointer to struct xfs_da3_icnode_hdr Source kernel commit: 51908ca75feb5b2dd4f0d0146f9c92775520812c All but two callers of the ->node_tree_p dir operation already have a xfs_da3_icnode_hdr from a previous call to xfs_da3_node_hdr_from_disk at hand. Add a pointer to the btree entries to struct xfs_da3_icnode_hdr to clean up this pattern. The two remaining callers now expand the whole header as well, but that isn't very expensive and not in a super hot path anyway. Signed-off-by: Christoph Hellwig <hch@lst.de> Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com> Signed-off-by: Eric Sandeen <sandeen@sandeen.net> --- diff --git a/libxfs/xfs_attr_leaf.c b/libxfs/xfs_attr_leaf.c index 7fd3436c8..b744991a3 100644 --- a/libxfs/xfs_attr_leaf.c +++ b/libxfs/xfs_attr_leaf.c @@ -1141,7 +1141,6 @@ xfs_attr3_leaf_to_node( struct xfs_attr_leafblock *leaf; struct xfs_attr3_icleaf_hdr icleafhdr; struct xfs_attr_leaf_entry *entries; - struct xfs_da_node_entry *btree; struct xfs_da3_icnode_hdr icnodehdr; struct xfs_da_intnode *node; struct xfs_inode *dp = args->dp; @@ -1182,15 +1181,14 @@ xfs_attr3_leaf_to_node( goto out; node = bp1->b_addr; xfs_da3_node_hdr_from_disk(mp, &icnodehdr, node); - btree = dp->d_ops->node_tree_p(node); leaf = bp2->b_addr; xfs_attr3_leaf_hdr_from_disk(args->geo, &icleafhdr, leaf); entries = xfs_attr3_leaf_entryp(leaf); /* both on-disk, don't endian-flip twice */ - btree[0].hashval = entries[icleafhdr.count - 1].hashval; - btree[0].before = cpu_to_be32(blkno); + icnodehdr.btree[0].hashval = entries[icleafhdr.count - 1].hashval; + icnodehdr.btree[0].before = cpu_to_be32(blkno); icnodehdr.count = 1; xfs_da3_node_hdr_to_disk(dp->i_mount, node, &icnodehdr); xfs_trans_log_buf(args->trans, bp1, 0, args->geo->blksize - 1); diff --git a/libxfs/xfs_da_btree.c b/libxfs/xfs_da_btree.c index 15a8218a5..0fc4dabd6 100644 --- a/libxfs/xfs_da_btree.c +++ b/libxfs/xfs_da_btree.c @@ -121,6 +121,7 @@ xfs_da3_node_hdr_from_disk( to->magic = be16_to_cpu(from3->hdr.info.hdr.magic); to->count = be16_to_cpu(from3->hdr.__count); to->level = be16_to_cpu(from3->hdr.__level); + to->btree = from3->__btree; ASSERT(to->magic == XFS_DA3_NODE_MAGIC); } else { to->forw = be32_to_cpu(from->hdr.info.forw); @@ -128,6 +129,7 @@ xfs_da3_node_hdr_from_disk( to->magic = be16_to_cpu(from->hdr.info.magic); to->count = be16_to_cpu(from->hdr.__count); to->level = be16_to_cpu(from->hdr.__level); + to->btree = from->__btree; ASSERT(to->magic == XFS_DA_NODE_MAGIC); } } @@ -624,7 +626,7 @@ xfs_da3_root_split( struct xfs_da3_icnode_hdr icnodehdr; xfs_da3_node_hdr_from_disk(dp->i_mount, &icnodehdr, oldroot); - btree = dp->d_ops->node_tree_p(oldroot); + btree = icnodehdr.btree; size = (int)((char *)&btree[icnodehdr.count] - (char *)oldroot); level = icnodehdr.level; @@ -684,7 +686,7 @@ xfs_da3_root_split( node = bp->b_addr; xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr, node); - btree = dp->d_ops->node_tree_p(node); + btree = nodehdr.btree; btree[0].hashval = cpu_to_be32(blk1->hashval); btree[0].before = cpu_to_be32(blk1->blkno); btree[1].hashval = cpu_to_be32(blk2->hashval); @@ -836,8 +838,8 @@ xfs_da3_node_rebalance( node2 = blk2->bp->b_addr; xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr1, node1); xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr2, node2); - btree1 = dp->d_ops->node_tree_p(node1); - btree2 = dp->d_ops->node_tree_p(node2); + btree1 = nodehdr1.btree; + btree2 = nodehdr2.btree; /* * Figure out how many entries need to move, and in which direction. @@ -852,8 +854,8 @@ xfs_da3_node_rebalance( node2 = tmpnode; xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr1, node1); xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr2, node2); - btree1 = dp->d_ops->node_tree_p(node1); - btree2 = dp->d_ops->node_tree_p(node2); + btree1 = nodehdr1.btree; + btree2 = nodehdr2.btree; swap = 1; } @@ -934,8 +936,8 @@ xfs_da3_node_rebalance( node2 = blk2->bp->b_addr; xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr1, node1); xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr2, node2); - btree1 = dp->d_ops->node_tree_p(node1); - btree2 = dp->d_ops->node_tree_p(node2); + btree1 = nodehdr1.btree; + btree2 = nodehdr2.btree; } blk1->hashval = be32_to_cpu(btree1[nodehdr1.count - 1].hashval); blk2->hashval = be32_to_cpu(btree2[nodehdr2.count - 1].hashval); @@ -968,7 +970,7 @@ xfs_da3_node_add( node = oldblk->bp->b_addr; xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr, node); - btree = dp->d_ops->node_tree_p(node); + btree = nodehdr.btree; ASSERT(oldblk->index >= 0 && oldblk->index <= nodehdr.count); ASSERT(newblk->blkno != 0); @@ -1128,7 +1130,6 @@ xfs_da3_root_join( xfs_dablk_t child; struct xfs_buf *bp; struct xfs_da3_icnode_hdr oldroothdr; - struct xfs_da_node_entry *btree; int error; struct xfs_inode *dp = state->args->dp; @@ -1152,8 +1153,7 @@ xfs_da3_root_join( * Read in the (only) child block, then copy those bytes into * the root block's buffer and free the original child block. */ - btree = dp->d_ops->node_tree_p(oldroot); - child = be32_to_cpu(btree[0].before); + child = be32_to_cpu(oldroothdr.btree[0].before); ASSERT(child != 0); error = xfs_da3_node_read(args->trans, dp, child, -1, &bp, args->whichfork); @@ -1318,18 +1318,14 @@ xfs_da3_node_lasthash( struct xfs_buf *bp, int *count) { - struct xfs_da_intnode *node; - struct xfs_da_node_entry *btree; struct xfs_da3_icnode_hdr nodehdr; - node = bp->b_addr; - xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr, node); + xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr, bp->b_addr); if (count) *count = nodehdr.count; if (!nodehdr.count) return 0; - btree = dp->d_ops->node_tree_p(node); - return be32_to_cpu(btree[nodehdr.count - 1].hashval); + return be32_to_cpu(nodehdr.btree[nodehdr.count - 1].hashval); } /* @@ -1375,7 +1371,7 @@ xfs_da3_fixhashpath( node = blk->bp->b_addr; xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr, node); - btree = dp->d_ops->node_tree_p(node); + btree = nodehdr.btree; if (be32_to_cpu(btree[blk->index].hashval) == lasthash) break; blk->hashval = lasthash; @@ -1414,7 +1410,7 @@ xfs_da3_node_remove( * Copy over the offending entry, or just zero it out. */ index = drop_blk->index; - btree = dp->d_ops->node_tree_p(node); + btree = nodehdr.btree; if (index < nodehdr.count - 1) { tmp = nodehdr.count - index - 1; tmp *= (uint)sizeof(xfs_da_node_entry_t); @@ -1464,8 +1460,8 @@ xfs_da3_node_unbalance( save_node = save_blk->bp->b_addr; xfs_da3_node_hdr_from_disk(dp->i_mount, &drop_hdr, drop_node); xfs_da3_node_hdr_from_disk(dp->i_mount, &save_hdr, save_node); - drop_btree = dp->d_ops->node_tree_p(drop_node); - save_btree = dp->d_ops->node_tree_p(save_node); + drop_btree = drop_hdr.btree; + save_btree = save_hdr.btree; tp = state->args->trans; /* @@ -1599,7 +1595,7 @@ xfs_da3_node_lookup_int( */ node = blk->bp->b_addr; xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr, node); - btree = dp->d_ops->node_tree_p(node); + btree = nodehdr.btree; /* Tree taller than we can handle; bail out! */ if (nodehdr.level >= XFS_DA_NODE_MAXDEPTH) { @@ -1736,8 +1732,8 @@ xfs_da3_node_order( node2 = node2_bp->b_addr; xfs_da3_node_hdr_from_disk(dp->i_mount, &node1hdr, node1); xfs_da3_node_hdr_from_disk(dp->i_mount, &node2hdr, node2); - btree1 = dp->d_ops->node_tree_p(node1); - btree2 = dp->d_ops->node_tree_p(node2); + btree1 = node1hdr.btree; + btree2 = node2hdr.btree; if (node1hdr.count > 0 && node2hdr.count > 0 && ((be32_to_cpu(btree2[0].hashval) < be32_to_cpu(btree1[0].hashval)) || @@ -1934,7 +1930,6 @@ xfs_da3_path_shift( { struct xfs_da_state_blk *blk; struct xfs_da_blkinfo *info; - struct xfs_da_intnode *node; struct xfs_da_args *args; struct xfs_da_node_entry *btree; struct xfs_da3_icnode_hdr nodehdr; @@ -1957,17 +1952,16 @@ xfs_da3_path_shift( ASSERT((path->active > 0) && (path->active < XFS_DA_NODE_MAXDEPTH)); level = (path->active-1) - 1; /* skip bottom layer in path */ for (blk = &path->blk[level]; level >= 0; blk--, level--) { - node = blk->bp->b_addr; - xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr, node); - btree = dp->d_ops->node_tree_p(node); + xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr, + blk->bp->b_addr); if (forward && (blk->index < nodehdr.count - 1)) { blk->index++; - blkno = be32_to_cpu(btree[blk->index].before); + blkno = be32_to_cpu(nodehdr.btree[blk->index].before); break; } else if (!forward && (blk->index > 0)) { blk->index--; - blkno = be32_to_cpu(btree[blk->index].before); + blkno = be32_to_cpu(nodehdr.btree[blk->index].before); break; } } @@ -2018,9 +2012,9 @@ xfs_da3_path_shift( case XFS_DA_NODE_MAGIC: case XFS_DA3_NODE_MAGIC: blk->magic = XFS_DA_NODE_MAGIC; - node = (xfs_da_intnode_t *)info; - xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr, node); - btree = dp->d_ops->node_tree_p(node); + xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr, + bp->b_addr); + btree = nodehdr.btree; blk->hashval = be32_to_cpu(btree[nodehdr.count - 1].hashval); if (forward) blk->index = 0; @@ -2305,7 +2299,7 @@ xfs_da3_swap_lastblock( dead_node = (xfs_da_intnode_t *)dead_info; xfs_da3_node_hdr_from_disk(dp->i_mount, &deadhdr, dead_node); - btree = dp->d_ops->node_tree_p(dead_node); + btree = deadhdr.btree; dead_level = deadhdr.level; dead_hash = be32_to_cpu(btree[deadhdr.count - 1].hashval); } @@ -2372,7 +2366,7 @@ xfs_da3_swap_lastblock( goto done; } level = par_hdr.level; - btree = dp->d_ops->node_tree_p(par_node); + btree = par_hdr.btree; for (entno = 0; entno < par_hdr.count && be32_to_cpu(btree[entno].hashval) < dead_hash; @@ -2422,7 +2416,7 @@ xfs_da3_swap_lastblock( error = -EFSCORRUPTED; goto done; } - btree = dp->d_ops->node_tree_p(par_node); + btree = par_hdr.btree; entno = 0; } /* diff --git a/libxfs/xfs_da_btree.h b/libxfs/xfs_da_btree.h index 932f3ba6a..4955c1fb8 100644 --- a/libxfs/xfs_da_btree.h +++ b/libxfs/xfs_da_btree.h @@ -135,6 +135,12 @@ struct xfs_da3_icnode_hdr { uint16_t magic; uint16_t count; uint16_t level; + + /* + * Pointer to the on-disk format entries, which are behind the + * variable size (v4 vs v5) header in the on-disk block. + */ + struct xfs_da_node_entry *btree; }; /* diff --git a/libxfs/xfs_da_format.c b/libxfs/xfs_da_format.c index dc056f3b9..4e807a4cc 100644 --- a/libxfs/xfs_da_format.c +++ b/libxfs/xfs_da_format.c @@ -494,22 +494,6 @@ xfs_dir3_leaf_hdr_to_disk( hdr3->stale = cpu_to_be16(from->stale); } - -/* - * Directory/Attribute Node block operations - */ -static struct xfs_da_node_entry * -xfs_da2_node_tree_p(struct xfs_da_intnode *dap) -{ - return dap->__btree; -} - -static struct xfs_da_node_entry * -xfs_da3_node_tree_p(struct xfs_da_intnode *dap) -{ - return ((struct xfs_da3_intnode *)dap)->__btree; -} - /* * Directory free space block operations */ @@ -669,7 +653,6 @@ static const struct xfs_dir_ops xfs_dir2_ops = { .leaf_ents_p = xfs_dir2_leaf_ents_p, .node_hdr_size = sizeof(struct xfs_da_node_hdr), - .node_tree_p = xfs_da2_node_tree_p, .free_hdr_size = sizeof(struct xfs_dir2_free_hdr), .free_hdr_to_disk = xfs_dir2_free_hdr_to_disk, @@ -717,7 +700,6 @@ static const struct xfs_dir_ops xfs_dir2_ftype_ops = { .leaf_ents_p = xfs_dir2_leaf_ents_p, .node_hdr_size = sizeof(struct xfs_da_node_hdr), - .node_tree_p = xfs_da2_node_tree_p, .free_hdr_size = sizeof(struct xfs_dir2_free_hdr), .free_hdr_to_disk = xfs_dir2_free_hdr_to_disk, @@ -765,7 +747,6 @@ static const struct xfs_dir_ops xfs_dir3_ops = { .leaf_ents_p = xfs_dir3_leaf_ents_p, .node_hdr_size = sizeof(struct xfs_da3_node_hdr), - .node_tree_p = xfs_da3_node_tree_p, .free_hdr_size = sizeof(struct xfs_dir3_free_hdr), .free_hdr_to_disk = xfs_dir3_free_hdr_to_disk, @@ -778,12 +759,10 @@ static const struct xfs_dir_ops xfs_dir3_ops = { static const struct xfs_dir_ops xfs_dir2_nondir_ops = { .node_hdr_size = sizeof(struct xfs_da_node_hdr), - .node_tree_p = xfs_da2_node_tree_p, }; static const struct xfs_dir_ops xfs_dir3_nondir_ops = { .node_hdr_size = sizeof(struct xfs_da3_node_hdr), - .node_tree_p = xfs_da3_node_tree_p, }; /* diff --git a/libxfs/xfs_dir2.h b/libxfs/xfs_dir2.h index c16efeae0..6eee4c1b2 100644 --- a/libxfs/xfs_dir2.h +++ b/libxfs/xfs_dir2.h @@ -82,8 +82,6 @@ struct xfs_dir_ops { (*leaf_ents_p)(struct xfs_dir2_leaf *lp); int node_hdr_size; - struct xfs_da_node_entry * - (*node_tree_p)(struct xfs_da_intnode *dap); int free_hdr_size; void (*free_hdr_to_disk)(struct xfs_dir2_free *to, diff --git a/repair/da_util.c b/repair/da_util.c index 1e56670d8..bf25f7f2a 100644 --- a/repair/da_util.c +++ b/repair/da_util.c @@ -93,7 +93,6 @@ traverse_int_dablock( xfs_da_intnode_t *node; bmap_ext_t lbmp; struct xfs_da_geometry *geo; - struct xfs_da_node_entry *btree; struct xfs_da3_icnode_hdr nodehdr; if (whichfork == XFS_DATA_FORK) { @@ -169,7 +168,6 @@ _("corrupt %s tree block %u for inode %" PRIu64 "\n"), goto error_out; } - btree = M_DIROPS(mp)->node_tree_p(node); if (nodehdr.count > geo->node_ents) { do_warn( _("bad %s record count in inode %" PRIu64 ", count = %d, max = %d\n"), @@ -204,7 +202,8 @@ _("bad %s btree for inode %" PRIu64 "\n"), } } - da_cursor->level[i].hashval = be32_to_cpu(btree[0].hashval); + da_cursor->level[i].hashval = + be32_to_cpu(nodehdr.btree[0].hashval); da_cursor->level[i].bp = bp; da_cursor->level[i].bno = bno; da_cursor->level[i].index = 0; @@ -212,7 +211,7 @@ _("bad %s btree for inode %" PRIu64 "\n"), /* * set up new bno for next level down */ - bno = be32_to_cpu(btree[0].before); + bno = be32_to_cpu(nodehdr.btree[0].before); } while (node != NULL && i > 1); /* @@ -301,7 +300,6 @@ verify_final_da_path( int bad = 0; int entry; int this_level = p_level + 1; - struct xfs_da_node_entry *btree; struct xfs_da3_icnode_hdr nodehdr; #ifdef XR_DIR_TRACE @@ -315,7 +313,6 @@ verify_final_da_path( */ entry = cursor->level[this_level].index; node = cursor->level[this_level].bp->b_addr; - btree = M_DIROPS(mp)->node_tree_p(node); libxfs_da3_node_hdr_from_disk(mp, &nodehdr, node); /* @@ -333,12 +330,12 @@ _("%s block used/count inconsistency - %d/%hu\n"), * hash values monotonically increasing ??? */ if (cursor->level[this_level].hashval >= - be32_to_cpu(btree[entry].hashval)) { + be32_to_cpu(nodehdr.btree[entry].hashval)) { do_warn( _("%s block hashvalue inconsistency, expected > %u / saw %u\n"), FORKNAME(whichfork), cursor->level[this_level].hashval, - be32_to_cpu(btree[entry].hashval)); + be32_to_cpu(nodehdr.btree[entry].hashval)); bad++; } if (nodehdr.forw != 0) { @@ -362,11 +359,13 @@ _("bad %s forward block pointer, expected 0, saw %u\n"), /* * ok, now check descendant block number against this level */ - if (cursor->level[p_level].bno != be32_to_cpu(btree[entry].before)) { + if (cursor->level[p_level].bno != + be32_to_cpu(nodehdr.btree[entry].before)) { #ifdef XR_DIR_TRACE fprintf(stderr, "bad %s btree pointer, child bno should " "be %d, block bno is %d, hashval is %u\n", - FORKNAME(whichfork), be16_to_cpu(btree[entry].before), + FORKNAME(whichfork), + be16_to_cpu(nodehdr.btree[entry].before), cursor->level[p_level].bno, cursor->level[p_level].hashval); fprintf(stderr, "verify_final_da_path returns 1 (bad) #1a\n"); @@ -375,13 +374,13 @@ _("bad %s forward block pointer, expected 0, saw %u\n"), } if (cursor->level[p_level].hashval != - be32_to_cpu(btree[entry].hashval)) { + be32_to_cpu(nodehdr.btree[entry].hashval)) { if (!no_modify) { do_warn( _("correcting bad hashval in non-leaf %s block\n" "\tin (level %d) in inode %" PRIu64 ".\n"), FORKNAME(whichfork), this_level, cursor->ino); - btree[entry].hashval = cpu_to_be32( + nodehdr.btree[entry].hashval = cpu_to_be32( cursor->level[p_level].hashval); cursor->level[this_level].dirty++; } else { @@ -396,7 +395,7 @@ _("would correct bad hashval in non-leaf %s block\n" * Note: squirrel hashval away _before_ releasing the * buffer, preventing a use-after-free problem. */ - hashval = be32_to_cpu(btree[entry].hashval); + hashval = be32_to_cpu(nodehdr.btree[entry].hashval); /* * release/write buffer @@ -486,7 +485,6 @@ verify_da_path( int nex; bmap_ext_t lbmp; struct xfs_da_geometry *geo; - struct xfs_da_node_entry *btree; struct xfs_da3_icnode_hdr nodehdr; if (whichfork == XFS_DATA_FORK) @@ -504,7 +502,6 @@ verify_da_path( */ entry = cursor->level[this_level].index; node = cursor->level[this_level].bp->b_addr; - btree = M_DIROPS(mp)->node_tree_p(node); libxfs_da3_node_hdr_from_disk(mp, &nodehdr, node); /* No entries in this node? Tree is corrupt. */ @@ -523,7 +520,7 @@ verify_da_path( * it was set when the block was first read in. */ cursor->level[this_level].hashval = - be32_to_cpu(btree[entry - 1].hashval); + be32_to_cpu(nodehdr.btree[entry - 1].hashval); /* * keep track of greatest block # -- that gets @@ -564,7 +561,6 @@ _("can't read %s block %u for inode %" PRIu64 "\n"), } newnode = bp->b_addr; - btree = M_DIROPS(mp)->node_tree_p(newnode); libxfs_da3_node_hdr_from_disk(mp, &nodehdr, newnode); /* @@ -633,18 +629,20 @@ _("bad level %d in %s block %u for inode %" PRIu64 "\n"), cursor->level[this_level].dirty = 0; cursor->level[this_level].bno = dabno; cursor->level[this_level].hashval = - be32_to_cpu(btree[0].hashval); + be32_to_cpu(nodehdr.btree[0].hashval); entry = cursor->level[this_level].index = 0; } /* * ditto for block numbers */ - if (cursor->level[p_level].bno != be32_to_cpu(btree[entry].before)) { + if (cursor->level[p_level].bno != + be32_to_cpu(nodehdr.btree[entry].before)) { #ifdef XR_DIR_TRACE fprintf(stderr, "bad %s btree pointer, child bno " "should be %d, block bno is %d, hashval is %u\n", - FORKNAME(whichfork), be32_to_cpu(btree[entry].before), + FORKNAME(whichfork), + be32_to_cpu(nodehdr.btree[entry].before), cursor->level[p_level].bno, cursor->level[p_level].hashval); fprintf(stderr, "verify_da_path returns 1 (bad) #1a\n"); @@ -656,13 +654,13 @@ _("bad level %d in %s block %u for inode %" PRIu64 "\n"), * block against the hashval in the current entry */ if (cursor->level[p_level].hashval != - be32_to_cpu(btree[entry].hashval)) { + be32_to_cpu(nodehdr.btree[entry].hashval)) { if (!no_modify) { do_warn( _("correcting bad hashval in interior %s block\n" "\tin (level %d) in inode %" PRIu64 ".\n"), FORKNAME(whichfork), this_level, cursor->ino); - btree[entry].hashval = cpu_to_be32( + nodehdr.btree[entry].hashval = cpu_to_be32( cursor->level[p_level].hashval); cursor->level[this_level].dirty++; } else {