|
@@ -204,19 +204,83 @@ xfs_attr_shortform_list(xfs_attr_list_context_t *context)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+/*
|
|
|
+ * We didn't find the block & hash mentioned in the cursor state, so
|
|
|
+ * walk down the attr btree looking for the hash.
|
|
|
+ */
|
|
|
STATIC int
|
|
|
-xfs_attr_node_list(xfs_attr_list_context_t *context)
|
|
|
+xfs_attr_node_list_lookup(
|
|
|
+ struct xfs_attr_list_context *context,
|
|
|
+ struct attrlist_cursor_kern *cursor,
|
|
|
+ struct xfs_buf **pbp)
|
|
|
{
|
|
|
- attrlist_cursor_kern_t *cursor;
|
|
|
- xfs_attr_leafblock_t *leaf;
|
|
|
- xfs_da_intnode_t *node;
|
|
|
- struct xfs_attr3_icleaf_hdr leafhdr;
|
|
|
- struct xfs_da3_icnode_hdr nodehdr;
|
|
|
- struct xfs_da_node_entry *btree;
|
|
|
- int error, i;
|
|
|
- struct xfs_buf *bp;
|
|
|
- struct xfs_inode *dp = context->dp;
|
|
|
- struct xfs_mount *mp = dp->i_mount;
|
|
|
+ struct xfs_da3_icnode_hdr nodehdr;
|
|
|
+ struct xfs_da_intnode *node;
|
|
|
+ struct xfs_da_node_entry *btree;
|
|
|
+ struct xfs_inode *dp = context->dp;
|
|
|
+ struct xfs_mount *mp = dp->i_mount;
|
|
|
+ struct xfs_trans *tp = context->tp;
|
|
|
+ struct xfs_buf *bp;
|
|
|
+ int i;
|
|
|
+ int error = 0;
|
|
|
+ uint16_t magic;
|
|
|
+
|
|
|
+ ASSERT(*pbp == NULL);
|
|
|
+ cursor->blkno = 0;
|
|
|
+ for (;;) {
|
|
|
+ error = xfs_da3_node_read(tp, dp, cursor->blkno, -1, &bp,
|
|
|
+ XFS_ATTR_FORK);
|
|
|
+ if (error)
|
|
|
+ return error;
|
|
|
+ node = bp->b_addr;
|
|
|
+ magic = be16_to_cpu(node->hdr.info.magic);
|
|
|
+ if (magic == XFS_ATTR_LEAF_MAGIC ||
|
|
|
+ magic == XFS_ATTR3_LEAF_MAGIC)
|
|
|
+ break;
|
|
|
+ if (magic != XFS_DA_NODE_MAGIC &&
|
|
|
+ magic != XFS_DA3_NODE_MAGIC) {
|
|
|
+ XFS_CORRUPTION_ERROR(__func__, XFS_ERRLEVEL_LOW, mp,
|
|
|
+ node);
|
|
|
+ goto out_corruptbuf;
|
|
|
+ }
|
|
|
+
|
|
|
+ dp->d_ops->node_hdr_from_disk(&nodehdr, node);
|
|
|
+
|
|
|
+ btree = dp->d_ops->node_tree_p(node);
|
|
|
+ for (i = 0; i < nodehdr.count; btree++, i++) {
|
|
|
+ if (cursor->hashval <= be32_to_cpu(btree->hashval)) {
|
|
|
+ cursor->blkno = be32_to_cpu(btree->before);
|
|
|
+ trace_xfs_attr_list_node_descend(context,
|
|
|
+ btree);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ xfs_trans_brelse(tp, bp);
|
|
|
+
|
|
|
+ if (i == nodehdr.count)
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ *pbp = bp;
|
|
|
+ return 0;
|
|
|
+
|
|
|
+out_corruptbuf:
|
|
|
+ xfs_trans_brelse(tp, bp);
|
|
|
+ return -EFSCORRUPTED;
|
|
|
+}
|
|
|
+
|
|
|
+STATIC int
|
|
|
+xfs_attr_node_list(
|
|
|
+ struct xfs_attr_list_context *context)
|
|
|
+{
|
|
|
+ struct xfs_attr3_icleaf_hdr leafhdr;
|
|
|
+ struct attrlist_cursor_kern *cursor;
|
|
|
+ struct xfs_attr_leafblock *leaf;
|
|
|
+ struct xfs_da_intnode *node;
|
|
|
+ struct xfs_buf *bp;
|
|
|
+ struct xfs_inode *dp = context->dp;
|
|
|
+ struct xfs_mount *mp = dp->i_mount;
|
|
|
+ int error;
|
|
|
|
|
|
trace_xfs_attr_node_list(context);
|
|
|
|
|
@@ -277,47 +341,9 @@ xfs_attr_node_list(xfs_attr_list_context_t *context)
|
|
|
* Note that start of node block is same as start of leaf block.
|
|
|
*/
|
|
|
if (bp == NULL) {
|
|
|
- cursor->blkno = 0;
|
|
|
- for (;;) {
|
|
|
- uint16_t magic;
|
|
|
-
|
|
|
- error = xfs_da3_node_read(context->tp, dp,
|
|
|
- cursor->blkno, -1, &bp,
|
|
|
- XFS_ATTR_FORK);
|
|
|
- if (error)
|
|
|
- return error;
|
|
|
- node = bp->b_addr;
|
|
|
- magic = be16_to_cpu(node->hdr.info.magic);
|
|
|
- if (magic == XFS_ATTR_LEAF_MAGIC ||
|
|
|
- magic == XFS_ATTR3_LEAF_MAGIC)
|
|
|
- break;
|
|
|
- if (magic != XFS_DA_NODE_MAGIC &&
|
|
|
- magic != XFS_DA3_NODE_MAGIC) {
|
|
|
- XFS_CORRUPTION_ERROR("xfs_attr_node_list(3)",
|
|
|
- XFS_ERRLEVEL_LOW,
|
|
|
- context->dp->i_mount,
|
|
|
- node);
|
|
|
- xfs_trans_brelse(context->tp, bp);
|
|
|
- return -EFSCORRUPTED;
|
|
|
- }
|
|
|
-
|
|
|
- dp->d_ops->node_hdr_from_disk(&nodehdr, node);
|
|
|
- btree = dp->d_ops->node_tree_p(node);
|
|
|
- for (i = 0; i < nodehdr.count; btree++, i++) {
|
|
|
- if (cursor->hashval
|
|
|
- <= be32_to_cpu(btree->hashval)) {
|
|
|
- cursor->blkno = be32_to_cpu(btree->before);
|
|
|
- trace_xfs_attr_list_node_descend(context,
|
|
|
- btree);
|
|
|
- break;
|
|
|
- }
|
|
|
- }
|
|
|
- if (i == nodehdr.count) {
|
|
|
- xfs_trans_brelse(context->tp, bp);
|
|
|
- return 0;
|
|
|
- }
|
|
|
- xfs_trans_brelse(context->tp, bp);
|
|
|
- }
|
|
|
+ error = xfs_attr_node_list_lookup(context, cursor, &bp);
|
|
|
+ if (error || !bp)
|
|
|
+ return error;
|
|
|
}
|
|
|
ASSERT(bp != NULL);
|
|
|
|