Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jbarnes...
[safe/jmp/linux-2.6] / include / linux / idr.h
index 7fb3ff9..e968db7 100644 (file)
@@ -8,8 +8,14 @@
  * Small id to pointer translation service avoiding fixed sized
  * tables.
  */
+
+#ifndef __IDR_H__
+#define __IDR_H__
+
 #include <linux/types.h>
 #include <linux/bitops.h>
+#include <linux/init.h>
+#include <linux/rcupdate.h>
 
 #if BITS_PER_LONG == 32
 # define IDR_BITS 5
@@ -46,12 +52,14 @@ struct idr_layer {
        unsigned long            bitmap; /* A zero bit means "space here" */
        struct idr_layer        *ary[1<<IDR_BITS];
        int                      count;  /* When zero, we can release it */
+       int                      layer;  /* distance from leaf */
+       struct rcu_head          rcu_head;
 };
 
 struct idr {
        struct idr_layer *top;
        struct idr_layer *id_free;
-       int               layers;
+       int               layers; /* only valid without concurrent changes */
        int               id_free_cnt;
        spinlock_t        lock;
 };
@@ -62,10 +70,32 @@ struct idr {
        .id_free        = NULL,                                 \
        .layers         = 0,                                    \
        .id_free_cnt    = 0,                                    \
-       .lock           = SPIN_LOCK_UNLOCKED,                   \
+       .lock           = __SPIN_LOCK_UNLOCKED(name.lock),      \
 }
 #define DEFINE_IDR(name)       struct idr name = IDR_INIT(name)
 
+/* Actions to be taken after a call to _idr_sub_alloc */
+#define IDR_NEED_TO_GROW -2
+#define IDR_NOMORE_SPACE -3
+
+#define _idr_rc_to_errno(rc) ((rc) == -1 ? -EAGAIN : -ENOSPC)
+
+/**
+ * idr synchronization (stolen from radix-tree.h)
+ *
+ * idr_find() is able to be called locklessly, using RCU. The caller must
+ * ensure calls to this function are made within rcu_read_lock() regions.
+ * Other readers (lock-free or otherwise) and modifications may be running
+ * concurrently.
+ *
+ * It is still required that the caller manage the synchronization and
+ * lifetimes of the items. So if RCU lock-free lookups are used, typically
+ * this would mean that the items have their own locks, or are amenable to
+ * lock-free access; and that the items are freed by RCU (or only freed after
+ * having been deleted from the idr tree *and* a synchronize_rcu() grace
+ * period).
+ */
+
 /*
  * This is what we export.
  */
@@ -74,6 +104,44 @@ void *idr_find(struct idr *idp, int id);
 int idr_pre_get(struct idr *idp, gfp_t gfp_mask);
 int idr_get_new(struct idr *idp, void *ptr, int *id);
 int idr_get_new_above(struct idr *idp, void *ptr, int starting_id, int *id);
+int idr_for_each(struct idr *idp,
+                int (*fn)(int id, void *p, void *data), void *data);
+void *idr_get_next(struct idr *idp, int *nextid);
+void *idr_replace(struct idr *idp, void *ptr, int id);
 void idr_remove(struct idr *idp, int id);
+void idr_remove_all(struct idr *idp);
 void idr_destroy(struct idr *idp);
 void idr_init(struct idr *idp);
+
+
+/*
+ * IDA - IDR based id allocator, use when translation from id to
+ * pointer isn't necessary.
+ */
+#define IDA_CHUNK_SIZE         128     /* 128 bytes per chunk */
+#define IDA_BITMAP_LONGS       (128 / sizeof(long) - 1)
+#define IDA_BITMAP_BITS                (IDA_BITMAP_LONGS * sizeof(long) * 8)
+
+struct ida_bitmap {
+       long                    nr_busy;
+       unsigned long           bitmap[IDA_BITMAP_LONGS];
+};
+
+struct ida {
+       struct idr              idr;
+       struct ida_bitmap       *free_bitmap;
+};
+
+#define IDA_INIT(name)         { .idr = IDR_INIT(name), .free_bitmap = NULL, }
+#define DEFINE_IDA(name)       struct ida name = IDA_INIT(name)
+
+int ida_pre_get(struct ida *ida, gfp_t gfp_mask);
+int ida_get_new_above(struct ida *ida, int starting_id, int *p_id);
+int ida_get_new(struct ida *ida, int *p_id);
+void ida_remove(struct ida *ida, int id);
+void ida_destroy(struct ida *ida);
+void ida_init(struct ida *ida);
+
+void __init idr_init_cache(void);
+
+#endif /* __IDR_H__ */