[PATCH] allow delayed freeing of ctl_table_header
[pandora-kernel.git] / include / linux / idr.h
index 8268034..fa035f9 100644 (file)
@@ -14,6 +14,8 @@
 
 #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
@@ -50,6 +52,7 @@ 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 */
+       struct rcu_head          rcu_head;
 };
 
 struct idr {
@@ -70,6 +73,28 @@ struct idr {
 }
 #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.
  */
@@ -78,9 +103,43 @@ 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_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__ */