Commit 50c4613d2293063a18c05dccfc8f4335be21b3e4

Authored by Johannes Weiner
Committed by Jiri Slaby
1 parent c05ac84a85

lib: radix-tree: add radix_tree_delete_item()

commit 53c59f262d747ea82e7414774c59a489501186a0 upstream.

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 <hannes@cmpxchg.org>
Reviewed-by: Minchan Kim <minchan@kernel.org>
Reviewed-by: Rik van Riel <riel@redhat.com>
Acked-by: Mel Gorman <mgorman@suse.de>
Cc: Andrea Arcangeli <aarcange@redhat.com>
Cc: Bob Liu <bob.liu@oracle.com>
Cc: Christoph Hellwig <hch@infradead.org>
Cc: Dave Chinner <david@fromorbit.com>
Cc: Greg Thelen <gthelen@google.com>
Cc: Hugh Dickins <hughd@google.com>
Cc: Jan Kara <jack@suse.cz>
Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Cc: Luigi Semenzato <semenzato@google.com>
Cc: Metin Doslu <metin@citusdata.com>
Cc: Michel Lespinasse <walken@google.com>
Cc: Ozgun Erdogan <ozgun@citusdata.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Roman Gushchin <klamm@yandex-team.ru>
Cc: Ryan Mallon <rmallon@gmail.com>
Cc: Tejun Heo <tj@kernel.org>
Cc: Vlastimil Babka <vbabka@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Signed-off-by: Mel Gorman <mgorman@suse.de>
Signed-off-by: Jiri Slaby <jslaby@suse.cz>

Showing 2 changed files with 28 additions and 4 deletions Side-by-side Diff

include/linux/radix-tree.h
... ... @@ -219,6 +219,7 @@
219 219 int radix_tree_insert(struct radix_tree_root *, unsigned long, void *);
220 220 void *radix_tree_lookup(struct radix_tree_root *, unsigned long);
221 221 void **radix_tree_lookup_slot(struct radix_tree_root *, unsigned long);
  222 +void *radix_tree_delete_item(struct radix_tree_root *, unsigned long, void *);
222 223 void *radix_tree_delete(struct radix_tree_root *, unsigned long);
223 224 unsigned int
224 225 radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
... ... @@ -1335,15 +1335,18 @@
1335 1335 }
1336 1336  
1337 1337 /**
1338   - * radix_tree_delete - delete an item from a radix tree
  1338 + * radix_tree_delete_item - delete an item from a radix tree
1339 1339 * @root: radix tree root
1340 1340 * @index: index key
  1341 + * @item: expected item
1341 1342 *
1342   - * Remove the item at @index from the radix tree rooted at @root.
  1343 + * Remove @item at @index from the radix tree rooted at @root.
1343 1344 *
1344   - * Returns the address of the deleted item, or NULL if it was not present.
  1345 + * Returns the address of the deleted item, or NULL if it was not present
  1346 + * or the entry at the given @index was not @item.
1345 1347 */
1346   -void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
  1348 +void *radix_tree_delete_item(struct radix_tree_root *root,
  1349 + unsigned long index, void *item)
1347 1350 {
1348 1351 struct radix_tree_node *node = NULL;
1349 1352 struct radix_tree_node *slot = NULL;
... ... @@ -1378,6 +1381,11 @@
1378 1381 if (slot == NULL)
1379 1382 goto out;
1380 1383  
  1384 + if (item && slot != item) {
  1385 + slot = NULL;
  1386 + goto out;
  1387 + }
  1388 +
1381 1389 /*
1382 1390 * Clear all tags associated with the item to be deleted.
1383 1391 * This way of doing it would be inefficient, but seldom is any set.
... ... @@ -1421,6 +1429,21 @@
1421 1429  
1422 1430 out:
1423 1431 return slot;
  1432 +}
  1433 +EXPORT_SYMBOL(radix_tree_delete_item);
  1434 +
  1435 +/**
  1436 + * radix_tree_delete - delete an item from a radix tree
  1437 + * @root: radix tree root
  1438 + * @index: index key
  1439 + *
  1440 + * Remove the item at @index from the radix tree rooted at @root.
  1441 + *
  1442 + * Returns the address of the deleted item, or NULL if it was not present.
  1443 + */
  1444 +void *radix_tree_delete(struct radix_tree_root *root, unsigned long index)
  1445 +{
  1446 + return radix_tree_delete_item(root, index, NULL);
1424 1447 }
1425 1448 EXPORT_SYMBOL(radix_tree_delete);
1426 1449