]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - lib/idr.c
kernel/compat.c: make do_sysinfo() static
[karo-tx-linux.git] / lib / idr.c
index 322e2816f2fb6fe67b512bb4329c49e7377c1591..cca4b9302a710c5ef0e1a66355302040ada9d3d7 100644 (file)
--- 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