struct radix_tree_node **nodep, void ***slotp);
 void *radix_tree_lookup(struct radix_tree_root *, unsigned long);
 void **radix_tree_lookup_slot(struct radix_tree_root *, unsigned long);
+typedef void (*radix_tree_update_node_t)(struct radix_tree_node *, void *);
 void __radix_tree_replace(struct radix_tree_root *root,
                          struct radix_tree_node *node,
-                         void **slot, void *item);
+                         void **slot, void *item,
+                         radix_tree_update_node_t update_node, void *private);
 void radix_tree_replace_slot(struct radix_tree_root *root,
                             void **slot, void *item);
 bool __radix_tree_delete_node(struct radix_tree_root *root,
 
                tag_clear(node, i, 0);
 
        node->slots[0] = NULL;
-       node->count = 0;
 
        kmem_cache_free(radix_tree_node_cachep, node);
 }
  *     radix_tree_shrink    -    shrink radix tree to minimum height
  *     @root           radix tree root
  */
-static inline bool radix_tree_shrink(struct radix_tree_root *root)
+static inline bool radix_tree_shrink(struct radix_tree_root *root,
+                                    radix_tree_update_node_t update_node,
+                                    void *private)
 {
        bool shrunk = false;
 
                 * also results in a stale slot). So tag the slot as indirect
                 * to force callers to retry.
                 */
-               if (!radix_tree_is_internal_node(child))
+               node->count = 0;
+               if (!radix_tree_is_internal_node(child)) {
                        node->slots[0] = RADIX_TREE_RETRY;
+                       if (update_node)
+                               update_node(node, private);
+               }
 
                radix_tree_node_free(node);
                shrunk = true;
 }
 
 static bool delete_node(struct radix_tree_root *root,
-                       struct radix_tree_node *node)
+                       struct radix_tree_node *node,
+                       radix_tree_update_node_t update_node, void *private)
 {
        bool deleted = false;
 
 
                if (node->count) {
                        if (node == entry_to_node(root->rnode))
-                               deleted |= radix_tree_shrink(root);
+                               deleted |= radix_tree_shrink(root, update_node,
+                                                            private);
                        return deleted;
                }
 
 
 /**
  * __radix_tree_replace                - replace item in a slot
- * @root:      radix tree root
- * @node:      pointer to tree node
- * @slot:      pointer to slot in @node
- * @item:      new item to store in the slot.
+ * @root:              radix tree root
+ * @node:              pointer to tree node
+ * @slot:              pointer to slot in @node
+ * @item:              new item to store in the slot.
+ * @update_node:       callback for changing leaf nodes
+ * @private:           private data to pass to @update_node
  *
  * For use with __radix_tree_lookup().  Caller must hold tree write locked
  * across slot lookup and replacement.
  */
 void __radix_tree_replace(struct radix_tree_root *root,
                          struct radix_tree_node *node,
-                         void **slot, void *item)
+                         void **slot, void *item,
+                         radix_tree_update_node_t update_node, void *private)
 {
        /*
         * This function supports replacing exceptional entries and
        replace_slot(root, node, slot, item,
                     !node && slot != (void **)&root->rnode);
 
-       delete_node(root, node);
+       if (!node)
+               return;
+
+       if (update_node)
+               update_node(node, private);
+
+       delete_node(root, node, update_node, private);
 }
 
 /**
 bool __radix_tree_delete_node(struct radix_tree_root *root,
                              struct radix_tree_node *node)
 {
-       return delete_node(root, node);
+       return delete_node(root, node, NULL, NULL);
 }
 
 static inline void delete_sibling_entries(struct radix_tree_node *node,
                node_tag_clear(root, node, tag, offset);
 
        delete_sibling_entries(node, node_to_entry(slot), offset);
-       __radix_tree_replace(root, node, slot, NULL);
+       __radix_tree_replace(root, node, slot, NULL, NULL, NULL);
 
        return entry;
 }