radix_tree_replace() replaces an old item with a new item. This function is invoked from the memory migration code to replace with a target page with a new page. Signed-off-by: Hirokazu Takahashi Signed-off-by: Dave Hansen --- memhotplug-dave/include/linux/radix-tree.h | 1 memhotplug-dave/lib/radix-tree.c | 55 ++++++++++++++++++++++++++++- 2 files changed, 55 insertions(+), 1 deletion(-) diff -puN include/linux/radix-tree.h~AA-PM-03-radix-tree-replace include/linux/radix-tree.h --- memhotplug/include/linux/radix-tree.h~AA-PM-03-radix-tree-replace 2005-07-28 13:50:32.000000000 -0700 +++ memhotplug-dave/include/linux/radix-tree.h 2005-07-28 13:50:32.000000000 -0700 @@ -47,6 +47,7 @@ do { \ int radix_tree_insert(struct radix_tree_root *, unsigned long, void *); void *radix_tree_lookup(struct radix_tree_root *, unsigned long); void *radix_tree_delete(struct radix_tree_root *, unsigned long); +void *radix_tree_replace(struct radix_tree_root *, unsigned long, void *); unsigned int radix_tree_gang_lookup(struct radix_tree_root *root, void **results, unsigned long first_index, unsigned int max_items); diff -puN lib/radix-tree.c~AA-PM-03-radix-tree-replace lib/radix-tree.c --- memhotplug/lib/radix-tree.c~AA-PM-03-radix-tree-replace 2005-07-28 13:50:32.000000000 -0700 +++ memhotplug-dave/lib/radix-tree.c 2005-07-28 13:50:32.000000000 -0700 @@ -100,7 +100,13 @@ radix_tree_node_alloc(struct radix_tree_ static inline void radix_tree_node_free(struct radix_tree_node *node) { - kmem_cache_free(radix_tree_node_cachep, node); + struct radix_tree_preload *rtp; + + rtp = &__get_cpu_var(radix_tree_preloads); + if (rtp->nr < ARRAY_SIZE(rtp->nodes)) + rtp->nodes[rtp->nr++] = node; + else + kmem_cache_free(radix_tree_node_cachep, node); } /* @@ -733,6 +739,53 @@ out: EXPORT_SYMBOL(radix_tree_delete); /** + * radix_tree_replace - replace items in a radix tree + * @root: radix tree root + * @index: index key + * @item: item to insert + * + * Replace the item at @index with @item. + * Returns the address of the deleted item, or NULL if it was not present. + */ +void *radix_tree_replace(struct radix_tree_root *root, + unsigned long index, void *item) +{ + struct radix_tree_path path[RADIX_TREE_MAX_PATH], *pathp = path; + unsigned int height, shift; + void *ret = NULL; + + height = root->height; + if (index > radix_tree_maxindex(height)) + goto out; + + shift = (height - 1) * RADIX_TREE_MAP_SHIFT; + pathp->node = NULL; + pathp->slot = &root->rnode; + + while (height > 0) { + int offset; + + if (*pathp->slot == NULL) + goto out; + + offset = (index >> shift) & RADIX_TREE_MAP_MASK; + pathp[1].offset = offset; + pathp[1].node = *pathp[0].slot; + pathp[1].slot = (struct radix_tree_node **) + (pathp[1].node->slots + offset); + pathp++; + shift -= RADIX_TREE_MAP_SHIFT; + height--; + } + + if ((ret = *pathp[0].slot)) + *pathp[0].slot = item; +out: + return ret; +} +EXPORT_SYMBOL(radix_tree_replace); + +/** * radix_tree_tagged - test whether any items in the tree are tagged * @root: radix tree root * @tag: tag to test _