Skip to content

Commit 53c59f2

Browse files
hnaztorvalds
authored andcommitted
lib: radix-tree: add radix_tree_delete_item()
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]>
1 parent 55881bc commit 53c59f2

File tree

2 files changed

+28
-4
lines changed

2 files changed

+28
-4
lines changed

include/linux/radix-tree.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ static inline void radix_tree_replace_slot(void **pslot, void *item)
219219
int radix_tree_insert(struct radix_tree_root *, unsigned long, void *);
220220
void *radix_tree_lookup(struct radix_tree_root *, unsigned long);
221221
void **radix_tree_lookup_slot(struct radix_tree_root *, unsigned long);
222+
void *radix_tree_delete_item(struct radix_tree_root *, unsigned long, void *);
222223
void *radix_tree_delete(struct radix_tree_root *, unsigned long);
223224
unsigned int
224225
radix_tree_gang_lookup(struct radix_tree_root *root, void **results,

lib/radix-tree.c

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1337,15 +1337,18 @@ static inline void radix_tree_shrink(struct radix_tree_root *root)
13371337
}
13381338

13391339
/**
1340-
* radix_tree_delete - delete an item from a radix tree
1340+
* radix_tree_delete_item - delete an item from a radix tree
13411341
* @root: radix tree root
13421342
* @index: index key
1343+
* @item: expected item
13431344
*
1344-
* Remove the item at @index from the radix tree rooted at @root.
1345+
* Remove @item at @index from the radix tree rooted at @root.
13451346
*
1346-
* Returns the address of the deleted item, or NULL if it was not present.
1347+
* Returns the address of the deleted item, or NULL if it was not present
1348+
* or the entry at the given @index was not @item.
13471349
*/
1348-
void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
1350+
void *radix_tree_delete_item(struct radix_tree_root *root,
1351+
unsigned long index, void *item)
13491352
{
13501353
struct radix_tree_node *node = NULL;
13511354
struct radix_tree_node *slot = NULL;
@@ -1380,6 +1383,11 @@ void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
13801383
if (slot == NULL)
13811384
goto out;
13821385

1386+
if (item && slot != item) {
1387+
slot = NULL;
1388+
goto out;
1389+
}
1390+
13831391
/*
13841392
* Clear all tags associated with the item to be deleted.
13851393
* 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)
14241432
out:
14251433
return slot;
14261434
}
1435+
EXPORT_SYMBOL(radix_tree_delete_item);
1436+
1437+
/**
1438+
* radix_tree_delete - delete an item from a radix tree
1439+
* @root: radix tree root
1440+
* @index: index key
1441+
*
1442+
* Remove the item at @index from the radix tree rooted at @root.
1443+
*
1444+
* Returns the address of the deleted item, or NULL if it was not present.
1445+
*/
1446+
void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
1447+
{
1448+
return radix_tree_delete_item(root, index, NULL);
1449+
}
14271450
EXPORT_SYMBOL(radix_tree_delete);
14281451

14291452
/**

0 commit comments

Comments
 (0)