Loading fs/xfs/libxfs/xfs_attr_leaf.c +22 −0 Original line number Diff line number Diff line Loading @@ -1415,6 +1415,28 @@ xfs_attr3_leaf_create( return 0; } /* * Reinitialize an existing attr fork block as an empty leaf, and attach * the buffer to tp. */ int xfs_attr3_leaf_init( struct xfs_trans *tp, struct xfs_inode *dp, xfs_dablk_t blkno) { struct xfs_buf *bp = NULL; struct xfs_da_args args = { .trans = tp, .dp = dp, .owner = dp->i_ino, .geo = dp->i_mount->m_attr_geo, }; ASSERT(tp != NULL); return xfs_attr3_leaf_create(&args, blkno, &bp); } /* * Split the leaf node, rebalance, then add the new entry. * Loading fs/xfs/libxfs/xfs_attr_leaf.h +3 −0 Original line number Diff line number Diff line Loading @@ -87,6 +87,9 @@ int xfs_attr3_leaf_list_int(struct xfs_buf *bp, /* * Routines used for shrinking the Btree. */ int xfs_attr3_leaf_init(struct xfs_trans *tp, struct xfs_inode *dp, xfs_dablk_t blkno); int xfs_attr3_leaf_toosmall(struct xfs_da_state *state, int *retval); void xfs_attr3_leaf_unbalance(struct xfs_da_state *state, struct xfs_da_state_blk *drop_blk, Loading fs/xfs/libxfs/xfs_da_btree.c +42 −11 Original line number Diff line number Diff line Loading @@ -1506,11 +1506,13 @@ xfs_da3_fixhashpath( } /* * Remove an entry from an intermediate node. * Internal implementation to remove an entry from an intermediate node. */ STATIC void xfs_da3_node_remove( struct xfs_da_state *state, __xfs_da3_node_remove( struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_da_geometry *geo, struct xfs_da_state_blk *drop_blk) { struct xfs_da_intnode *node; Loading @@ -1518,9 +1520,6 @@ xfs_da3_node_remove( struct xfs_da_node_entry *btree; int index; int tmp; struct xfs_inode *dp = state->args->dp; trace_xfs_da_node_remove(state->args); node = drop_blk->bp->b_addr; xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr, node); Loading @@ -1536,17 +1535,17 @@ xfs_da3_node_remove( tmp = nodehdr.count - index - 1; tmp *= (uint)sizeof(xfs_da_node_entry_t); memmove(&btree[index], &btree[index + 1], tmp); xfs_trans_log_buf(state->args->trans, drop_blk->bp, xfs_trans_log_buf(tp, drop_blk->bp, XFS_DA_LOGRANGE(node, &btree[index], tmp)); index = nodehdr.count - 1; } memset(&btree[index], 0, sizeof(xfs_da_node_entry_t)); xfs_trans_log_buf(state->args->trans, drop_blk->bp, xfs_trans_log_buf(tp, drop_blk->bp, XFS_DA_LOGRANGE(node, &btree[index], sizeof(btree[index]))); nodehdr.count -= 1; xfs_da3_node_hdr_to_disk(dp->i_mount, node, &nodehdr); xfs_trans_log_buf(state->args->trans, drop_blk->bp, XFS_DA_LOGRANGE(node, &node->hdr, state->args->geo->node_hdr_size)); xfs_trans_log_buf(tp, drop_blk->bp, XFS_DA_LOGRANGE(node, &node->hdr, geo->node_hdr_size)); /* * Copy the last hash value from the block to propagate upwards. Loading @@ -1554,6 +1553,38 @@ xfs_da3_node_remove( drop_blk->hashval = be32_to_cpu(btree[index - 1].hashval); } /* * Remove an entry from an intermediate node. */ STATIC void xfs_da3_node_remove( struct xfs_da_state *state, struct xfs_da_state_blk *drop_blk) { trace_xfs_da_node_remove(state->args); __xfs_da3_node_remove(state->args->trans, state->args->dp, state->args->geo, drop_blk); } /* * Remove an entry from an intermediate attr node at the specified index. */ void xfs_attr3_node_entry_remove( struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_buf *bp, int index) { struct xfs_da_state_blk blk = { .index = index, .bp = bp, }; __xfs_da3_node_remove(tp, dp, dp->i_mount->m_attr_geo, &blk); } /* * Unbalance the elements between two intermediate nodes, * move all Btree elements from one node into another. Loading fs/xfs/libxfs/xfs_da_btree.h +2 −0 Original line number Diff line number Diff line Loading @@ -184,6 +184,8 @@ int xfs_da3_split(xfs_da_state_t *state); int xfs_da3_join(xfs_da_state_t *state); void xfs_da3_fixhashpath(struct xfs_da_state *state, struct xfs_da_state_path *path_to_to_fix); void xfs_attr3_node_entry_remove(struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_buf *bp, int index); /* * Routines used for finding things in the Btree. Loading fs/xfs/xfs_attr_inactive.c +57 −38 Original line number Diff line number Diff line Loading @@ -140,7 +140,7 @@ xfs_attr3_node_inactive( xfs_daddr_t parent_blkno, child_blkno; struct xfs_buf *child_bp; struct xfs_da3_icnode_hdr ichdr; int error, i; int error; /* * Since this code is recursive (gasp!) we must protect ourselves. Loading @@ -152,7 +152,7 @@ xfs_attr3_node_inactive( return -EFSCORRUPTED; } xfs_da3_node_hdr_from_disk(dp->i_mount, &ichdr, bp->b_addr); xfs_da3_node_hdr_from_disk(mp, &ichdr, bp->b_addr); parent_blkno = xfs_buf_daddr(bp); if (!ichdr.count) { xfs_trans_brelse(*trans, bp); Loading @@ -167,7 +167,7 @@ xfs_attr3_node_inactive( * over the leaves removing all of them. If this is higher up * in the tree, recurse downward. */ for (i = 0; i < ichdr.count; i++) { while (ichdr.count > 0) { /* * Read the subsidiary block to see what we have to work with. * Don't do this in a transaction. This is a depth-first Loading Loading @@ -218,23 +218,25 @@ xfs_attr3_node_inactive( xfs_trans_binval(*trans, child_bp); child_bp = NULL; /* * If we're not done, re-read the parent to get the next * child block number. */ if (i + 1 < ichdr.count) { struct xfs_da3_icnode_hdr phdr; error = xfs_da3_node_read_mapped(*trans, dp, parent_blkno, &bp, XFS_ATTR_FORK); if (error) return error; xfs_da3_node_hdr_from_disk(dp->i_mount, &phdr, bp->b_addr); child_fsb = be32_to_cpu(phdr.btree[i + 1].before); xfs_trans_brelse(*trans, bp); /* * Remove entry from parent node, prevents being indexed to. */ xfs_attr3_node_entry_remove(*trans, dp, bp, 0); xfs_da3_node_hdr_from_disk(mp, &ichdr, bp->b_addr); bp = NULL; } if (ichdr.count > 0) { /* * If we're not done, get the next child block number. */ child_fsb = be32_to_cpu(ichdr.btree[0].before); /* * Atomically commit the whole invalidate stuff. */ Loading @@ -242,6 +244,7 @@ xfs_attr3_node_inactive( if (error) return error; } } return 0; } Loading @@ -257,10 +260,8 @@ xfs_attr3_root_inactive( struct xfs_trans **trans, struct xfs_inode *dp) { struct xfs_mount *mp = dp->i_mount; struct xfs_da_blkinfo *info; struct xfs_buf *bp; xfs_daddr_t blkno; int error; /* Loading @@ -272,7 +273,6 @@ xfs_attr3_root_inactive( error = xfs_da3_node_read(*trans, dp, 0, &bp, XFS_ATTR_FORK); if (error) return error; blkno = xfs_buf_daddr(bp); /* * Invalidate the tree, even if the "tree" is only a single leaf block. Loading @@ -283,10 +283,26 @@ xfs_attr3_root_inactive( case cpu_to_be16(XFS_DA_NODE_MAGIC): case cpu_to_be16(XFS_DA3_NODE_MAGIC): error = xfs_attr3_node_inactive(trans, dp, bp, 1); /* * Empty root node block are not allowed, convert it to leaf. */ if (!error) error = xfs_attr3_leaf_init(*trans, dp, 0); if (!error) error = xfs_trans_roll_inode(trans, dp); break; case cpu_to_be16(XFS_ATTR_LEAF_MAGIC): case cpu_to_be16(XFS_ATTR3_LEAF_MAGIC): error = xfs_attr3_leaf_inactive(trans, dp, bp); /* * Reinit the leaf before truncating extents so that a crash * mid-truncation leaves an empty leaf rather than one with * entries that may reference freed remote value blocks. */ if (!error) error = xfs_attr3_leaf_init(*trans, dp, 0); if (!error) error = xfs_trans_roll_inode(trans, dp); break; default: xfs_dirattr_mark_sick(dp, XFS_ATTR_FORK); Loading @@ -295,21 +311,6 @@ xfs_attr3_root_inactive( xfs_trans_brelse(*trans, bp); break; } if (error) return error; /* * Invalidate the incore copy of the root block. */ error = xfs_trans_get_buf(*trans, mp->m_ddev_targp, blkno, XFS_FSB_TO_BB(mp, mp->m_attr_geo->fsbcount), 0, &bp); if (error) return error; xfs_trans_binval(*trans, bp); /* remove from cache */ /* * Commit the invalidate and start the next transaction. */ error = xfs_trans_roll_inode(trans, dp); return error; } Loading @@ -328,6 +329,7 @@ xfs_attr_inactive( { struct xfs_trans *trans; struct xfs_mount *mp; struct xfs_buf *bp; int lock_mode = XFS_ILOCK_SHARED; int error = 0; Loading Loading @@ -363,10 +365,27 @@ xfs_attr_inactive( * removal below. */ if (dp->i_af.if_nextents > 0) { /* * Invalidate and truncate all blocks but leave the root block. */ error = xfs_attr3_root_inactive(&trans, dp); if (error) goto out_cancel; error = xfs_itruncate_extents(&trans, dp, XFS_ATTR_FORK, XFS_FSB_TO_B(mp, mp->m_attr_geo->fsbcount)); if (error) goto out_cancel; /* * Invalidate and truncate the root block and ensure that the * operation is completed within a single transaction. */ error = xfs_da_get_buf(trans, dp, 0, &bp, XFS_ATTR_FORK); if (error) goto out_cancel; xfs_trans_binval(trans, bp); error = xfs_itruncate_extents(&trans, dp, XFS_ATTR_FORK, 0); if (error) goto out_cancel; Loading Loading
fs/xfs/libxfs/xfs_attr_leaf.c +22 −0 Original line number Diff line number Diff line Loading @@ -1415,6 +1415,28 @@ xfs_attr3_leaf_create( return 0; } /* * Reinitialize an existing attr fork block as an empty leaf, and attach * the buffer to tp. */ int xfs_attr3_leaf_init( struct xfs_trans *tp, struct xfs_inode *dp, xfs_dablk_t blkno) { struct xfs_buf *bp = NULL; struct xfs_da_args args = { .trans = tp, .dp = dp, .owner = dp->i_ino, .geo = dp->i_mount->m_attr_geo, }; ASSERT(tp != NULL); return xfs_attr3_leaf_create(&args, blkno, &bp); } /* * Split the leaf node, rebalance, then add the new entry. * Loading
fs/xfs/libxfs/xfs_attr_leaf.h +3 −0 Original line number Diff line number Diff line Loading @@ -87,6 +87,9 @@ int xfs_attr3_leaf_list_int(struct xfs_buf *bp, /* * Routines used for shrinking the Btree. */ int xfs_attr3_leaf_init(struct xfs_trans *tp, struct xfs_inode *dp, xfs_dablk_t blkno); int xfs_attr3_leaf_toosmall(struct xfs_da_state *state, int *retval); void xfs_attr3_leaf_unbalance(struct xfs_da_state *state, struct xfs_da_state_blk *drop_blk, Loading
fs/xfs/libxfs/xfs_da_btree.c +42 −11 Original line number Diff line number Diff line Loading @@ -1506,11 +1506,13 @@ xfs_da3_fixhashpath( } /* * Remove an entry from an intermediate node. * Internal implementation to remove an entry from an intermediate node. */ STATIC void xfs_da3_node_remove( struct xfs_da_state *state, __xfs_da3_node_remove( struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_da_geometry *geo, struct xfs_da_state_blk *drop_blk) { struct xfs_da_intnode *node; Loading @@ -1518,9 +1520,6 @@ xfs_da3_node_remove( struct xfs_da_node_entry *btree; int index; int tmp; struct xfs_inode *dp = state->args->dp; trace_xfs_da_node_remove(state->args); node = drop_blk->bp->b_addr; xfs_da3_node_hdr_from_disk(dp->i_mount, &nodehdr, node); Loading @@ -1536,17 +1535,17 @@ xfs_da3_node_remove( tmp = nodehdr.count - index - 1; tmp *= (uint)sizeof(xfs_da_node_entry_t); memmove(&btree[index], &btree[index + 1], tmp); xfs_trans_log_buf(state->args->trans, drop_blk->bp, xfs_trans_log_buf(tp, drop_blk->bp, XFS_DA_LOGRANGE(node, &btree[index], tmp)); index = nodehdr.count - 1; } memset(&btree[index], 0, sizeof(xfs_da_node_entry_t)); xfs_trans_log_buf(state->args->trans, drop_blk->bp, xfs_trans_log_buf(tp, drop_blk->bp, XFS_DA_LOGRANGE(node, &btree[index], sizeof(btree[index]))); nodehdr.count -= 1; xfs_da3_node_hdr_to_disk(dp->i_mount, node, &nodehdr); xfs_trans_log_buf(state->args->trans, drop_blk->bp, XFS_DA_LOGRANGE(node, &node->hdr, state->args->geo->node_hdr_size)); xfs_trans_log_buf(tp, drop_blk->bp, XFS_DA_LOGRANGE(node, &node->hdr, geo->node_hdr_size)); /* * Copy the last hash value from the block to propagate upwards. Loading @@ -1554,6 +1553,38 @@ xfs_da3_node_remove( drop_blk->hashval = be32_to_cpu(btree[index - 1].hashval); } /* * Remove an entry from an intermediate node. */ STATIC void xfs_da3_node_remove( struct xfs_da_state *state, struct xfs_da_state_blk *drop_blk) { trace_xfs_da_node_remove(state->args); __xfs_da3_node_remove(state->args->trans, state->args->dp, state->args->geo, drop_blk); } /* * Remove an entry from an intermediate attr node at the specified index. */ void xfs_attr3_node_entry_remove( struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_buf *bp, int index) { struct xfs_da_state_blk blk = { .index = index, .bp = bp, }; __xfs_da3_node_remove(tp, dp, dp->i_mount->m_attr_geo, &blk); } /* * Unbalance the elements between two intermediate nodes, * move all Btree elements from one node into another. Loading
fs/xfs/libxfs/xfs_da_btree.h +2 −0 Original line number Diff line number Diff line Loading @@ -184,6 +184,8 @@ int xfs_da3_split(xfs_da_state_t *state); int xfs_da3_join(xfs_da_state_t *state); void xfs_da3_fixhashpath(struct xfs_da_state *state, struct xfs_da_state_path *path_to_to_fix); void xfs_attr3_node_entry_remove(struct xfs_trans *tp, struct xfs_inode *dp, struct xfs_buf *bp, int index); /* * Routines used for finding things in the Btree. Loading
fs/xfs/xfs_attr_inactive.c +57 −38 Original line number Diff line number Diff line Loading @@ -140,7 +140,7 @@ xfs_attr3_node_inactive( xfs_daddr_t parent_blkno, child_blkno; struct xfs_buf *child_bp; struct xfs_da3_icnode_hdr ichdr; int error, i; int error; /* * Since this code is recursive (gasp!) we must protect ourselves. Loading @@ -152,7 +152,7 @@ xfs_attr3_node_inactive( return -EFSCORRUPTED; } xfs_da3_node_hdr_from_disk(dp->i_mount, &ichdr, bp->b_addr); xfs_da3_node_hdr_from_disk(mp, &ichdr, bp->b_addr); parent_blkno = xfs_buf_daddr(bp); if (!ichdr.count) { xfs_trans_brelse(*trans, bp); Loading @@ -167,7 +167,7 @@ xfs_attr3_node_inactive( * over the leaves removing all of them. If this is higher up * in the tree, recurse downward. */ for (i = 0; i < ichdr.count; i++) { while (ichdr.count > 0) { /* * Read the subsidiary block to see what we have to work with. * Don't do this in a transaction. This is a depth-first Loading Loading @@ -218,23 +218,25 @@ xfs_attr3_node_inactive( xfs_trans_binval(*trans, child_bp); child_bp = NULL; /* * If we're not done, re-read the parent to get the next * child block number. */ if (i + 1 < ichdr.count) { struct xfs_da3_icnode_hdr phdr; error = xfs_da3_node_read_mapped(*trans, dp, parent_blkno, &bp, XFS_ATTR_FORK); if (error) return error; xfs_da3_node_hdr_from_disk(dp->i_mount, &phdr, bp->b_addr); child_fsb = be32_to_cpu(phdr.btree[i + 1].before); xfs_trans_brelse(*trans, bp); /* * Remove entry from parent node, prevents being indexed to. */ xfs_attr3_node_entry_remove(*trans, dp, bp, 0); xfs_da3_node_hdr_from_disk(mp, &ichdr, bp->b_addr); bp = NULL; } if (ichdr.count > 0) { /* * If we're not done, get the next child block number. */ child_fsb = be32_to_cpu(ichdr.btree[0].before); /* * Atomically commit the whole invalidate stuff. */ Loading @@ -242,6 +244,7 @@ xfs_attr3_node_inactive( if (error) return error; } } return 0; } Loading @@ -257,10 +260,8 @@ xfs_attr3_root_inactive( struct xfs_trans **trans, struct xfs_inode *dp) { struct xfs_mount *mp = dp->i_mount; struct xfs_da_blkinfo *info; struct xfs_buf *bp; xfs_daddr_t blkno; int error; /* Loading @@ -272,7 +273,6 @@ xfs_attr3_root_inactive( error = xfs_da3_node_read(*trans, dp, 0, &bp, XFS_ATTR_FORK); if (error) return error; blkno = xfs_buf_daddr(bp); /* * Invalidate the tree, even if the "tree" is only a single leaf block. Loading @@ -283,10 +283,26 @@ xfs_attr3_root_inactive( case cpu_to_be16(XFS_DA_NODE_MAGIC): case cpu_to_be16(XFS_DA3_NODE_MAGIC): error = xfs_attr3_node_inactive(trans, dp, bp, 1); /* * Empty root node block are not allowed, convert it to leaf. */ if (!error) error = xfs_attr3_leaf_init(*trans, dp, 0); if (!error) error = xfs_trans_roll_inode(trans, dp); break; case cpu_to_be16(XFS_ATTR_LEAF_MAGIC): case cpu_to_be16(XFS_ATTR3_LEAF_MAGIC): error = xfs_attr3_leaf_inactive(trans, dp, bp); /* * Reinit the leaf before truncating extents so that a crash * mid-truncation leaves an empty leaf rather than one with * entries that may reference freed remote value blocks. */ if (!error) error = xfs_attr3_leaf_init(*trans, dp, 0); if (!error) error = xfs_trans_roll_inode(trans, dp); break; default: xfs_dirattr_mark_sick(dp, XFS_ATTR_FORK); Loading @@ -295,21 +311,6 @@ xfs_attr3_root_inactive( xfs_trans_brelse(*trans, bp); break; } if (error) return error; /* * Invalidate the incore copy of the root block. */ error = xfs_trans_get_buf(*trans, mp->m_ddev_targp, blkno, XFS_FSB_TO_BB(mp, mp->m_attr_geo->fsbcount), 0, &bp); if (error) return error; xfs_trans_binval(*trans, bp); /* remove from cache */ /* * Commit the invalidate and start the next transaction. */ error = xfs_trans_roll_inode(trans, dp); return error; } Loading @@ -328,6 +329,7 @@ xfs_attr_inactive( { struct xfs_trans *trans; struct xfs_mount *mp; struct xfs_buf *bp; int lock_mode = XFS_ILOCK_SHARED; int error = 0; Loading Loading @@ -363,10 +365,27 @@ xfs_attr_inactive( * removal below. */ if (dp->i_af.if_nextents > 0) { /* * Invalidate and truncate all blocks but leave the root block. */ error = xfs_attr3_root_inactive(&trans, dp); if (error) goto out_cancel; error = xfs_itruncate_extents(&trans, dp, XFS_ATTR_FORK, XFS_FSB_TO_B(mp, mp->m_attr_geo->fsbcount)); if (error) goto out_cancel; /* * Invalidate and truncate the root block and ensure that the * operation is completed within a single transaction. */ error = xfs_da_get_buf(trans, dp, 0, &bp, XFS_ATTR_FORK); if (error) goto out_cancel; xfs_trans_binval(trans, bp); error = xfs_itruncate_extents(&trans, dp, XFS_ATTR_FORK, 0); if (error) goto out_cancel; Loading