lib: radix-tree: add radix_tree_delete_item()
authorJohannes Weiner <[email protected]>
Thu, 3 Apr 2014 21:47:39 +0000 (14:47 -0700)
committerLinus Torvalds <[email protected]>
Thu, 3 Apr 2014 23:21:00 +0000 (16:21 -0700)
Provide a function that does not just delete an entry at a given index,
but also allows passing in an expected item.  Delete only if that item
is still located at the specified index.

This is handy when lockless tree traversals want to delete entries as
well because they don't have to do an second, locked lookup to verify
the slot has not changed under them before deleting the entry.

Signed-off-by: Johannes Weiner <[email protected]>
Reviewed-by: Minchan Kim <[email protected]>
Reviewed-by: Rik van Riel <[email protected]>
Acked-by: Mel Gorman <[email protected]>
Cc: Andrea Arcangeli <[email protected]>
Cc: Bob Liu <[email protected]>
Cc: Christoph Hellwig <[email protected]>
Cc: Dave Chinner <[email protected]>
Cc: Greg Thelen <[email protected]>
Cc: Hugh Dickins <[email protected]>
Cc: Jan Kara <[email protected]>
Cc: KOSAKI Motohiro <[email protected]>
Cc: Luigi Semenzato <[email protected]>
Cc: Metin Doslu <[email protected]>
Cc: Michel Lespinasse <[email protected]>
Cc: Ozgun Erdogan <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Cc: Roman Gushchin <[email protected]>
Cc: Ryan Mallon <[email protected]>
Cc: Tejun Heo <[email protected]>
Cc: Vlastimil Babka <[email protected]>
Signed-off-by: Andrew Morton <[email protected]>
Signed-off-by: Linus Torvalds <[email protected]>
include/linux/radix-tree.h
lib/radix-tree.c

index 403940787be18230a5201799d57020ed46177cab..1bf0a9c388d9fe9a1eba9e603a1f2732453067c9 100644 (file)
@@ -219,6 +219,7 @@ static inline void radix_tree_replace_slot(void **pslot, void *item)
 int radix_tree_insert(struct radix_tree_root *, unsigned long, void *);
 void *radix_tree_lookup(struct radix_tree_root *, unsigned long);
 void **radix_tree_lookup_slot(struct radix_tree_root *, unsigned long);
+void *radix_tree_delete_item(struct radix_tree_root *, unsigned long, void *);
 void *radix_tree_delete(struct radix_tree_root *, unsigned long);
 unsigned int
 radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
index bd4a8dfdf0b8052cdaedd0b3478eea4138ac100a..d832117e7d94942328690f4b275a5e10b3d6f9b4 100644 (file)
@@ -1337,15 +1337,18 @@ static inline void radix_tree_shrink(struct radix_tree_root *root)
 }
 
 /**
- *     radix_tree_delete    -    delete an item from a radix tree
+ *     radix_tree_delete_item    -    delete an item from a radix tree
  *     @root:          radix tree root
  *     @index:         index key
+ *     @item:          expected item
  *
- *     Remove the item at @index from the radix tree rooted at @root.
+ *     Remove @item at @index from the radix tree rooted at @root.
  *
- *     Returns the address of the deleted item, or NULL if it was not present.
+ *     Returns the address of the deleted item, or NULL if it was not present
+ *     or the entry at the given @index was not @item.
  */
-void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
+void *radix_tree_delete_item(struct radix_tree_root *root,
+                            unsigned long index, void *item)
 {
        struct radix_tree_node *node = NULL;
        struct radix_tree_node *slot = NULL;
@@ -1380,6 +1383,11 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
        if (slot == NULL)
                goto out;
 
+       if (item && slot != item) {
+               slot = NULL;
+               goto out;
+       }
+
        /*
         * Clear all tags associated with the item to be deleted.
         * This way of doing it would be inefficient, but seldom is any set.
@@ -1424,6 +1432,21 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
 out:
        return slot;
 }
+EXPORT_SYMBOL(radix_tree_delete_item);
+
+/**
+ *     radix_tree_delete    -    delete an item from a radix tree
+ *     @root:          radix tree root
+ *     @index:         index key
+ *
+ *     Remove the item at @index from the radix tree rooted at @root.
+ *
+ *     Returns the address of the deleted item, or NULL if it was not present.
+ */
+void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
+{
+       return radix_tree_delete_item(root, index, NULL);
+}
 EXPORT_SYMBOL(radix_tree_delete);
 
 /**