aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Wilcox <willy@infradead.org>2018-03-20 17:07:11 -0400
committerMatthew Wilcox <willy@infradead.org>2018-08-21 23:54:13 -0400
commit5ade60dda43c8906d4554374226c2eb11cc2ffba (patch)
treead246f964d28e84a4c18c0cae666bb434b30b873
parent50d97d50715a8664f6bddc18211279cd74b8c3bf (diff)
ida: Add new API
Add ida_alloc(), ida_alloc_min(), ida_alloc_max(), ida_alloc_range() and ida_free(). The ida_alloc_max() and ida_alloc_range() functions differ from ida_simple_get() in that they take an inclusive 'max' parameter instead of an exclusive 'end' parameter. Callers are about evenly split whether they'd like inclusive or exclusive parameters and 'max' is easier to document than 'end'. Change the IDA allocation to first attempt to allocate a bit using existing memory, and only allocate memory afterwards. Also change the behaviour of 'min' > INT_MAX from being a BUG() to returning -ENOSPC. Leave compatibility wrappers in place for ida_simple_get() and ida_simple_remove() to avoid changing all callers. Signed-off-by: Matthew Wilcox <willy@infradead.org>
-rw-r--r--include/linux/idr.h59
-rw-r--r--lib/idr.c70
2 files changed, 87 insertions, 42 deletions
diff --git a/include/linux/idr.h b/include/linux/idr.h
index e856f4e0ab35..cd339da0b1aa 100644
--- a/include/linux/idr.h
+++ b/include/linux/idr.h
@@ -230,15 +230,68 @@ int ida_get_new_above(struct ida *ida, int starting_id, int *p_id);
230void ida_remove(struct ida *ida, int id); 230void ida_remove(struct ida *ida, int id);
231void ida_destroy(struct ida *ida); 231void ida_destroy(struct ida *ida);
232 232
233int ida_simple_get(struct ida *ida, unsigned int start, unsigned int end, 233int ida_alloc_range(struct ida *, unsigned int min, unsigned int max, gfp_t);
234 gfp_t gfp_mask); 234void ida_free(struct ida *, unsigned int id);
235void ida_simple_remove(struct ida *ida, unsigned int id); 235
236/**
237 * ida_alloc() - Allocate an unused ID.
238 * @ida: IDA handle.
239 * @gfp: Memory allocation flags.
240 *
241 * Allocate an ID between 0 and %INT_MAX, inclusive.
242 *
243 * Context: Any context.
244 * Return: The allocated ID, or %-ENOMEM if memory could not be allocated,
245 * or %-ENOSPC if there are no free IDs.
246 */
247static inline int ida_alloc(struct ida *ida, gfp_t gfp)
248{
249 return ida_alloc_range(ida, 0, ~0, gfp);
250}
251
252/**
253 * ida_alloc_min() - Allocate an unused ID.
254 * @ida: IDA handle.
255 * @min: Lowest ID to allocate.
256 * @gfp: Memory allocation flags.
257 *
258 * Allocate an ID between @min and %INT_MAX, inclusive.
259 *
260 * Context: Any context.
261 * Return: The allocated ID, or %-ENOMEM if memory could not be allocated,
262 * or %-ENOSPC if there are no free IDs.
263 */
264static inline int ida_alloc_min(struct ida *ida, unsigned int min, gfp_t gfp)
265{
266 return ida_alloc_range(ida, min, ~0, gfp);
267}
268
269/**
270 * ida_alloc_max() - Allocate an unused ID.
271 * @ida: IDA handle.
272 * @max: Highest ID to allocate.
273 * @gfp: Memory allocation flags.
274 *
275 * Allocate an ID between 0 and @max, inclusive.
276 *
277 * Context: Any context.
278 * Return: The allocated ID, or %-ENOMEM if memory could not be allocated,
279 * or %-ENOSPC if there are no free IDs.
280 */
281static inline int ida_alloc_max(struct ida *ida, unsigned int max, gfp_t gfp)
282{
283 return ida_alloc_range(ida, 0, max, gfp);
284}
236 285
237static inline void ida_init(struct ida *ida) 286static inline void ida_init(struct ida *ida)
238{ 287{
239 INIT_RADIX_TREE(&ida->ida_rt, IDR_RT_MARKER | GFP_NOWAIT); 288 INIT_RADIX_TREE(&ida->ida_rt, IDR_RT_MARKER | GFP_NOWAIT);
240} 289}
241 290
291#define ida_simple_get(ida, start, end, gfp) \
292 ida_alloc_range(ida, start, (end) - 1, gfp)
293#define ida_simple_remove(ida, id) ida_free(ida, id)
294
242/** 295/**
243 * ida_get_new - allocate new ID 296 * ida_get_new - allocate new ID
244 * @ida: idr handle 297 * @ida: idr handle
diff --git a/lib/idr.c b/lib/idr.c
index 352c6160e2e0..760fce92f1fb 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -317,7 +317,8 @@ EXPORT_SYMBOL(idr_replace);
317 * bit per ID, and so is more space efficient than an IDR. To use an IDA, 317 * bit per ID, and so is more space efficient than an IDR. To use an IDA,
318 * define it using DEFINE_IDA() (or embed a &struct ida in a data structure, 318 * define it using DEFINE_IDA() (or embed a &struct ida in a data structure,
319 * then initialise it using ida_init()). To allocate a new ID, call 319 * then initialise it using ida_init()). To allocate a new ID, call
320 * ida_simple_get(). To free an ID, call ida_simple_remove(). 320 * ida_alloc(), ida_alloc_min(), ida_alloc_max() or ida_alloc_range().
321 * To free an ID, call ida_free().
321 * 322 *
322 * If you have more complex locking requirements, use a loop around 323 * If you have more complex locking requirements, use a loop around
323 * ida_pre_get() and ida_get_new() to allocate a new ID. Then use 324 * ida_pre_get() and ida_get_new() to allocate a new ID. Then use
@@ -378,7 +379,7 @@ EXPORT_SYMBOL(idr_replace);
378 * Allocate new ID above or equal to @start. It should be called 379 * Allocate new ID above or equal to @start. It should be called
379 * with any required locks to ensure that concurrent calls to 380 * with any required locks to ensure that concurrent calls to
380 * ida_get_new_above() / ida_get_new() / ida_remove() are not allowed. 381 * ida_get_new_above() / ida_get_new() / ida_remove() are not allowed.
381 * Consider using ida_simple_get() if you do not have complex locking 382 * Consider using ida_alloc_range() if you do not have complex locking
382 * requirements. 383 * requirements.
383 * 384 *
384 * If memory is required, it will return %-EAGAIN, you should unlock 385 * If memory is required, it will return %-EAGAIN, you should unlock
@@ -551,43 +552,34 @@ void ida_destroy(struct ida *ida)
551EXPORT_SYMBOL(ida_destroy); 552EXPORT_SYMBOL(ida_destroy);
552 553
553/** 554/**
554 * ida_simple_get - get a new id. 555 * ida_alloc_range() - Allocate an unused ID.
555 * @ida: the (initialized) ida. 556 * @ida: IDA handle.
556 * @start: the minimum id (inclusive, < 0x8000000) 557 * @min: Lowest ID to allocate.
557 * @end: the maximum id (exclusive, < 0x8000000 or 0) 558 * @max: Highest ID to allocate.
558 * @gfp_mask: memory allocation flags 559 * @gfp: Memory allocation flags.
559 *
560 * Allocates an id in the range start <= id < end, or returns -ENOSPC.
561 * On memory allocation failure, returns -ENOMEM.
562 * 560 *
563 * Compared to ida_get_new_above() this function does its own locking, and 561 * Allocate an ID between @min and @max, inclusive. The allocated ID will
564 * should be used unless there are special requirements. 562 * not exceed %INT_MAX, even if @max is larger.
565 * 563 *
566 * Use ida_simple_remove() to get rid of an id. 564 * Context: Any context.
565 * Return: The allocated ID, or %-ENOMEM if memory could not be allocated,
566 * or %-ENOSPC if there are no free IDs.
567 */ 567 */
568int ida_simple_get(struct ida *ida, unsigned int start, unsigned int end, 568int ida_alloc_range(struct ida *ida, unsigned int min, unsigned int max,
569 gfp_t gfp_mask) 569 gfp_t gfp)
570{ 570{
571 int ret, id; 571 int ret, id;
572 unsigned int max;
573 unsigned long flags; 572 unsigned long flags;
574 573
575 BUG_ON((int)start < 0); 574 if ((int)min < 0)
576 BUG_ON((int)end < 0); 575 return -ENOSPC;
577 576
578 if (end == 0) 577 if ((int)max < 0)
579 max = 0x80000000; 578 max = INT_MAX;
580 else {
581 BUG_ON(end < start);
582 max = end - 1;
583 }
584 579
585again: 580again:
586 if (!ida_pre_get(ida, gfp_mask))
587 return -ENOMEM;
588
589 xa_lock_irqsave(&ida->ida_rt, flags); 581 xa_lock_irqsave(&ida->ida_rt, flags);
590 ret = ida_get_new_above(ida, start, &id); 582 ret = ida_get_new_above(ida, min, &id);
591 if (!ret) { 583 if (!ret) {
592 if (id > max) { 584 if (id > max) {
593 ida_remove(ida, id); 585 ida_remove(ida, id);
@@ -598,24 +590,24 @@ again:
598 } 590 }
599 xa_unlock_irqrestore(&ida->ida_rt, flags); 591 xa_unlock_irqrestore(&ida->ida_rt, flags);
600 592
601 if (unlikely(ret == -EAGAIN)) 593 if (unlikely(ret == -EAGAIN)) {
594 if (!ida_pre_get(ida, gfp))
595 return -ENOMEM;
602 goto again; 596 goto again;
597 }
603 598
604 return ret; 599 return ret;
605} 600}
606EXPORT_SYMBOL(ida_simple_get); 601EXPORT_SYMBOL(ida_alloc_range);
607 602
608/** 603/**
609 * ida_simple_remove - remove an allocated id. 604 * ida_free() - Release an allocated ID.
610 * @ida: the (initialized) ida. 605 * @ida: IDA handle.
611 * @id: the id returned by ida_simple_get. 606 * @id: Previously allocated ID.
612 *
613 * Use to release an id allocated with ida_simple_get().
614 * 607 *
615 * Compared to ida_remove() this function does its own locking, and should be 608 * Context: Any context.
616 * used unless there are special requirements.
617 */ 609 */
618void ida_simple_remove(struct ida *ida, unsigned int id) 610void ida_free(struct ida *ida, unsigned int id)
619{ 611{
620 unsigned long flags; 612 unsigned long flags;
621 613
@@ -624,4 +616,4 @@ void ida_simple_remove(struct ida *ida, unsigned int id)
624 ida_remove(ida, id); 616 ida_remove(ida, id);
625 xa_unlock_irqrestore(&ida->ida_rt, flags); 617 xa_unlock_irqrestore(&ida->ida_rt, flags);
626} 618}
627EXPORT_SYMBOL(ida_simple_remove); 619EXPORT_SYMBOL(ida_free);