|
|
@@ -80,6 +80,46 @@ static inline void *indirect_to_ptr(void *ptr)
|
|
|
return (void *)((unsigned long)ptr & ~RADIX_TREE_INDIRECT_PTR);
|
|
|
}
|
|
|
|
|
|
+#ifdef CONFIG_RADIX_TREE_MULTIORDER
|
|
|
+/* Sibling slots point directly to another slot in the same node */
|
|
|
+static inline bool is_sibling_entry(struct radix_tree_node *parent, void *node)
|
|
|
+{
|
|
|
+ void **ptr = node;
|
|
|
+ return (parent->slots <= ptr) &&
|
|
|
+ (ptr < parent->slots + RADIX_TREE_MAP_SIZE);
|
|
|
+}
|
|
|
+#else
|
|
|
+static inline bool is_sibling_entry(struct radix_tree_node *parent, void *node)
|
|
|
+{
|
|
|
+ return false;
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
+static inline unsigned long get_slot_offset(struct radix_tree_node *parent,
|
|
|
+ void **slot)
|
|
|
+{
|
|
|
+ return slot - parent->slots;
|
|
|
+}
|
|
|
+
|
|
|
+static unsigned radix_tree_descend(struct radix_tree_node *parent,
|
|
|
+ struct radix_tree_node **nodep, unsigned offset)
|
|
|
+{
|
|
|
+ void **entry = rcu_dereference_raw(parent->slots[offset]);
|
|
|
+
|
|
|
+#ifdef CONFIG_RADIX_TREE_MULTIORDER
|
|
|
+ if (radix_tree_is_indirect_ptr(entry)) {
|
|
|
+ unsigned long siboff = get_slot_offset(parent, entry);
|
|
|
+ if (siboff < RADIX_TREE_MAP_SIZE) {
|
|
|
+ offset = siboff;
|
|
|
+ entry = rcu_dereference_raw(parent->slots[offset]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+#endif
|
|
|
+
|
|
|
+ *nodep = (void *)entry;
|
|
|
+ return offset;
|
|
|
+}
|
|
|
+
|
|
|
static inline gfp_t root_gfp_mask(struct radix_tree_root *root)
|
|
|
{
|
|
|
return root->gfp_mask & __GFP_BITS_MASK;
|