[PATCH 03/13] This patch only fixes the ridr_pre_get() portion of ridr.c, to introduce a per-cpu pool of preloaded ridr layer structures, and define the ridr_pre_get[_end]() routines. Signed-off-by: Nadia Derbey --- include/linux/ridr.h | 7 ++++++- lib/ridr.c | 50 ++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 42 insertions(+), 15 deletions(-) Index: linux-2.6.25-rc8-mm1/include/linux/ridr.h =================================================================== --- linux-2.6.25-rc8-mm1.orig/include/linux/ridr.h 2008-04-11 17:34:35.000000000 +0200 +++ linux-2.6.25-rc8-mm1/include/linux/ridr.h 2008-04-11 17:41:20.000000000 +0200 @@ -61,10 +61,15 @@ do { \ */ void *ridr_find(struct ridr *idp, int id); -int ridr_pre_get(struct ridr *idp, gfp_t gfp_mask); +int ridr_pre_get(gfp_t gfp_mask); int ridr_get_new(struct ridr *idp, void *ptr, int *id); void ridr_remove(struct ridr *idp, int id); void __init ridr_init_cache(void); +static inline void ridr_pre_get_end(void) +{ + preempt_enable(); +} + #endif /* _RIDR_H_ */ Index: linux-2.6.25-rc8-mm1/lib/ridr.c =================================================================== --- linux-2.6.25-rc8-mm1.orig/lib/ridr.c 2008-04-11 17:30:28.000000000 +0200 +++ linux-2.6.25-rc8-mm1/lib/ridr.c 2008-04-11 17:40:13.000000000 +0200 @@ -13,6 +13,15 @@ static struct kmem_cache *ridr_layer_cache; +/* + * Per-cpu pool of preloaded layers + */ +struct ridr_preget { + int nr; + struct ridr_layer *layers[MAX_LEVEL]; +}; +DEFINE_PER_CPU(struct ridr_preget, ridr_pregets) = { 0, }; + static struct ridr_layer *alloc_layer(struct ridr *idp) { struct ridr_layer *p; @@ -75,23 +84,36 @@ static void ridr_mark_full(struct ridr_l * @idp: ridr handle * @gfp_mask: memory allocation flags * - * This function should be called prior to locking and calling the - * following function. It preallocates enough memory to satisfy - * the worst possible allocation. + * Load up this CPU's ridr_layer buffer with sufficient objects to + * ensure that the addition of a single element in the tree cannot fail. * - * If the system is REALLY out of memory this function returns 0, - * otherwise 1. + * If the system is REALLY out of memory this function returns 0, with + * preemption enabled. + * Otherwise 1, with preemption disabled. */ -int ridr_pre_get(struct ridr *idp, gfp_t gfp_mask) +int ridr_pre_get(gfp_t gfp_mask) { - while (idp->id_free_cnt < IDR_FREE_MAX) { - struct ridr_layer *new; - new = kmem_cache_alloc(ridr_layer_cache, gfp_mask); - if (new == NULL) - return (0); - free_layer(idp, new); - } - return 1; + struct ridr_preget *idp; + struct ridr_layer *layer; + int ret = 0; + + preempt_disable(); + idp = &__get_cpu_var(ridr_pregets); + while (idp->nr < ARRAY_SIZE(idp->layers)) { + preempt_enable(); + layer = kmem_cache_alloc(ridr_layer_cache, gfp_mask); + if (layer == NULL) + goto out; + preempt_disable(); + idp = &__get_cpu_var(ridr_pregets); + if (idp->nr < ARRAY_SIZE(idp->layers)) + idp->layers[idp->nr++] = layer; + else + kmem_cache_free(ridr_layer_cache, layer); + } + ret = 1; +out: + return ret; } EXPORT_SYMBOL(ridr_pre_get); -- -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/