Patch "radix-tree: fix race in gang lookup" has been added to the 3.10-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
radix-tree: fix race in gang lookup
to the 3.10-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
radix-tree-fix-race-in-gang-lookup.patch
and it can be found in the queue-3.10 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
46437f9a554fbe3e110580ca08ab703b59f2f95aMon Sep 17 00:00:00 2001
From: Matthew Wilcox <[email protected]>
Date: Tue, 2 Feb 2016 16:57:52 -0800
Subject: radix-tree: fix race in gang lookup
From: Matthew Wilcox <[email protected]>
commit 46437f9a554fbe3e110580ca08ab703b59f2f95a upstream.
If the indirect_ptr bit is set on a slot, that indicates we need to redo the lookup. Introduce a new function radix_tree_iter_retry() which forces the loop to retry the lookup by setting 'slot' to NULL and turning the iterator back to point at the problematic entry.
This is a pretty rare problem to hit at the moment; the lookup has to race with a grow of the radix tree from a height of 0. The consequences of hitting this race are that gang lookup could return a pointer to a radix_tree_node instead of a pointer to whatever the user had inserted in the tree.
--- include/linux/radix-tree.h | 16 ++++++++++++++++ lib/radix-tree.c | 12 ++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-)
include/linux/radix-tree.h +16 -0
@@ -322,6 +322,22 @@ void **radix_tree_next_chunk(struct radi struct radix_tree_iter *iter, unsigned flags);/** +* radix_tree_iter_retry - retry this chunk of the iteration +* @iter: iterator state +* +* If we iterate over a tree protected only by the RCU lock, a race +* against deletion or creation may result in seeing a slot for which +* radix_tree_deref_retry() returns true. If so, call this function +* and continue the iteration. +*/ +static inline __must_check +void **radix_tree_iter_retry (struct radix_tree_iter *iter) +{ + iter->next_index = iter->index; +return NULL ; +} + +/** * radix_tree_chunk_size - get current chunk size * * @iter: pointer to radix tree iterator
lib/radix-tree.c +10 -2
@@ -1015,9 +1015,13 @@ radix_tree_gang_lookup(struct radix_treereturn 0 ;radix_tree_for_each_slot (slot, root, &iter, first_index) { - results[ret] =indirect_to_ptr (rcu_dereference_raw (*slot)); + results[ret] =rcu_dereference_raw (*slot);if (!results[ret])continue ; +if (radix_tree_is_indirect_ptr (results[ret])) { + slot =radix_tree_iter_retry (&iter); +continue ; + }if (++ret == max_items)break ; }
@@ -1094,9 +1098,13 @@ radix_tree_gang_lookup_tag(struct radix_return 0 ;radix_tree_for_each_tagged (slot, root, &iter, first_index, tag) { - results[ret] =indirect_to_ptr (rcu_dereference_raw (*slot)); + results[ret] =rcu_dereference_raw (*slot);if (!results[ret])continue ; +if (radix_tree_is_indirect_ptr (results[ret])) { + slot =radix_tree_iter_retry (&iter); +continue ; + }if (++ret == max_items)break ; }
Patches currently in stable-queue which might be from [email protected] are
queue-3.10/radix-tree-fix-oops-after-radix_tree_iter_retry.patch queue-3.10/radix-tree-fix-race-in-gang-lookup.patch