X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=lib%2Fradix-tree.c;h=65f0e758ec3819d57f1799e5563a9f90dc0e41eb;hb=3d7e6cf8f5837c6dace759734c987e03021a4015;hp=53fd44d78716cfb3d0b9f77c1372737e49a1a12b;hpb=4ba9b9d0ba0a49d91fa6417c7510ee36f48cf957;p=linux-2.6 diff --git a/lib/radix-tree.c b/lib/radix-tree.c index 53fd44d787..65f0e758ec 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c @@ -95,14 +95,17 @@ static inline gfp_t root_gfp_mask(struct radix_tree_root *root) static struct radix_tree_node * radix_tree_node_alloc(struct radix_tree_root *root) { - struct radix_tree_node *ret; + struct radix_tree_node *ret = NULL; gfp_t gfp_mask = root_gfp_mask(root); - ret = kmem_cache_alloc(radix_tree_node_cachep, - set_migrateflags(gfp_mask, __GFP_RECLAIMABLE)); - if (ret == NULL && !(gfp_mask & __GFP_WAIT)) { + if (!(gfp_mask & __GFP_WAIT)) { struct radix_tree_preload *rtp; + /* + * Provided the caller has preloaded here, we will always + * succeed in getting a node here (and never reach + * kmem_cache_alloc) + */ rtp = &__get_cpu_var(radix_tree_preloads); if (rtp->nr) { ret = rtp->nodes[rtp->nr - 1]; @@ -110,6 +113,10 @@ radix_tree_node_alloc(struct radix_tree_root *root) rtp->nr--; } } + if (ret == NULL) + ret = kmem_cache_alloc(radix_tree_node_cachep, + set_migrateflags(gfp_mask, __GFP_RECLAIMABLE)); + BUG_ON(radix_tree_is_indirect_ptr(ret)); return ret; } @@ -1049,12 +1056,14 @@ radix_tree_node_ctor(struct kmem_cache *cachep, void *node) static __init unsigned long __maxindex(unsigned int height) { - unsigned int tmp = height * RADIX_TREE_MAP_SHIFT; - unsigned long index = (~0UL >> (RADIX_TREE_INDEX_BITS - tmp - 1)) >> 1; - - if (tmp >= RADIX_TREE_INDEX_BITS) - index = ~0UL; - return index; + unsigned int width = height * RADIX_TREE_MAP_SHIFT; + int shift = RADIX_TREE_INDEX_BITS - width; + + if (shift < 0) + return ~0UL; + if (shift >= BITS_PER_LONG) + return 0UL; + return ~0UL >> shift; } static __init void radix_tree_init_maxindex(void)