···9696 * @next_index: one beyond the last index for this chunk9797 * @tags: bit-mask for tag-iterating9898 * @node: node that contains current slot9999- * @shift: shift for the node that holds our slots10099 *101100 * This radix tree iterator works in terms of "chunks" of slots. A chunk is a102101 * subinterval of slots contained within one radix tree leaf node. It is···109110 unsigned long next_index;110111 unsigned long tags;111112 struct radix_tree_node *node;112112-#ifdef CONFIG_RADIX_TREE_MULTIORDER113113- unsigned int shift;114114-#endif115113};116116-117117-static inline unsigned int iter_shift(const struct radix_tree_iter *iter)118118-{119119-#ifdef CONFIG_RADIX_TREE_MULTIORDER120120- return iter->shift;121121-#else122122- return 0;123123-#endif124124-}125114126115/**127116 * Radix-tree synchronization···217230 return unlikely((unsigned long)arg & RADIX_TREE_ENTRY_MASK);218231}219232220220-int __radix_tree_insert(struct radix_tree_root *, unsigned long index,221221- unsigned order, void *);222222-static inline int radix_tree_insert(struct radix_tree_root *root,223223- unsigned long index, void *entry)224224-{225225- return __radix_tree_insert(root, index, 0, entry);226226-}233233+int radix_tree_insert(struct radix_tree_root *, unsigned long index,234234+ void *);227235void *__radix_tree_lookup(const struct radix_tree_root *, unsigned long index,228236 struct radix_tree_node **nodep, void __rcu ***slotp);229237void *radix_tree_lookup(const struct radix_tree_root *, unsigned long);···366384static inline unsigned long367385__radix_tree_iter_add(struct radix_tree_iter *iter, unsigned long slots)368386{369369- return iter->index + (slots << iter_shift(iter));387387+ return iter->index + slots;370388}371389372390/**···391409static __always_inline long392410radix_tree_chunk_size(struct radix_tree_iter *iter)393411{394394- return (iter->next_index - iter->index) >> iter_shift(iter);412412+ return iter->next_index - iter->index;395413}396396-397397-#ifdef CONFIG_RADIX_TREE_MULTIORDER398398-void __rcu **__radix_tree_next_slot(void __rcu **slot,399399- struct radix_tree_iter *iter, unsigned flags);400400-#else401401-/* Can't happen without sibling entries, but the compiler can't tell that */402402-static inline void __rcu **__radix_tree_next_slot(void __rcu **slot,403403- struct radix_tree_iter *iter, unsigned flags)404404-{405405- return slot;406406-}407407-#endif408414409415/**410416 * radix_tree_next_slot - find next slot in chunk···452482 return NULL;453483454484 found:455455- if (unlikely(radix_tree_is_internal_node(rcu_dereference_raw(*slot))))456456- return __radix_tree_next_slot(slot, iter, flags);457485 return slot;458486}459487
-4
lib/Kconfig
···405405 Support entries which occupy multiple consecutive indices in the406406 XArray.407407408408-config RADIX_TREE_MULTIORDER409409- bool410410- select XARRAY_MULTI411411-412408config ASSOCIATIVE_ARRAY413409 bool414410 help
+13-202
lib/radix-tree.c
···110110 unsigned int offset = (index >> parent->shift) & RADIX_TREE_MAP_MASK;111111 void __rcu **entry = rcu_dereference_raw(parent->slots[offset]);112112113113- if (xa_is_sibling(entry)) {114114- offset = xa_to_sibling(entry);115115- entry = rcu_dereference_raw(parent->slots[offset]);116116- }117117-118113 *nodep = (void *)entry;119114 return offset;120115}···224229225230static unsigned int iter_offset(const struct radix_tree_iter *iter)226231{227227- return (iter->index >> iter_shift(iter)) & RADIX_TREE_MAP_MASK;232232+ return iter->index & RADIX_TREE_MAP_MASK;228233}229234230235/*···501506502507 /*503508 * The candidate node has more than one child, or its child504504- * is not at the leftmost slot, or the child is a multiorder505505- * entry, we cannot shrink.509509+ * is not at the leftmost slot, we cannot shrink.506510 */507511 if (node->count != 1)508512 break;509513 child = rcu_dereference_raw(node->slots[0]);510514 if (!child)511511- break;512512- if (!radix_tree_is_internal_node(child) && node->shift)513515 break;514516515517 /*···605613 * __radix_tree_create - create a slot in a radix tree606614 * @root: radix tree root607615 * @index: index key608608- * @order: index occupies 2^order aligned slots609616 * @nodep: returns node610617 * @slotp: returns slot611618 *···618627 * Returns -ENOMEM, or 0 for success.619628 */620629static int __radix_tree_create(struct radix_tree_root *root,621621- unsigned long index, unsigned order,622622- struct radix_tree_node **nodep, void __rcu ***slotp)630630+ unsigned long index, struct radix_tree_node **nodep,631631+ void __rcu ***slotp)623632{624633 struct radix_tree_node *node = NULL, *child;625634 void __rcu **slot = (void __rcu **)&root->xa_head;626635 unsigned long maxindex;627636 unsigned int shift, offset = 0;628628- unsigned long max = index | ((1UL << order) - 1);637637+ unsigned long max = index;629638 gfp_t gfp = root_gfp_mask(root);630639631640 shift = radix_tree_load_root(root, &child, &maxindex);632641633642 /* Make sure the tree is high enough. */634634- if (order > 0 && max == ((1UL << order) - 1))635635- max++;636643 if (max > maxindex) {637644 int error = radix_tree_extend(root, gfp, max, shift);638645 if (error < 0)···639650 child = rcu_dereference_raw(root->xa_head);640651 }641652642642- while (shift > order) {653653+ while (shift > 0) {643654 shift -= RADIX_TREE_MAP_SHIFT;644655 if (child == NULL) {645656 /* Have to add a child node. */···700711 }701712}702713703703-#ifdef CONFIG_RADIX_TREE_MULTIORDER704714static inline int insert_entries(struct radix_tree_node *node,705705- void __rcu **slot, void *item, unsigned order, bool replace)706706-{707707- void *sibling;708708- unsigned i, n, tag, offset, tags = 0;709709-710710- if (node) {711711- if (order > node->shift)712712- n = 1 << (order - node->shift);713713- else714714- n = 1;715715- offset = get_slot_offset(node, slot);716716- } else {717717- n = 1;718718- offset = 0;719719- }720720-721721- if (n > 1) {722722- offset = offset & ~(n - 1);723723- slot = &node->slots[offset];724724- }725725- sibling = xa_mk_sibling(offset);726726-727727- for (i = 0; i < n; i++) {728728- if (slot[i]) {729729- if (replace) {730730- node->count--;731731- for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++)732732- if (tag_get(node, tag, offset + i))733733- tags |= 1 << tag;734734- } else735735- return -EEXIST;736736- }737737- }738738-739739- for (i = 0; i < n; i++) {740740- struct radix_tree_node *old = rcu_dereference_raw(slot[i]);741741- if (i) {742742- rcu_assign_pointer(slot[i], sibling);743743- for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++)744744- if (tags & (1 << tag))745745- tag_clear(node, tag, offset + i);746746- } else {747747- rcu_assign_pointer(slot[i], item);748748- for (tag = 0; tag < RADIX_TREE_MAX_TAGS; tag++)749749- if (tags & (1 << tag))750750- tag_set(node, tag, offset);751751- }752752- if (xa_is_node(old))753753- radix_tree_free_nodes(old);754754- if (xa_is_value(old))755755- node->nr_values--;756756- }757757- if (node) {758758- node->count += n;759759- if (xa_is_value(item))760760- node->nr_values += n;761761- }762762- return n;763763-}764764-#else765765-static inline int insert_entries(struct radix_tree_node *node,766766- void __rcu **slot, void *item, unsigned order, bool replace)715715+ void __rcu **slot, void *item, bool replace)767716{768717 if (*slot)769718 return -EEXIST;···713786 }714787 return 1;715788}716716-#endif717789718790/**719791 * __radix_tree_insert - insert into a radix tree720792 * @root: radix tree root721793 * @index: index key722722- * @order: key covers the 2^order indices around index723794 * @item: item to insert724795 *725796 * Insert an item into the radix tree at position @index.726797 */727727-int __radix_tree_insert(struct radix_tree_root *root, unsigned long index,728728- unsigned order, void *item)798798+int radix_tree_insert(struct radix_tree_root *root, unsigned long index,799799+ void *item)729800{730801 struct radix_tree_node *node;731802 void __rcu **slot;···731806732807 BUG_ON(radix_tree_is_internal_node(item));733808734734- error = __radix_tree_create(root, index, order, &node, &slot);809809+ error = __radix_tree_create(root, index, &node, &slot);735810 if (error)736811 return error;737812738738- error = insert_entries(node, slot, item, order, false);813813+ error = insert_entries(node, slot, item, false);739814 if (error < 0)740815 return error;741816···750825751826 return 0;752827}753753-EXPORT_SYMBOL(__radix_tree_insert);828828+EXPORT_SYMBOL(radix_tree_insert);754829755830/**756831 * __radix_tree_lookup - lookup an item in a radix tree···842917}843918EXPORT_SYMBOL(radix_tree_lookup);844919845845-static inline void replace_sibling_entries(struct radix_tree_node *node,846846- void __rcu **slot, int count, int values)847847-{848848-#ifdef CONFIG_RADIX_TREE_MULTIORDER849849- unsigned offset = get_slot_offset(node, slot);850850- void *ptr = xa_mk_sibling(offset);851851-852852- while (++offset < RADIX_TREE_MAP_SIZE) {853853- if (rcu_dereference_raw(node->slots[offset]) != ptr)854854- break;855855- if (count < 0) {856856- node->slots[offset] = NULL;857857- node->count--;858858- }859859- node->nr_values += values;860860- }861861-#endif862862-}863863-864920static void replace_slot(void __rcu **slot, void *item,865921 struct radix_tree_node *node, int count, int values)866922{867923 if (node && (count || values)) {868924 node->count += count;869925 node->nr_values += values;870870- replace_sibling_entries(node, slot, count, values);871926 }872927873928 rcu_assign_pointer(*slot, item);···11281223}11291224EXPORT_SYMBOL(radix_tree_tag_get);1130122511311131-static inline void __set_iter_shift(struct radix_tree_iter *iter,11321132- unsigned int shift)11331133-{11341134-#ifdef CONFIG_RADIX_TREE_MULTIORDER11351135- iter->shift = shift;11361136-#endif11371137-}11381138-11391226/* Construct iter->tags bit-mask from node->tags[tag] array */11401227static void set_iter_tags(struct radix_tree_iter *iter,11411228 struct radix_tree_node *node, unsigned offset,···11541257 }11551258}1156125911571157-#ifdef CONFIG_RADIX_TREE_MULTIORDER11581158-static void __rcu **skip_siblings(struct radix_tree_node **nodep,11591159- void __rcu **slot, struct radix_tree_iter *iter)11601160-{11611161- while (iter->index < iter->next_index) {11621162- *nodep = rcu_dereference_raw(*slot);11631163- if (*nodep && !xa_is_sibling(*nodep))11641164- return slot;11651165- slot++;11661166- iter->index = __radix_tree_iter_add(iter, 1);11671167- iter->tags >>= 1;11681168- }11691169-11701170- *nodep = NULL;11711171- return NULL;11721172-}11731173-11741174-void __rcu **__radix_tree_next_slot(void __rcu **slot,11751175- struct radix_tree_iter *iter, unsigned flags)11761176-{11771177- unsigned tag = flags & RADIX_TREE_ITER_TAG_MASK;11781178- struct radix_tree_node *node;11791179-11801180- slot = skip_siblings(&node, slot, iter);11811181-11821182- while (radix_tree_is_internal_node(node)) {11831183- unsigned offset;11841184- unsigned long next_index;11851185-11861186- if (node == RADIX_TREE_RETRY)11871187- return slot;11881188- node = entry_to_node(node);11891189- iter->node = node;11901190- iter->shift = node->shift;11911191-11921192- if (flags & RADIX_TREE_ITER_TAGGED) {11931193- offset = radix_tree_find_next_bit(node, tag, 0);11941194- if (offset == RADIX_TREE_MAP_SIZE)11951195- return NULL;11961196- slot = &node->slots[offset];11971197- iter->index = __radix_tree_iter_add(iter, offset);11981198- set_iter_tags(iter, node, offset, tag);11991199- node = rcu_dereference_raw(*slot);12001200- } else {12011201- offset = 0;12021202- slot = &node->slots[0];12031203- for (;;) {12041204- node = rcu_dereference_raw(*slot);12051205- if (node)12061206- break;12071207- slot++;12081208- offset++;12091209- if (offset == RADIX_TREE_MAP_SIZE)12101210- return NULL;12111211- }12121212- iter->index = __radix_tree_iter_add(iter, offset);12131213- }12141214- if ((flags & RADIX_TREE_ITER_CONTIG) && (offset > 0))12151215- goto none;12161216- next_index = (iter->index | shift_maxindex(iter->shift)) + 1;12171217- if (next_index < iter->next_index)12181218- iter->next_index = next_index;12191219- }12201220-12211221- return slot;12221222- none:12231223- iter->next_index = 0;12241224- return NULL;12251225-}12261226-EXPORT_SYMBOL(__radix_tree_next_slot);12271227-#else12281228-static void __rcu **skip_siblings(struct radix_tree_node **nodep,12291229- void __rcu **slot, struct radix_tree_iter *iter)12301230-{12311231- return slot;12321232-}12331233-#endif12341234-12351260void __rcu **radix_tree_iter_resume(void __rcu **slot,12361261 struct radix_tree_iter *iter)12371262{12381238- struct radix_tree_node *node;12391239-12401263 slot++;12411264 iter->index = __radix_tree_iter_add(iter, 1);12421242- skip_siblings(&node, slot, iter);12431265 iter->next_index = iter->index;12441266 iter->tags = 0;12451267 return NULL;···12091393 iter->next_index = maxindex + 1;12101394 iter->tags = 1;12111395 iter->node = NULL;12121212- __set_iter_shift(iter, 0);12131396 return (void __rcu **)&root->xa_head;12141397 }12151398···12291414 while (++offset < RADIX_TREE_MAP_SIZE) {12301415 void *slot = rcu_dereference_raw(12311416 node->slots[offset]);12321232- if (xa_is_sibling(slot))12331233- continue;12341417 if (slot)12351418 break;12361419 }···12491436 } while (node->shift && radix_tree_is_internal_node(child));1250143712511438 /* Update the iterator state */12521252- iter->index = (index &~ node_maxindex(node)) | (offset << node->shift);14391439+ iter->index = (index &~ node_maxindex(node)) | offset;12531440 iter->next_index = (index | node_maxindex(node)) + 1;12541441 iter->node = node;12551255- __set_iter_shift(iter, node->shift);1256144212571443 if (flags & RADIX_TREE_ITER_TAGGED)12581444 set_iter_tags(iter, node, offset, tag);···15621750 else15631751 iter->next_index = 1;15641752 iter->node = node;15651565- __set_iter_shift(iter, shift);15661753 set_iter_tags(iter, node, offset, IDR_FREE);1567175415681755 return slot;
+2-2
mm/Kconfig
···379379 bool "Transparent Hugepage Support"380380 depends on HAVE_ARCH_TRANSPARENT_HUGEPAGE381381 select COMPACTION382382- select RADIX_TREE_MULTIORDER382382+ select XARRAY_MULTI383383 help384384 Transparent Hugepages allows the kernel to use huge pages and385385 huge tlb transparently to the applications whenever possible.···671671 depends on MEMORY_HOTREMOVE672672 depends on SPARSEMEM_VMEMMAP673673 depends on ARCH_HAS_ZONE_DEVICE674674- select RADIX_TREE_MULTIORDER674674+ select XARRAY_MULTI675675676676 help677677 Device memory hotplug support allows for establishing pmem,