netfilter: nf_conntrack: pass template to l4proto ->error() handler
[safe/jmp/linux-2.6] / include / linux / radix-tree.h
index 430e4a8..c5da749 100644 (file)
 #include <linux/rcupdate.h>
 
 /*
- * A direct pointer (root->rnode pointing directly to a data item,
- * rather than another radix_tree_node) is signalled by the low bit
- * set in the root->rnode pointer.
+ * An indirect pointer (root->rnode pointing to a radix_tree_node, rather
+ * than a data item) is signalled by the low bit set in the root->rnode
+ * pointer.
  *
- * In this case root->height is also NULL, but the direct pointer tests are
- * needed for RCU lookups when root->height is unreliable.
+ * In this case root->height is > 0, but the indirect pointer tests are
+ * needed for RCU lookups (because root->height is unreliable). The only
+ * time callers need worry about this is when doing a lookup_slot under
+ * RCU.
  */
-#define RADIX_TREE_DIRECT_PTR  1
+#define RADIX_TREE_INDIRECT_PTR        1
+#define RADIX_TREE_RETRY ((void *)-1UL)
 
-static inline void *radix_tree_ptr_to_direct(void *ptr)
+static inline void *radix_tree_ptr_to_indirect(void *ptr)
 {
-       return (void *)((unsigned long)ptr | RADIX_TREE_DIRECT_PTR);
+       return (void *)((unsigned long)ptr | RADIX_TREE_INDIRECT_PTR);
 }
 
-static inline void *radix_tree_direct_to_ptr(void *ptr)
+static inline void *radix_tree_indirect_to_ptr(void *ptr)
 {
-       return (void *)((unsigned long)ptr & ~RADIX_TREE_DIRECT_PTR);
+       return (void *)((unsigned long)ptr & ~RADIX_TREE_INDIRECT_PTR);
 }
 
-static inline int radix_tree_is_direct_ptr(void *ptr)
+static inline int radix_tree_is_indirect_ptr(void *ptr)
 {
-       return (int)((unsigned long)ptr & RADIX_TREE_DIRECT_PTR);
+       return (int)((unsigned long)ptr & RADIX_TREE_INDIRECT_PTR);
 }
 
 /*** radix-tree API starts here ***/
@@ -88,7 +91,7 @@ do {                                                                  \
  *
  * For API usage, in general,
  * - any function _modifying_ the tree or tags (inserting or deleting
- *   items, setting or clearing tags must exclude other modifications, and
+ *   items, setting or clearing tags) must exclude other modifications, and
  *   exclude any functions reading the tree.
  * - any function _reading_ the tree or tags (looking up items or tags,
  *   gang lookups) must exclude modifications to the tree, but may occur
@@ -96,12 +99,15 @@ do {                                                                        \
  *
  * The notable exceptions to this rule are the following functions:
  * radix_tree_lookup
+ * radix_tree_lookup_slot
  * radix_tree_tag_get
  * radix_tree_gang_lookup
+ * radix_tree_gang_lookup_slot
  * radix_tree_gang_lookup_tag
+ * radix_tree_gang_lookup_tag_slot
  * radix_tree_tagged
  *
- * The first 4 functions are able to be called locklessly, using RCU. The
+ * The first 7 functions are able to be called locklessly, using RCU. The
  * caller must ensure calls to these functions are made within rcu_read_lock()
  * regions. Other readers (lock-free or otherwise) and modifications may be
  * running concurrently.
@@ -130,7 +136,10 @@ do {                                                                       \
  */
 static inline void *radix_tree_deref_slot(void **pslot)
 {
-       return radix_tree_direct_to_ptr(*pslot);
+       void *ret = rcu_dereference(*pslot);
+       if (unlikely(radix_tree_is_indirect_ptr(ret)))
+               ret = RADIX_TREE_RETRY;
+       return ret;
 }
 /**
  * radix_tree_replace_slot     - replace item in a slot
@@ -142,10 +151,8 @@ static inline void *radix_tree_deref_slot(void **pslot)
  */
 static inline void radix_tree_replace_slot(void **pslot, void *item)
 {
-       BUG_ON(radix_tree_is_direct_ptr(item));
-       rcu_assign_pointer(*pslot,
-               (void *)((unsigned long)item |
-                       ((unsigned long)*pslot & RADIX_TREE_DIRECT_PTR)));
+       BUG_ON(radix_tree_is_indirect_ptr(item));
+       rcu_assign_pointer(*pslot, item);
 }
 
 int radix_tree_insert(struct radix_tree_root *, unsigned long, void *);
@@ -155,8 +162,13 @@ void *radix_tree_delete(struct radix_tree_root *, unsigned long);
 unsigned int
 radix_tree_gang_lookup(struct radix_tree_root *root, void **results,
                        unsigned long first_index, unsigned int max_items);
+unsigned int
+radix_tree_gang_lookup_slot(struct radix_tree_root *root, void ***results,
+                       unsigned long first_index, unsigned int max_items);
 unsigned long radix_tree_next_hole(struct radix_tree_root *root,
                                unsigned long index, unsigned long max_scan);
+unsigned long radix_tree_prev_hole(struct radix_tree_root *root,
+                               unsigned long index, unsigned long max_scan);
 int radix_tree_preload(gfp_t gfp_mask);
 void radix_tree_init(void);
 void *radix_tree_tag_set(struct radix_tree_root *root,
@@ -169,6 +181,10 @@ unsigned int
 radix_tree_gang_lookup_tag(struct radix_tree_root *root, void **results,
                unsigned long first_index, unsigned int max_items,
                unsigned int tag);
+unsigned int
+radix_tree_gang_lookup_tag_slot(struct radix_tree_root *root, void ***results,
+               unsigned long first_index, unsigned int max_items,
+               unsigned int tag);
 int radix_tree_tagged(struct radix_tree_root *root, unsigned int tag);
 
 static inline void radix_tree_preload_end(void)