From: Nick Piggin Signed-off-by: Andrew Morton --- include/linux/radix-tree.h | 15 ++++++++------- lib/radix-tree.c | 9 +++++---- 2 files changed, 13 insertions(+), 11 deletions(-) diff -puN include/linux/radix-tree.h~redo-radix-tree-fixes include/linux/radix-tree.h --- a/include/linux/radix-tree.h~redo-radix-tree-fixes +++ a/include/linux/radix-tree.h @@ -67,18 +67,19 @@ static inline int radix_tree_is_direct_p return (int)((unsigned long)ptr & RADIX_TREE_DIRECT_PTR); } -static inline void *__radix_tree_deref_slot(void **slot) +static inline void *radix_tree_deref_slot(void *pslot) { - return rcu_dereference(radix_tree_direct_to_ptr(*slot)); + void *slot = *(void **)pslot; + return rcu_dereference(radix_tree_direct_to_ptr(slot)); } -#define radix_tree_deref_slot(slot) __radix_tree_deref_slot((void **)slot) - -static inline void radix_tree_replace_slot(void **slot, void *item) +static inline void radix_tree_replace_slot(void *pslot, void *item) { + void *slot = *(void **)pslot; BUG_ON(radix_tree_is_direct_ptr(item)); - rcu_assign_pointer(*slot, - (void *)((unsigned long)item | ((unsigned long)*slot & RADIX_TREE_DIRECT_PTR))); + rcu_assign_pointer(slot, + (void *)((unsigned long)item | + ((unsigned long)slot & RADIX_TREE_DIRECT_PTR))); } int radix_tree_insert(struct radix_tree_root *, unsigned long, void *); diff -puN lib/radix-tree.c~redo-radix-tree-fixes lib/radix-tree.c --- a/lib/radix-tree.c~redo-radix-tree-fixes +++ a/lib/radix-tree.c @@ -607,8 +607,8 @@ __lookup(struct radix_tree_node *slot, v for ( ; height > 1; height--) { struct radix_tree_node *__s; - for (i = (index >> shift) & RADIX_TREE_MAP_MASK ; - i < RADIX_TREE_MAP_SIZE; i++) { + i = (index >> shift) & RADIX_TREE_MAP_MASK ; + for (;;) { __s = rcu_dereference(slot->slots[i]); if (__s != NULL) break; @@ -616,9 +616,10 @@ __lookup(struct radix_tree_node *slot, v index += 1UL << shift; if (index == 0) goto out; /* 32-bit wraparound */ + i++; + if (i == RADIX_TREE_MAP_SIZE) + goto out; } - if (i == RADIX_TREE_MAP_SIZE) - goto out; shift -= RADIX_TREE_MAP_SHIFT; slot = __s; _