Signed-off-by: Mateusz Guzik --- include/linux/idr.h | 1 + lib/radix-tree.c | 19 +++++++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/include/linux/idr.h b/include/linux/idr.h index 789e23e67444..c9aeae695442 100644 --- a/include/linux/idr.h +++ b/include/linux/idr.h @@ -110,6 +110,7 @@ static inline void idr_set_cursor(struct idr *idr, unsigned int val) #define idr_unlock_irqrestore(idr, flags) \ xa_unlock_irqrestore(&(idr)->idr_rt, flags) +void idr_preload_many(int nr, gfp_t gfp_mask); void idr_preload(gfp_t gfp_mask); int idr_alloc(struct idr *, void *ptr, int start, int end, gfp_t); diff --git a/lib/radix-tree.c b/lib/radix-tree.c index 976b9bd02a1b..2e71024e5323 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c @@ -1459,6 +1459,22 @@ int radix_tree_tagged(const struct radix_tree_root *root, unsigned int tag) } EXPORT_SYMBOL(radix_tree_tagged); +/** + * idr_preload_many - preload for idr_alloc() + * @gfp_mask: allocation mask to use for preloading + * @nr: how many calls to preload for + * + * Preallocate memory to use for n calls to idr_alloc(). This function + * returns with preemption disabled. It will be enabled by idr_preload_end(). + */ +void idr_preload_many(int nr, gfp_t gfp_mask) +{ + WARN_ON_ONCE(!nr); + if (__radix_tree_preload(gfp_mask, nr * IDR_PRELOAD_SIZE)) + local_lock(&radix_tree_preloads.lock); +} +EXPORT_SYMBOL(idr_preload_many); + /** * idr_preload - preload for idr_alloc() * @gfp_mask: allocation mask to use for preloading @@ -1468,8 +1484,7 @@ EXPORT_SYMBOL(radix_tree_tagged); */ void idr_preload(gfp_t gfp_mask) { - if (__radix_tree_preload(gfp_mask, IDR_PRELOAD_SIZE)) - local_lock(&radix_tree_preloads.lock); + idr_preload_many(1, gfp_mask); } EXPORT_SYMBOL(idr_preload); -- 2.48.1