summaryrefslogtreecommitdiffstats
path: root/kernel/include/linux/radix-tree.h
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/include/linux/radix-tree.h')
-rw-r--r--kernel/include/linux/radix-tree.h22
1 files changed, 19 insertions, 3 deletions
diff --git a/kernel/include/linux/radix-tree.h b/kernel/include/linux/radix-tree.h
index 933ff6977..8ddbd6e15 100644
--- a/kernel/include/linux/radix-tree.h
+++ b/kernel/include/linux/radix-tree.h
@@ -375,12 +375,28 @@ void **radix_tree_next_chunk(struct radix_tree_root *root,
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
* Returns: current chunk size
*/
-static __always_inline unsigned
+static __always_inline long
radix_tree_chunk_size(struct radix_tree_iter *iter)
{
return iter->next_index - iter->index;
@@ -414,9 +430,9 @@ radix_tree_next_slot(void **slot, struct radix_tree_iter *iter, unsigned flags)
return slot + offset + 1;
}
} else {
- unsigned size = radix_tree_chunk_size(iter) - 1;
+ long size = radix_tree_chunk_size(iter);
- while (size--) {
+ while (--size > 0) {
slot++;
iter->index++;
if (likely(*slot))