Skip to content

Commit cebbd29

Browse files
koct9itorvalds
authored andcommitted
radix-tree: rewrite gang lookup using iterator
Rewrite radix_tree_gang_lookup_* functions using the new radix-tree iterator. Signed-off-by: Konstantin Khlebnikov <[email protected]> Tested-by: Hugh Dickins <[email protected]> Cc: Christoph Hellwig <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Signed-off-by: Linus Torvalds <[email protected]>
1 parent 78c1d78 commit cebbd29

File tree

1 file changed

+33
-258
lines changed

1 file changed

+33
-258
lines changed

lib/radix-tree.c

Lines changed: 33 additions & 258 deletions
Original file line numberDiff line numberDiff line change
@@ -968,57 +968,6 @@ unsigned long radix_tree_prev_hole(struct radix_tree_root *root,
968968
}
969969
EXPORT_SYMBOL(radix_tree_prev_hole);
970970

971-
static unsigned int
972-
__lookup(struct radix_tree_node *slot, void ***results, unsigned long *indices,
973-
unsigned long index, unsigned int max_items, unsigned long *next_index)
974-
{
975-
unsigned int nr_found = 0;
976-
unsigned int shift, height;
977-
unsigned long i;
978-
979-
height = slot->height;
980-
if (height == 0)
981-
goto out;
982-
shift = (height-1) * RADIX_TREE_MAP_SHIFT;
983-
984-
for ( ; height > 1; height--) {
985-
i = (index >> shift) & RADIX_TREE_MAP_MASK;
986-
for (;;) {
987-
if (slot->slots[i] != NULL)
988-
break;
989-
index &= ~((1UL << shift) - 1);
990-
index += 1UL << shift;
991-
if (index == 0)
992-
goto out; /* 32-bit wraparound */
993-
i++;
994-
if (i == RADIX_TREE_MAP_SIZE)
995-
goto out;
996-
}
997-
998-
shift -= RADIX_TREE_MAP_SHIFT;
999-
slot = rcu_dereference_raw(slot->slots[i]);
1000-
if (slot == NULL)
1001-
goto out;
1002-
}
1003-
1004-
/* Bottom level: grab some items */
1005-
for (i = index & RADIX_TREE_MAP_MASK; i < RADIX_TREE_MAP_SIZE; i++) {
1006-
if (slot->slots[i]) {
1007-
results[nr_found] = &(slot->slots[i]);
1008-
if (indices)
1009-
indices[nr_found] = index;
1010-
if (++nr_found == max_items) {
1011-
index++;
1012-
goto out;
1013-
}
1014-
}
1015-
index++;
1016-
}
1017-
out:
1018-
*next_index = index;
1019-
return nr_found;
1020-
}
1021-
1022971
/**
1023972
* radix_tree_gang_lookup - perform multiple lookup on a radix tree
1024973
* @root: radix tree root
@@ -1042,48 +991,19 @@ unsigned int
1042991
radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
1043992
unsigned long first_index, unsigned int max_items)
1044993
{
1045-
unsigned long max_index;
1046-
struct radix_tree_node *node;
1047-
unsigned long cur_index = first_index;
1048-
unsigned int ret;
994+
struct radix_tree_iter iter;
995+
void **slot;
996+
unsigned int ret = 0;
1049997

1050-
node = rcu_dereference_raw(root->rnode);
1051-
if (!node)
998+
if (unlikely(!max_items))
1052999
return 0;
10531000

1054-
if (!radix_tree_is_indirect_ptr(node)) {
1055-
if (first_index > 0)
1056-
return 0;
1057-
results[0] = node;
1058-
return 1;
1059-
}
1060-
node = indirect_to_ptr(node);
1061-
1062-
max_index = radix_tree_maxindex(node->height);
1063-
1064-
ret = 0;
1065-
while (ret < max_items) {
1066-
unsigned int nr_found, slots_found, i;
1067-
unsigned long next_index; /* Index of next search */
1068-
1069-
if (cur_index > max_index)
1070-
break;
1071-
slots_found = __lookup(node, (void ***)results + ret, NULL,
1072-
cur_index, max_items - ret, &next_index);
1073-
nr_found = 0;
1074-
for (i = 0; i < slots_found; i++) {
1075-
struct radix_tree_node *slot;
1076-
slot = *(((void ***)results)[ret + i]);
1077-
if (!slot)
1078-
continue;
1079-
results[ret + nr_found] =
1080-
indirect_to_ptr(rcu_dereference_raw(slot));
1081-
nr_found++;
1082-
}
1083-
ret += nr_found;
1084-
if (next_index == 0)
1001+
radix_tree_for_each_slot(slot, root, &iter, first_index) {
1002+
results[ret] = indirect_to_ptr(rcu_dereference_raw(*slot));
1003+
if (!results[ret])
1004+
continue;
1005+
if (++ret == max_items)
10851006
break;
1086-
cur_index = next_index;
10871007
}
10881008

10891009
return ret;
@@ -1113,112 +1033,25 @@ radix_tree_gang_lookup_slot(struct radix_tree_root *root,
11131033
void ***results, unsigned long *indices,
11141034
unsigned long first_index, unsigned int max_items)
11151035
{
1116-
unsigned long max_index;
1117-
struct radix_tree_node *node;
1118-
unsigned long cur_index = first_index;
1119-
unsigned int ret;
1036+
struct radix_tree_iter iter;
1037+
void **slot;
1038+
unsigned int ret = 0;
11201039

1121-
node = rcu_dereference_raw(root->rnode);
1122-
if (!node)
1040+
if (unlikely(!max_items))
11231041
return 0;
11241042

1125-
if (!radix_tree_is_indirect_ptr(node)) {
1126-
if (first_index > 0)
1127-
return 0;
1128-
results[0] = (void **)&root->rnode;
1043+
radix_tree_for_each_slot(slot, root, &iter, first_index) {
1044+
results[ret] = slot;
11291045
if (indices)
1130-
indices[0] = 0;
1131-
return 1;
1132-
}
1133-
node = indirect_to_ptr(node);
1134-
1135-
max_index = radix_tree_maxindex(node->height);
1136-
1137-
ret = 0;
1138-
while (ret < max_items) {
1139-
unsigned int slots_found;
1140-
unsigned long next_index; /* Index of next search */
1141-
1142-
if (cur_index > max_index)
1046+
indices[ret] = iter.index;
1047+
if (++ret == max_items)
11431048
break;
1144-
slots_found = __lookup(node, results + ret,
1145-
indices ? indices + ret : NULL,
1146-
cur_index, max_items - ret, &next_index);
1147-
ret += slots_found;
1148-
if (next_index == 0)
1149-
break;
1150-
cur_index = next_index;
11511049
}
11521050

11531051
return ret;
11541052
}
11551053
EXPORT_SYMBOL(radix_tree_gang_lookup_slot);
11561054

1157-
/*
1158-
* FIXME: the two tag_get()s here should use find_next_bit() instead of
1159-
* open-coding the search.
1160-
*/
1161-
static unsigned int
1162-
__lookup_tag(struct radix_tree_node *slot, void ***results, unsigned long index,
1163-
unsigned int max_items, unsigned long *next_index, unsigned int tag)
1164-
{
1165-
unsigned int nr_found = 0;
1166-
unsigned int shift, height;
1167-
1168-
height = slot->height;
1169-
if (height == 0)
1170-
goto out;
1171-
shift = (height-1) * RADIX_TREE_MAP_SHIFT;
1172-
1173-
while (height > 0) {
1174-
unsigned long i = (index >> shift) & RADIX_TREE_MAP_MASK ;
1175-
1176-
for (;;) {
1177-
if (tag_get(slot, tag, i))
1178-
break;
1179-
index &= ~((1UL << shift) - 1);
1180-
index += 1UL << shift;
1181-
if (index == 0)
1182-
goto out; /* 32-bit wraparound */
1183-
i++;
1184-
if (i == RADIX_TREE_MAP_SIZE)
1185-
goto out;
1186-
}
1187-
height--;
1188-
if (height == 0) { /* Bottom level: grab some items */
1189-
unsigned long j = index & RADIX_TREE_MAP_MASK;
1190-
1191-
for ( ; j < RADIX_TREE_MAP_SIZE; j++) {
1192-
index++;
1193-
if (!tag_get(slot, tag, j))
1194-
continue;
1195-
/*
1196-
* Even though the tag was found set, we need to
1197-
* recheck that we have a non-NULL node, because
1198-
* if this lookup is lockless, it may have been
1199-
* subsequently deleted.
1200-
*
1201-
* Similar care must be taken in any place that
1202-
* lookup ->slots[x] without a lock (ie. can't
1203-
* rely on its value remaining the same).
1204-
*/
1205-
if (slot->slots[j]) {
1206-
results[nr_found++] = &(slot->slots[j]);
1207-
if (nr_found == max_items)
1208-
goto out;
1209-
}
1210-
}
1211-
}
1212-
shift -= RADIX_TREE_MAP_SHIFT;
1213-
slot = rcu_dereference_raw(slot->slots[i]);
1214-
if (slot == NULL)
1215-
break;
1216-
}
1217-
out:
1218-
*next_index = index;
1219-
return nr_found;
1220-
}
1221-
12221055
/**
12231056
* radix_tree_gang_lookup_tag - perform multiple lookup on a radix tree
12241057
* based on a tag
@@ -1237,52 +1070,19 @@ radix_tree_gang_lookup_tag(struct radix_tree_root *root, void **results,
12371070
unsigned long first_index, unsigned int max_items,
12381071
unsigned int tag)
12391072
{
1240-
struct radix_tree_node *node;
1241-
unsigned long max_index;
1242-
unsigned long cur_index = first_index;
1243-
unsigned int ret;
1073+
struct radix_tree_iter iter;
1074+
void **slot;
1075+
unsigned int ret = 0;
12441076

1245-
/* check the root's tag bit */
1246-
if (!root_tag_get(root, tag))
1077+
if (unlikely(!max_items))
12471078
return 0;
12481079

1249-
node = rcu_dereference_raw(root->rnode);
1250-
if (!node)
1251-
return 0;
1252-
1253-
if (!radix_tree_is_indirect_ptr(node)) {
1254-
if (first_index > 0)
1255-
return 0;
1256-
results[0] = node;
1257-
return 1;
1258-
}
1259-
node = indirect_to_ptr(node);
1260-
1261-
max_index = radix_tree_maxindex(node->height);
1262-
1263-
ret = 0;
1264-
while (ret < max_items) {
1265-
unsigned int nr_found, slots_found, i;
1266-
unsigned long next_index; /* Index of next search */
1267-
1268-
if (cur_index > max_index)
1269-
break;
1270-
slots_found = __lookup_tag(node, (void ***)results + ret,
1271-
cur_index, max_items - ret, &next_index, tag);
1272-
nr_found = 0;
1273-
for (i = 0; i < slots_found; i++) {
1274-
struct radix_tree_node *slot;
1275-
slot = *(((void ***)results)[ret + i]);
1276-
if (!slot)
1277-
continue;
1278-
results[ret + nr_found] =
1279-
indirect_to_ptr(rcu_dereference_raw(slot));
1280-
nr_found++;
1281-
}
1282-
ret += nr_found;
1283-
if (next_index == 0)
1080+
radix_tree_for_each_tagged(slot, root, &iter, first_index, tag) {
1081+
results[ret] = indirect_to_ptr(rcu_dereference_raw(*slot));
1082+
if (!results[ret])
1083+
continue;
1084+
if (++ret == max_items)
12841085
break;
1285-
cur_index = next_index;
12861086
}
12871087

12881088
return ret;
@@ -1307,42 +1107,17 @@ radix_tree_gang_lookup_tag_slot(struct radix_tree_root *root, void ***results,
13071107
unsigned long first_index, unsigned int max_items,
13081108
unsigned int tag)
13091109
{
1310-
struct radix_tree_node *node;
1311-
unsigned long max_index;
1312-
unsigned long cur_index = first_index;
1313-
unsigned int ret;
1110+
struct radix_tree_iter iter;
1111+
void **slot;
1112+
unsigned int ret = 0;
13141113

1315-
/* check the root's tag bit */
1316-
if (!root_tag_get(root, tag))
1317-
return 0;
1318-
1319-
node = rcu_dereference_raw(root->rnode);
1320-
if (!node)
1114+
if (unlikely(!max_items))
13211115
return 0;
13221116

1323-
if (!radix_tree_is_indirect_ptr(node)) {
1324-
if (first_index > 0)
1325-
return 0;
1326-
results[0] = (void **)&root->rnode;
1327-
return 1;
1328-
}
1329-
node = indirect_to_ptr(node);
1330-
1331-
max_index = radix_tree_maxindex(node->height);
1332-
1333-
ret = 0;
1334-
while (ret < max_items) {
1335-
unsigned int slots_found;
1336-
unsigned long next_index; /* Index of next search */
1337-
1338-
if (cur_index > max_index)
1339-
break;
1340-
slots_found = __lookup_tag(node, results + ret,
1341-
cur_index, max_items - ret, &next_index, tag);
1342-
ret += slots_found;
1343-
if (next_index == 0)
1117+
radix_tree_for_each_tagged(slot, root, &iter, first_index, tag) {
1118+
results[ret] = slot;
1119+
if (++ret == max_items)
13441120
break;
1345-
cur_index = next_index;
13461121
}
13471122

13481123
return ret;

0 commit comments

Comments
 (0)