summaryrefslogtreecommitdiffstats
path: root/lib/radix-tree.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/radix-tree.c')
-rw-r--r--lib/radix-tree.c138
1 files changed, 121 insertions, 17 deletions
diff --git a/lib/radix-tree.c b/lib/radix-tree.c
index dbf4e8c8e100..0a7ac0fb4a65 100644
--- a/lib/radix-tree.c
+++ b/lib/radix-tree.c
@@ -69,6 +69,11 @@ struct radix_tree_preload {
69}; 69};
70static DEFINE_PER_CPU(struct radix_tree_preload, radix_tree_preloads) = { 0, }; 70static DEFINE_PER_CPU(struct radix_tree_preload, radix_tree_preloads) = { 0, };
71 71
72static inline struct radix_tree_node *entry_to_node(void *ptr)
73{
74 return (void *)((unsigned long)ptr & ~RADIX_TREE_INTERNAL_NODE);
75}
76
72static inline void *node_to_entry(void *ptr) 77static inline void *node_to_entry(void *ptr)
73{ 78{
74 return (void *)((unsigned long)ptr | RADIX_TREE_INTERNAL_NODE); 79 return (void *)((unsigned long)ptr | RADIX_TREE_INTERNAL_NODE);
@@ -1104,6 +1109,120 @@ static inline void __set_iter_shift(struct radix_tree_iter *iter,
1104#endif 1109#endif
1105} 1110}
1106 1111
1112/* Construct iter->tags bit-mask from node->tags[tag] array */
1113static void set_iter_tags(struct radix_tree_iter *iter,
1114 struct radix_tree_node *node, unsigned offset,
1115 unsigned tag)
1116{
1117 unsigned tag_long = offset / BITS_PER_LONG;
1118 unsigned tag_bit = offset % BITS_PER_LONG;
1119
1120 iter->tags = node->tags[tag][tag_long] >> tag_bit;
1121
1122 /* This never happens if RADIX_TREE_TAG_LONGS == 1 */
1123 if (tag_long < RADIX_TREE_TAG_LONGS - 1) {
1124 /* Pick tags from next element */
1125 if (tag_bit)
1126 iter->tags |= node->tags[tag][tag_long + 1] <<
1127 (BITS_PER_LONG - tag_bit);
1128 /* Clip chunk size, here only BITS_PER_LONG tags */
1129 iter->next_index = __radix_tree_iter_add(iter, BITS_PER_LONG);
1130 }
1131}
1132
1133#ifdef CONFIG_RADIX_TREE_MULTIORDER
1134static void **skip_siblings(struct radix_tree_node **nodep,
1135 void **slot, struct radix_tree_iter *iter)
1136{
1137 void *sib = node_to_entry(slot - 1);
1138
1139 while (iter->index < iter->next_index) {
1140 *nodep = rcu_dereference_raw(*slot);
1141 if (*nodep && *nodep != sib)
1142 return slot;
1143 slot++;
1144 iter->index = __radix_tree_iter_add(iter, 1);
1145 iter->tags >>= 1;
1146 }
1147
1148 *nodep = NULL;
1149 return NULL;
1150}
1151
1152void ** __radix_tree_next_slot(void **slot, struct radix_tree_iter *iter,
1153 unsigned flags)
1154{
1155 unsigned tag = flags & RADIX_TREE_ITER_TAG_MASK;
1156 struct radix_tree_node *node = rcu_dereference_raw(*slot);
1157
1158 slot = skip_siblings(&node, slot, iter);
1159
1160 while (radix_tree_is_internal_node(node)) {
1161 unsigned offset;
1162 unsigned long next_index;
1163
1164 if (node == RADIX_TREE_RETRY)
1165 return slot;
1166 node = entry_to_node(node);
1167 iter->shift = node->shift;
1168
1169 if (flags & RADIX_TREE_ITER_TAGGED) {
1170 offset = radix_tree_find_next_bit(node, tag, 0);
1171 if (offset == RADIX_TREE_MAP_SIZE)
1172 return NULL;
1173 slot = &node->slots[offset];
1174 iter->index = __radix_tree_iter_add(iter, offset);
1175 set_iter_tags(iter, node, offset, tag);
1176 node = rcu_dereference_raw(*slot);
1177 } else {
1178 offset = 0;
1179 slot = &node->slots[0];
1180 for (;;) {
1181 node = rcu_dereference_raw(*slot);
1182 if (node)
1183 break;
1184 slot++;
1185 offset++;
1186 if (offset == RADIX_TREE_MAP_SIZE)
1187 return NULL;
1188 }
1189 iter->index = __radix_tree_iter_add(iter, offset);
1190 }
1191 if ((flags & RADIX_TREE_ITER_CONTIG) && (offset > 0))
1192 goto none;
1193 next_index = (iter->index | shift_maxindex(iter->shift)) + 1;
1194 if (next_index < iter->next_index)
1195 iter->next_index = next_index;
1196 }
1197
1198 return slot;
1199 none:
1200 iter->next_index = 0;
1201 return NULL;
1202}
1203EXPORT_SYMBOL(__radix_tree_next_slot);
1204#else
1205static void **skip_siblings(struct radix_tree_node **nodep,
1206 void **slot, struct radix_tree_iter *iter)
1207{
1208 return slot;
1209}
1210#endif
1211
1212void **radix_tree_iter_resume(void **slot, struct radix_tree_iter *iter)
1213{
1214 struct radix_tree_node *node;
1215
1216 slot++;
1217 iter->index = __radix_tree_iter_add(iter, 1);
1218 node = rcu_dereference_raw(*slot);
1219 skip_siblings(&node, slot, iter);
1220 iter->next_index = iter->index;
1221 iter->tags = 0;
1222 return NULL;
1223}
1224EXPORT_SYMBOL(radix_tree_iter_resume);
1225
1107/** 1226/**
1108 * radix_tree_next_chunk - find next chunk of slots for iteration 1227 * radix_tree_next_chunk - find next chunk of slots for iteration
1109 * 1228 *
@@ -1191,23 +1310,8 @@ void **radix_tree_next_chunk(struct radix_tree_root *root,
1191 iter->next_index = (index | node_maxindex(node)) + 1; 1310 iter->next_index = (index | node_maxindex(node)) + 1;
1192 __set_iter_shift(iter, node->shift); 1311 __set_iter_shift(iter, node->shift);
1193 1312
1194 /* Construct iter->tags bit-mask from node->tags[tag] array */ 1313 if (flags & RADIX_TREE_ITER_TAGGED)
1195 if (flags & RADIX_TREE_ITER_TAGGED) { 1314 set_iter_tags(iter, node, offset, tag);
1196 unsigned tag_long, tag_bit;
1197
1198 tag_long = offset / BITS_PER_LONG;
1199 tag_bit = offset % BITS_PER_LONG;
1200 iter->tags = node->tags[tag][tag_long] >> tag_bit;
1201 /* This never happens if RADIX_TREE_TAG_LONGS == 1 */
1202 if (tag_long < RADIX_TREE_TAG_LONGS - 1) {
1203 /* Pick tags from next element */
1204 if (tag_bit)
1205 iter->tags |= node->tags[tag][tag_long + 1] <<
1206 (BITS_PER_LONG - tag_bit);
1207 /* Clip chunk size, here only BITS_PER_LONG tags */
1208 iter->next_index = index + BITS_PER_LONG;
1209 }
1210 }
1211 1315
1212 return node->slots + offset; 1316 return node->slots + offset;
1213} 1317}