summaryrefslogtreecommitdiff
path: root/lib/idr.c
diff options
context:
space:
mode:
authorThomas Gleixner <tglx@linutronix.de>2013-05-05 08:24:42 +0200
committerThomas Gleixner <tglx@linutronix.de>2013-05-05 08:27:03 +0200
commitf99e44a7f3352d7131c7526207f153f13ec5acd4 (patch)
tree0f448b21128c478053ee7f7765b865954c4eebe8 /lib/idr.c
parentfd29f424d458118f02e89596505c68a63dcb3007 (diff)
parentce857229e0c3adc211944a13a5579ef84fd7b4af (diff)
Merge branch 'linus' into core/urgent
Update with Linus tree so fixes for the same can be applied. Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'lib/idr.c')
-rw-r--r--lib/idr.c27
1 files changed, 27 insertions, 0 deletions
diff --git a/lib/idr.c b/lib/idr.c
index 322e2816f2fb..cca4b9302a71 100644
--- a/lib/idr.c
+++ b/lib/idr.c
@@ -495,6 +495,33 @@ int idr_alloc(struct idr *idr, void *ptr, int start, int end, gfp_t gfp_mask)
}
EXPORT_SYMBOL_GPL(idr_alloc);
+/**
+ * idr_alloc_cyclic - allocate new idr entry in a cyclical fashion
+ * @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)
+ * @gfp_mask: memory allocation flags
+ *
+ * Essentially the same as idr_alloc, but prefers to allocate progressively
+ * higher ids if it can. If the "cur" counter wraps, then it will start again
+ * at the "start" end of the range and allocate one that has already been used.
+ */
+int idr_alloc_cyclic(struct idr *idr, void *ptr, int start, int end,
+ gfp_t gfp_mask)
+{
+ int id;
+
+ id = idr_alloc(idr, ptr, max(start, idr->cur), end, gfp_mask);
+ if (id == -ENOSPC)
+ id = idr_alloc(idr, ptr, start, end, gfp_mask);
+
+ if (likely(id >= 0))
+ idr->cur = id + 1;
+ return id;
+}
+EXPORT_SYMBOL(idr_alloc_cyclic);
+
static void idr_remove_warning(int id)
{
printk(KERN_WARNING