aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_da_btree.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/xfs/xfs_da_btree.c')
-rw-r--r--fs/xfs/xfs_da_btree.c33
1 files changed, 18 insertions, 15 deletions
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c
index 32ab61d17ace..a68bc1f1a313 100644
--- a/fs/xfs/xfs_da_btree.c
+++ b/fs/xfs/xfs_da_btree.c
@@ -1054,7 +1054,7 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result)
1054 xfs_da_node_entry_t *btree; 1054 xfs_da_node_entry_t *btree;
1055 xfs_dablk_t blkno; 1055 xfs_dablk_t blkno;
1056 int probe, span, max, error, retval; 1056 int probe, span, max, error, retval;
1057 xfs_dahash_t hashval; 1057 xfs_dahash_t hashval, btreehashval;
1058 xfs_da_args_t *args; 1058 xfs_da_args_t *args;
1059 1059
1060 args = state->args; 1060 args = state->args;
@@ -1079,30 +1079,32 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result)
1079 return(error); 1079 return(error);
1080 } 1080 }
1081 curr = blk->bp->data; 1081 curr = blk->bp->data;
1082 ASSERT(be16_to_cpu(curr->magic) == XFS_DA_NODE_MAGIC || 1082 blk->magic = be16_to_cpu(curr->magic);
1083 be16_to_cpu(curr->magic) == XFS_DIR2_LEAFN_MAGIC || 1083 ASSERT(blk->magic == XFS_DA_NODE_MAGIC ||
1084 be16_to_cpu(curr->magic) == XFS_ATTR_LEAF_MAGIC); 1084 blk->magic == XFS_DIR2_LEAFN_MAGIC ||
1085 blk->magic == XFS_ATTR_LEAF_MAGIC);
1085 1086
1086 /* 1087 /*
1087 * Search an intermediate node for a match. 1088 * Search an intermediate node for a match.
1088 */ 1089 */
1089 blk->magic = be16_to_cpu(curr->magic);
1090 if (blk->magic == XFS_DA_NODE_MAGIC) { 1090 if (blk->magic == XFS_DA_NODE_MAGIC) {
1091 node = blk->bp->data; 1091 node = blk->bp->data;
1092 blk->hashval = be32_to_cpu(node->btree[be16_to_cpu(node->hdr.count)-1].hashval); 1092 max = be16_to_cpu(node->hdr.count);
1093 btreehashval = node->btree[max-1].hashval;
1094 blk->hashval = be32_to_cpu(btreehashval);
1093 1095
1094 /* 1096 /*
1095 * Binary search. (note: small blocks will skip loop) 1097 * Binary search. (note: small blocks will skip loop)
1096 */ 1098 */
1097 max = be16_to_cpu(node->hdr.count);
1098 probe = span = max / 2; 1099 probe = span = max / 2;
1099 hashval = args->hashval; 1100 hashval = args->hashval;
1100 for (btree = &node->btree[probe]; span > 4; 1101 for (btree = &node->btree[probe]; span > 4;
1101 btree = &node->btree[probe]) { 1102 btree = &node->btree[probe]) {
1102 span /= 2; 1103 span /= 2;
1103 if (be32_to_cpu(btree->hashval) < hashval) 1104 btreehashval = be32_to_cpu(btree->hashval);
1105 if (btreehashval < hashval)
1104 probe += span; 1106 probe += span;
1105 else if (be32_to_cpu(btree->hashval) > hashval) 1107 else if (btreehashval > hashval)
1106 probe -= span; 1108 probe -= span;
1107 else 1109 else
1108 break; 1110 break;
@@ -1133,10 +1135,10 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result)
1133 blk->index = probe; 1135 blk->index = probe;
1134 blkno = be32_to_cpu(btree->before); 1136 blkno = be32_to_cpu(btree->before);
1135 } 1137 }
1136 } else if (be16_to_cpu(curr->magic) == XFS_ATTR_LEAF_MAGIC) { 1138 } else if (blk->magic == XFS_ATTR_LEAF_MAGIC) {
1137 blk->hashval = xfs_attr_leaf_lasthash(blk->bp, NULL); 1139 blk->hashval = xfs_attr_leaf_lasthash(blk->bp, NULL);
1138 break; 1140 break;
1139 } else if (be16_to_cpu(curr->magic) == XFS_DIR2_LEAFN_MAGIC) { 1141 } else if (blk->magic == XFS_DIR2_LEAFN_MAGIC) {
1140 blk->hashval = xfs_dir2_leafn_lasthash(blk->bp, NULL); 1142 blk->hashval = xfs_dir2_leafn_lasthash(blk->bp, NULL);
1141 break; 1143 break;
1142 } 1144 }
@@ -1152,11 +1154,13 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result)
1152 if (blk->magic == XFS_DIR2_LEAFN_MAGIC) { 1154 if (blk->magic == XFS_DIR2_LEAFN_MAGIC) {
1153 retval = xfs_dir2_leafn_lookup_int(blk->bp, args, 1155 retval = xfs_dir2_leafn_lookup_int(blk->bp, args,
1154 &blk->index, state); 1156 &blk->index, state);
1155 } 1157 } else if (blk->magic == XFS_ATTR_LEAF_MAGIC) {
1156 else if (blk->magic == XFS_ATTR_LEAF_MAGIC) {
1157 retval = xfs_attr_leaf_lookup_int(blk->bp, args); 1158 retval = xfs_attr_leaf_lookup_int(blk->bp, args);
1158 blk->index = args->index; 1159 blk->index = args->index;
1159 args->blkno = blk->blkno; 1160 args->blkno = blk->blkno;
1161 } else {
1162 ASSERT(0);
1163 return XFS_ERROR(EFSCORRUPTED);
1160 } 1164 }
1161 if (((retval == ENOENT) || (retval == ENOATTR)) && 1165 if (((retval == ENOENT) || (retval == ENOATTR)) &&
1162 (blk->hashval == args->hashval)) { 1166 (blk->hashval == args->hashval)) {
@@ -1166,8 +1170,7 @@ xfs_da_node_lookup_int(xfs_da_state_t *state, int *result)
1166 return(error); 1170 return(error);
1167 if (retval == 0) { 1171 if (retval == 0) {
1168 continue; 1172 continue;
1169 } 1173 } else if (blk->magic == XFS_ATTR_LEAF_MAGIC) {
1170 else if (blk->magic == XFS_ATTR_LEAF_MAGIC) {
1171 /* path_shift() gives ENOENT */ 1174 /* path_shift() gives ENOENT */
1172 retval = XFS_ERROR(ENOATTR); 1175 retval = XFS_ERROR(ENOATTR);
1173 } 1176 }