]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
idr: implement idr_preload[_end]() and idr_alloc()
authorTejun Heo <tj@kernel.org>
Wed, 20 Feb 2013 02:16:09 +0000 (13:16 +1100)
committerStephen Rothwell <sfr@canb.auug.org.au>
Wed, 20 Feb 2013 05:53:43 +0000 (16:53 +1100)
v3: In idr_alloc() treat @end <= 0 as indicating max.  This is
    necessary to always allow using @start + N as @end for a positive
    integer N.

Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
lib/idr.c

index 511570584b2f89a257887e05ad6292b48e2d8b06..2d016f5c410ee0c32baaf0731eb8f2af0ed057da 100644 (file)
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -439,13 +439,16 @@ EXPORT_SYMBOL(idr_preload);
  * @idr: the (initialized) idr
  * @ptr: pointer to be associated with the new id
  * @start: the minimum id (inclusive)
- * @end: the maximum id (exclusive, 0 for max)
+ * @end: the maximum id (exclusive, <= 0 for max)
  * @gfp_mask: memory allocation flags
  *
  * Allocate an id in [start, end) and associate it with @ptr.  If no ID is
  * available in the specified range, returns -ENOSPC.  On memory allocation
  * failure, returns -ENOMEM.
  *
+ * Note that @end is treated as max when <= 0.  This is to always allow
+ * using @start + N as @end as long as N is inside integer range.
+ *
  * The user is responsible for exclusively synchronizing all operations
  * which may modify @idr.  However, read-only accesses such as idr_find()
  * or iteration can be performed under RCU read lock provided the user
@@ -453,14 +456,14 @@ EXPORT_SYMBOL(idr_preload);
  */
 int idr_alloc(struct idr *idr, void *ptr, int start, int end, gfp_t gfp_mask)
 {
-       int max = end ? end - 1 : INT_MAX;      /* inclusive upper limit */
+       int max = end > 0 ? end - 1 : INT_MAX;  /* inclusive upper limit */
        struct idr_layer *pa[MAX_IDR_LEVEL];
        int id;
 
        might_sleep_if(gfp_mask & __GFP_WAIT);
 
        /* sanity checks */
-       if (WARN_ON_ONCE(start < 0 || end < 0))
+       if (WARN_ON_ONCE(start < 0))
                return -EINVAL;
        if (unlikely(max < start))
                return -ENOSPC;