History

xarray: Add definition of struct xarray

This is a direct replacement for struct radix_tree_root. Some of the struct members have changed name; convert those, and use a #define so that radix_tree users continue to work without change.

Matthew Wilcox committed 9 years ago

Commit f8d5d0c1 parent 02c02bf12 files · +181 −68Browse files

Unified · Split

12 files
  1. include/linux/radix-tree.h +8 −20
  2. include/linux/xarray.h +70 −0
  3. lib/Makefile +1 −1
  4. lib/idr.c +2 −2
  5. lib/radix-tree.c +37 −38
  6. lib/xarray.c +44 −0
  7. tools/testing/radix-tree/Makefile +4 −1
  8. tools/testing/radix-tree/linux/bug.h +1 −0
  9. tools/testing/radix-tree/linux/kconfig.h +1 −0
  10. tools/testing/radix-tree/multiorder.c +3 −3
  11. tools/testing/radix-tree/test.c +3 −3
  12. tools/testing/radix-tree/xarray.c +7 −0
include/linux/radix-tree.h+8−20
@@ -30,6 +30,9 @@ · 29 unmodified lines
30#include <linux/types.h>30#include <linux/types.h>
31#include <linux/xarray.h>31#include <linux/xarray.h>
32 32
33/* Keep unconverted code working */
34#define radix_tree_root xarray
35
33/*36/*
34 * The bottom two bits of the slot determine how the remaining bits in the37 * The bottom two bits of the slot determine how the remaining bits in the
35 * slot are interpreted:38 * slot are interpreted:
@@ -92,36 +95,21 @@ struct radix_tree_node { · 56 unmodified lines
92 unsigned long tags[RADIX_TREE_MAX_TAGS][RADIX_TREE_TAG_LONGS];95 unsigned long tags[RADIX_TREE_MAX_TAGS][RADIX_TREE_TAG_LONGS];
93};96};
94 97
95/* The IDR tag is stored in the low bits of the GFP flags */98/* The IDR tag is stored in the low bits of xa_flags */
96#define ROOT_IS_IDR ((__force gfp_t)4)99#define ROOT_IS_IDR ((__force gfp_t)4)
97/* The top bits of gfp_mask are used to store the root tags */100/* The top bits of xa_flags are used to store the root tags */
98#define ROOT_TAG_SHIFT (__GFP_BITS_SHIFT)101#define ROOT_TAG_SHIFT (__GFP_BITS_SHIFT)
99 102
100struct radix_tree_root {103#define RADIX_TREE_INIT(name, mask) XARRAY_INIT(name, mask)
101 spinlock_t xa_lock;
102 gfp_t gfp_mask;
103 struct radix_tree_node __rcu *rnode;
104};
105
106#define RADIX_TREE_INIT(name, mask) { \
107 .xa_lock = __SPIN_LOCK_UNLOCKED(name.xa_lock), \
108 .gfp_mask = (mask), \
109 .rnode = NULL, \
110}
111 104
112#define RADIX_TREE(name, mask) \105#define RADIX_TREE(name, mask) \
113 struct radix_tree_root name = RADIX_TREE_INIT(name, mask)106 struct radix_tree_root name = RADIX_TREE_INIT(name, mask)
114 107
115#define INIT_RADIX_TREE(root, mask) \108#define INIT_RADIX_TREE(root, mask) xa_init_flags(root, mask)
116do { \
117 spin_lock_init(&(root)->xa_lock); \
118 (root)->gfp_mask = (mask); \
119 (root)->rnode = NULL; \
120} while (0)
121 109
122static inline bool radix_tree_empty(const struct radix_tree_root *root)110static inline bool radix_tree_empty(const struct radix_tree_root *root)
123{111{
124 return root->rnode == NULL;112 return root->xa_head == NULL;
125}113}
126 114
127/**115/**
include/linux/xarray.h+70−0
@@ -10,6 +10,8 @@ · 9 unmodified lines
10 */10 */
11 11
12#include <linux/bug.h>12#include <linux/bug.h>
13#include <linux/compiler.h>
14#include <linux/kconfig.h>
13#include <linux/spinlock.h>15#include <linux/spinlock.h>
14#include <linux/types.h>16#include <linux/types.h>
15 17
@@ -153,6 +155,74 @@ static inline bool xa_is_internal(const void *entry) · 137 unmodified lines
153 return ((unsigned long)entry & 3) == 2;155 return ((unsigned long)entry & 3) == 2;
154}156}
155 157
158/**
159 * struct xarray - The anchor of the XArray.
160 * @xa_lock: Lock that protects the contents of the XArray.
161 *
162 * To use the xarray, define it statically or embed it in your data structure.
163 * It is a very small data structure, so it does not usually make sense to
164 * allocate it separately and keep a pointer to it in your data structure.
165 *
166 * You may use the xa_lock to protect your own data structures as well.
167 */
168/*
169 * If all of the entries in the array are NULL, @xa_head is a NULL pointer.
170 * If the only non-NULL entry in the array is at index 0, @xa_head is that
171 * entry. If any other entry in the array is non-NULL, @xa_head points
172 * to an @xa_node.
173 */
174struct xarray {
175 spinlock_t xa_lock;
176/* private: The rest of the data structure is not to be used directly. */
177 gfp_t xa_flags;
178 void __rcu * xa_head;
179};
180
181#define XARRAY_INIT(name, flags) { \
182 .xa_lock = __SPIN_LOCK_UNLOCKED(name.xa_lock), \
183 .xa_flags = flags, \
184 .xa_head = NULL, \
185}
186
187/**
188 * DEFINE_XARRAY_FLAGS() - Define an XArray with custom flags.
189 * @name: A string that names your XArray.
190 * @flags: XA_FLAG values.
191 *
192 * This is intended for file scope definitions of XArrays. It declares
193 * and initialises an empty XArray with the chosen name and flags. It is
194 * equivalent to calling xa_init_flags() on the array, but it does the
195 * initialisation at compiletime instead of runtime.
196 */
197#define DEFINE_XARRAY_FLAGS(name, flags) \
198 struct xarray name = XARRAY_INIT(name, flags)
199
200/**
201 * DEFINE_XARRAY() - Define an XArray.
202 * @name: A string that names your XArray.
203 *
204 * This is intended for file scope definitions of XArrays. It declares
205 * and initialises an empty XArray with the chosen name. It is equivalent
206 * to calling xa_init() on the array, but it does the initialisation at
207 * compiletime instead of runtime.
208 */
209#define DEFINE_XARRAY(name) DEFINE_XARRAY_FLAGS(name, 0)
210
211void xa_init_flags(struct xarray *, gfp_t flags);
212
213/**
214 * xa_init() - Initialise an empty XArray.
215 * @xa: XArray.
216 *
217 * An empty XArray is full of NULL entries.
218 *
219 * Context: Any context.
220 */
221static inline void xa_init(struct xarray *xa)
222{
223 xa_init_flags(xa, 0);
224}
225
156#define xa_trylock(xa) spin_trylock(&(xa)->xa_lock)226#define xa_trylock(xa) spin_trylock(&(xa)->xa_lock)
157#define xa_lock(xa) spin_lock(&(xa)->xa_lock)227#define xa_lock(xa) spin_lock(&(xa)->xa_lock)
158#define xa_unlock(xa) spin_unlock(&(xa)->xa_lock)228#define xa_unlock(xa) spin_unlock(&(xa)->xa_lock)
lib/Makefile+1−1
@@ -18,7 +18,7 @@ KCOV_INSTRUMENT_debugobjects.o := n · 17 unmodified lines
18KCOV_INSTRUMENT_dynamic_debug.o := n18KCOV_INSTRUMENT_dynamic_debug.o := n
19 19
20lib-y := ctype.o string.o vsprintf.o cmdline.o \20lib-y := ctype.o string.o vsprintf.o cmdline.o \
21 rbtree.o radix-tree.o timerqueue.o\21 rbtree.o radix-tree.o timerqueue.o xarray.o \
22 idr.o int_sqrt.o extable.o \22 idr.o int_sqrt.o extable.o \
23 sha1.o chacha20.o irq_regs.o argv_split.o \23 sha1.o chacha20.o irq_regs.o argv_split.o \
24 flex_proportions.o ratelimit.o show_mem.o \24 flex_proportions.o ratelimit.o show_mem.o \
lib/idr.c+2−2
@@ -39,8 +39,8 @@ int idr_alloc_u32(struct idr *idr, void *ptr, u32 *nextid, · 38 unmodified lines
39 unsigned int base = idr->idr_base;39 unsigned int base = idr->idr_base;
40 unsigned int id = *nextid;40 unsigned int id = *nextid;
41 41
42 if (WARN_ON_ONCE(!(idr->idr_rt.gfp_mask & ROOT_IS_IDR)))42 if (WARN_ON_ONCE(!(idr->idr_rt.xa_flags & ROOT_IS_IDR)))
43 idr->idr_rt.gfp_mask |= IDR_RT_MARKER;43 idr->idr_rt.xa_flags |= IDR_RT_MARKER;
44 44
45 id = (id < base) ? 0 : id - base;45 id = (id < base) ? 0 : id - base;
46 radix_tree_iter_init(&iter, id);46 radix_tree_iter_init(&iter, id);
lib/radix-tree.c+37−38
@@ -124,7 +124,7 @@ static unsigned int radix_tree_descend(const struct radix_tree_node *parent, · 123 unmodified lines
124 124
125static inline gfp_t root_gfp_mask(const struct radix_tree_root *root)125static inline gfp_t root_gfp_mask(const struct radix_tree_root *root)
126{126{
127 return root->gfp_mask & (__GFP_BITS_MASK & ~GFP_ZONEMASK);127 return root->xa_flags & (__GFP_BITS_MASK & ~GFP_ZONEMASK);
128}128}
129 129
130static inline void tag_set(struct radix_tree_node *node, unsigned int tag,130static inline void tag_set(struct radix_tree_node *node, unsigned int tag,
@@ -147,32 +147,32 @@ static inline int tag_get(const struct radix_tree_node *node, unsigned int tag, · 16 unmodified lines
147 147
148static inline void root_tag_set(struct radix_tree_root *root, unsigned tag)148static inline void root_tag_set(struct radix_tree_root *root, unsigned tag)
149{149{
150 root->gfp_mask |= (__force gfp_t)(1 << (tag + ROOT_TAG_SHIFT));150 root->xa_flags |= (__force gfp_t)(1 << (tag + ROOT_TAG_SHIFT));
151}151}
152 152
153static inline void root_tag_clear(struct radix_tree_root *root, unsigned tag)153static inline void root_tag_clear(struct radix_tree_root *root, unsigned tag)
154{154{
155 root->gfp_mask &= (__force gfp_t)~(1 << (tag + ROOT_TAG_SHIFT));155 root->xa_flags &= (__force gfp_t)~(1 << (tag + ROOT_TAG_SHIFT));
156}156}
157 157
158static inline void root_tag_clear_all(struct radix_tree_root *root)158static inline void root_tag_clear_all(struct radix_tree_root *root)
159{159{
160 root->gfp_mask &= (1 << ROOT_TAG_SHIFT) - 1;160 root->xa_flags &= (__force gfp_t)((1 << ROOT_TAG_SHIFT) - 1);
161}161}
162 162
163static inline int root_tag_get(const struct radix_tree_root *root, unsigned tag)163static inline int root_tag_get(const struct radix_tree_root *root, unsigned tag)
164{164{
165 return (__force int)root->gfp_mask & (1 << (tag + ROOT_TAG_SHIFT));165 return (__force int)root->xa_flags & (1 << (tag + ROOT_TAG_SHIFT));
166}166}
167 167
168static inline unsigned root_tags_get(const struct radix_tree_root *root)168static inline unsigned root_tags_get(const struct radix_tree_root *root)
169{169{
170 return (__force unsigned)root->gfp_mask >> ROOT_TAG_SHIFT;170 return (__force unsigned)root->xa_flags >> ROOT_TAG_SHIFT;
171}171}
172 172
173static inline bool is_idr(const struct radix_tree_root *root)173static inline bool is_idr(const struct radix_tree_root *root)
174{174{
175 return !!(root->gfp_mask & ROOT_IS_IDR);175 return !!(root->xa_flags & ROOT_IS_IDR);
176}176}
177 177
178/*178/*
@@ -291,12 +291,12 @@ static void dump_node(struct radix_tree_node *node, unsigned long index) · 112 unmodified lines
291/* For debug */291/* For debug */
292static void radix_tree_dump(struct radix_tree_root *root)292static void radix_tree_dump(struct radix_tree_root *root)
293{293{
294 pr_debug("radix root: %p rnode %p tags %x\n",294 pr_debug("radix root: %p xa_head %p tags %x\n",
295 root, root->rnode,295 root, root->xa_head,
296 root->gfp_mask >> ROOT_TAG_SHIFT);296 root->xa_flags >> ROOT_TAG_SHIFT);
297 if (!radix_tree_is_internal_node(root->rnode))297 if (!radix_tree_is_internal_node(root->xa_head))
298 return;298 return;
299 dump_node(entry_to_node(root->rnode), 0);299 dump_node(entry_to_node(root->xa_head), 0);
300}300}
301 301
302static void dump_ida_node(void *entry, unsigned long index)302static void dump_ida_node(void *entry, unsigned long index)
@@ -340,9 +340,9 @@ static void dump_ida_node(void *entry, unsigned long index) · 37 unmodified lines
340static void ida_dump(struct ida *ida)340static void ida_dump(struct ida *ida)
341{341{
342 struct radix_tree_root *root = &ida->ida_rt;342 struct radix_tree_root *root = &ida->ida_rt;
343 pr_debug("ida: %p node %p free %d\n", ida, root->rnode,343 pr_debug("ida: %p node %p free %d\n", ida, root->xa_head,
344 root->gfp_mask >> ROOT_TAG_SHIFT);344 root->xa_flags >> ROOT_TAG_SHIFT);
345 dump_ida_node(root->rnode, 0);345 dump_ida_node(root->xa_head, 0);
346}346}
347#endif347#endif
348 348
@@ -576,7 +576,7 @@ int radix_tree_maybe_preload_order(gfp_t gfp_mask, int order) · 227 unmodified lines
576static unsigned radix_tree_load_root(const struct radix_tree_root *root,576static unsigned radix_tree_load_root(const struct radix_tree_root *root,
577 struct radix_tree_node **nodep, unsigned long *maxindex)577 struct radix_tree_node **nodep, unsigned long *maxindex)
578{578{
579 struct radix_tree_node *node = rcu_dereference_raw(root->rnode);579 struct radix_tree_node *node = rcu_dereference_raw(root->xa_head);
580 580
581 *nodep = node;581 *nodep = node;
582 582
@@ -605,7 +605,7 @@ static int radix_tree_extend(struct radix_tree_root *root, gfp_t gfp, · 22 unmodified lines
605 while (index > shift_maxindex(maxshift))605 while (index > shift_maxindex(maxshift))
606 maxshift += RADIX_TREE_MAP_SHIFT;606 maxshift += RADIX_TREE_MAP_SHIFT;
607 607
608 entry = rcu_dereference_raw(root->rnode);608 entry = rcu_dereference_raw(root->xa_head);
609 if (!entry && (!is_idr(root) || root_tag_get(root, IDR_FREE)))609 if (!entry && (!is_idr(root) || root_tag_get(root, IDR_FREE)))
610 goto out;610 goto out;
611 611
@@ -633,7 +633,7 @@ static int radix_tree_extend(struct radix_tree_root *root, gfp_t gfp, · 21 unmodified lines
633 if (radix_tree_is_internal_node(entry)) {633 if (radix_tree_is_internal_node(entry)) {
634 entry_to_node(entry)->parent = node;634 entry_to_node(entry)->parent = node;
635 } else if (xa_is_value(entry)) {635 } else if (xa_is_value(entry)) {
636 /* Moving an exceptional root->rnode to a node */636 /* Moving an exceptional root->xa_head to a node */
637 node->exceptional = 1;637 node->exceptional = 1;
638 }638 }
639 /*639 /*
@@ -642,7 +642,7 @@ static int radix_tree_extend(struct radix_tree_root *root, gfp_t gfp, · 2 unmodified lines
642 */642 */
643 node->slots[0] = (void __rcu *)entry;643 node->slots[0] = (void __rcu *)entry;
644 entry = node_to_entry(node);644 entry = node_to_entry(node);
645 rcu_assign_pointer(root->rnode, entry);645 rcu_assign_pointer(root->xa_head, entry);
646 shift += RADIX_TREE_MAP_SHIFT;646 shift += RADIX_TREE_MAP_SHIFT;
647 } while (shift <= maxshift);647 } while (shift <= maxshift);
648out:648out:
@@ -659,7 +659,7 @@ static inline bool radix_tree_shrink(struct radix_tree_root *root, · 10 unmodified lines
659 bool shrunk = false;659 bool shrunk = false;
660 660
661 for (;;) {661 for (;;) {
662 struct radix_tree_node *node = rcu_dereference_raw(root->rnode);662 struct radix_tree_node *node = rcu_dereference_raw(root->xa_head);
663 struct radix_tree_node *child;663 struct radix_tree_node *child;
664 664
665 if (!radix_tree_is_internal_node(node))665 if (!radix_tree_is_internal_node(node))
@@ -695,9 +695,9 @@ static inline bool radix_tree_shrink(struct radix_tree_root *root, · 29 unmodified lines
695 * moving the node from one part of the tree to another: if it695 * moving the node from one part of the tree to another: if it
696 * was safe to dereference the old pointer to it696 * was safe to dereference the old pointer to it
697 * (node->slots[0]), it will be safe to dereference the new697 * (node->slots[0]), it will be safe to dereference the new
698 * one (root->rnode) as far as dependent read barriers go.698 * one (root->xa_head) as far as dependent read barriers go.
699 */699 */
700 root->rnode = (void __rcu *)child;700 root->xa_head = (void __rcu *)child;
701 if (is_idr(root) && !tag_get(node, IDR_FREE, 0))701 if (is_idr(root) && !tag_get(node, IDR_FREE, 0))
702 root_tag_clear(root, IDR_FREE);702 root_tag_clear(root, IDR_FREE);
703 703
@@ -745,9 +745,8 @@ static bool delete_node(struct radix_tree_root *root, · 41 unmodified lines
745 745
746 if (node->count) {746 if (node->count) {
747 if (node_to_entry(node) ==747 if (node_to_entry(node) ==
748 rcu_dereference_raw(root->rnode))748 rcu_dereference_raw(root->xa_head))
749 deleted |= radix_tree_shrink(root,749 deleted |= radix_tree_shrink(root, update_node);
750 update_node);
751 return deleted;750 return deleted;
752 }751 }
753 752
@@ -762,7 +761,7 @@ static bool delete_node(struct radix_tree_root *root, · 8 unmodified lines
762 */761 */
763 if (!is_idr(root))762 if (!is_idr(root))
764 root_tag_clear_all(root);763 root_tag_clear_all(root);
765 root->rnode = NULL;764 root->xa_head = NULL;
766 }765 }
767 766
768 WARN_ON_ONCE(!list_empty(&node->private_list));767 WARN_ON_ONCE(!list_empty(&node->private_list));
@@ -787,7 +786,7 @@ static bool delete_node(struct radix_tree_root *root, · 18 unmodified lines
787 * at position @index in the radix tree @root.786 * at position @index in the radix tree @root.
788 *787 *
789 * Until there is more than one item in the tree, no nodes are788 * Until there is more than one item in the tree, no nodes are
790 * allocated and @root->rnode is used as a direct slot instead of789 * allocated and @root->xa_head is used as a direct slot instead of
791 * pointing to a node, in which case *@nodep will be NULL.790 * pointing to a node, in which case *@nodep will be NULL.
792 *791 *
793 * Returns -ENOMEM, or 0 for success.792 * Returns -ENOMEM, or 0 for success.
@@ -797,7 +796,7 @@ int __radix_tree_create(struct radix_tree_root *root, unsigned long index, · 3 unmodified lines
797 void __rcu ***slotp)796 void __rcu ***slotp)
798{797{
799 struct radix_tree_node *node = NULL, *child;798 struct radix_tree_node *node = NULL, *child;
800 void __rcu **slot = (void __rcu **)&root->rnode;799 void __rcu **slot = (void __rcu **)&root->xa_head;
801 unsigned long maxindex;800 unsigned long maxindex;
802 unsigned int shift, offset = 0;801 unsigned int shift, offset = 0;
803 unsigned long max = index | ((1UL << order) - 1);802 unsigned long max = index | ((1UL << order) - 1);
@@ -813,7 +812,7 @@ int __radix_tree_create(struct radix_tree_root *root, unsigned long index, · 9 unmodified lines
813 if (error < 0)812 if (error < 0)
814 return error;813 return error;
815 shift = error;814 shift = error;
816 child = rcu_dereference_raw(root->rnode);815 child = rcu_dereference_raw(root->xa_head);
817 }816 }
818 817
819 while (shift > order) {818 while (shift > order) {
@@ -1004,7 +1003,7 @@ EXPORT_SYMBOL(__radix_tree_insert); · 184 unmodified lines
1004 * tree @root.1003 * tree @root.
1005 *1004 *
1006 * Until there is more than one item in the tree, no nodes are1005 * Until there is more than one item in the tree, no nodes are
1007 * allocated and @root->rnode is used as a direct slot instead of1006 * allocated and @root->xa_head is used as a direct slot instead of
1008 * pointing to a node, in which case *@nodep will be NULL.1007 * pointing to a node, in which case *@nodep will be NULL.
1009 */1008 */
1010void *__radix_tree_lookup(const struct radix_tree_root *root,1009void *__radix_tree_lookup(const struct radix_tree_root *root,
@@ -1017,7 +1016,7 @@ void *__radix_tree_lookup(const struct radix_tree_root *root, · 6 unmodified lines
1017 1016
1018 restart:1017 restart:
1019 parent = NULL;1018 parent = NULL;
1020 slot = (void __rcu **)&root->rnode;1019 slot = (void __rcu **)&root->xa_head;
1021 radix_tree_load_root(root, &node, &maxindex);1020 radix_tree_load_root(root, &node, &maxindex);
1022 if (index > maxindex)1021 if (index > maxindex)
1023 return NULL;1022 return NULL;
@@ -1168,9 +1167,9 @@ void __radix_tree_replace(struct radix_tree_root *root, · 144 unmodified lines
1168 /*1167 /*
1169 * This function supports replacing exceptional entries and1168 * This function supports replacing exceptional entries and
1170 * deleting entries, but that needs accounting against the1169 * deleting entries, but that needs accounting against the
1171 * node unless the slot is root->rnode.1170 * node unless the slot is root->xa_head.
1172 */1171 */
1173 WARN_ON_ONCE(!node && (slot != (void __rcu **)&root->rnode) &&1172 WARN_ON_ONCE(!node && (slot != (void __rcu **)&root->xa_head) &&
1174 (count || exceptional));1173 (count || exceptional));
1175 replace_slot(slot, item, node, count, exceptional);1174 replace_slot(slot, item, node, count, exceptional);
1176 1175
@@ -1722,7 +1721,7 @@ void __rcu **radix_tree_next_chunk(const struct radix_tree_root *root, · 545 unmodified lines
1722 iter->tags = 1;1721 iter->tags = 1;
1723 iter->node = NULL;1722 iter->node = NULL;
1724 __set_iter_shift(iter, 0);1723 __set_iter_shift(iter, 0);
1725 return (void __rcu **)&root->rnode;1724 return (void __rcu **)&root->xa_head;
1726 }1725 }
1727 1726
1728 do {1727 do {
@@ -2109,7 +2108,7 @@ void __rcu **idr_get_free(struct radix_tree_root *root, · 380 unmodified lines
2109 unsigned long max)2108 unsigned long max)
2110{2109{
2111 struct radix_tree_node *node = NULL, *child;2110 struct radix_tree_node *node = NULL, *child;
2112 void __rcu **slot = (void __rcu **)&root->rnode;2111 void __rcu **slot = (void __rcu **)&root->xa_head;
2113 unsigned long maxindex, start = iter->next_index;2112 unsigned long maxindex, start = iter->next_index;
2114 unsigned int shift, offset = 0;2113 unsigned int shift, offset = 0;
2115 2114
@@ -2125,7 +2124,7 @@ void __rcu **idr_get_free(struct radix_tree_root *root, · 9 unmodified lines
2125 if (error < 0)2124 if (error < 0)
2126 return ERR_PTR(error);2125 return ERR_PTR(error);
2127 shift = error;2126 shift = error;
2128 child = rcu_dereference_raw(root->rnode);2127 child = rcu_dereference_raw(root->xa_head);
2129 }2128 }
2130 if (start == 0 && shift == 0)2129 if (start == 0 && shift == 0)
2131 shift = RADIX_TREE_MAP_SHIFT;2130 shift = RADIX_TREE_MAP_SHIFT;
@@ -2190,10 +2189,10 @@ void __rcu **idr_get_free(struct radix_tree_root *root, · 58 unmodified lines
2190 */2189 */
2191void idr_destroy(struct idr *idr)2190void idr_destroy(struct idr *idr)
2192{2191{
2193 struct radix_tree_node *node = rcu_dereference_raw(idr->idr_rt.rnode);2192 struct radix_tree_node *node = rcu_dereference_raw(idr->idr_rt.xa_head);
2194 if (radix_tree_is_internal_node(node))2193 if (radix_tree_is_internal_node(node))
2195 radix_tree_free_nodes(node);2194 radix_tree_free_nodes(node);
2196 idr->idr_rt.rnode = NULL;2195 idr->idr_rt.xa_head = NULL;
2197 root_tag_set(&idr->idr_rt, IDR_FREE);2196 root_tag_set(&idr->idr_rt, IDR_FREE);
2198}2197}
2199EXPORT_SYMBOL(idr_destroy);2198EXPORT_SYMBOL(idr_destroy);
lib/xarray.c+44−0
@@ -0,0 +1,44 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * XArray implementation
4 * Copyright (c) 2017 Microsoft Corporation
5 * Author: Matthew Wilcox <willy@infradead.org>
6 */
7
8#include <linux/export.h>
9#include <linux/xarray.h>
10
11/*
12 * Coding conventions in this file:
13 *
14 * @xa is used to refer to the entire xarray.
15 * @xas is the 'xarray operation state'. It may be either a pointer to
16 * an xa_state, or an xa_state stored on the stack. This is an unfortunate
17 * ambiguity.
18 * @index is the index of the entry being operated on
19 * @mark is an xa_mark_t; a small number indicating one of the mark bits.
20 * @node refers to an xa_node; usually the primary one being operated on by
21 * this function.
22 * @offset is the index into the slots array inside an xa_node.
23 * @parent refers to the @xa_node closer to the head than @node.
24 * @entry refers to something stored in a slot in the xarray
25 */
26
27/**
28 * xa_init_flags() - Initialise an empty XArray with flags.
29 * @xa: XArray.
30 * @flags: XA_FLAG values.
31 *
32 * If you need to initialise an XArray with special flags (eg you need
33 * to take the lock from interrupt context), use this function instead
34 * of xa_init().
35 *
36 * Context: Any context.
37 */
38void xa_init_flags(struct xarray *xa, gfp_t flags)
39{
40 spin_lock_init(&xa->xa_lock);
41 xa->xa_flags = flags;
42 xa->xa_head = NULL;
43}
44EXPORT_SYMBOL(xa_init_flags);
tools/testing/radix-tree/Makefile+4−1
@@ -5,7 +5,7 @@ CFLAGS += -I. -I../../include -g -Og -Wall -D_LGPL_SOURCE -fsanitize=address \ · 4 unmodified lines
5LDFLAGS += -fsanitize=address -fsanitize=undefined5LDFLAGS += -fsanitize=address -fsanitize=undefined
6LDLIBS+= -lpthread -lurcu6LDLIBS+= -lpthread -lurcu
7TARGETS = main idr-test multiorder7TARGETS = main idr-test multiorder
8CORE_OFILES := radix-tree.o idr.o linux.o test.o find_bit.o8CORE_OFILES := xarray.o radix-tree.o idr.o linux.o test.o find_bit.o
9OFILES = main.o $(CORE_OFILES) regression1.o regression2.o regression3.o \9OFILES = main.o $(CORE_OFILES) regression1.o regression2.o regression3.o \
10 tag_check.o multiorder.o idr-test.o iteration_check.o benchmark.o10 tag_check.o multiorder.o idr-test.o iteration_check.o benchmark.o
11 11
@@ -35,6 +35,7 @@ vpath %.c ../../lib · 23 unmodified lines
35$(OFILES): Makefile *.h */*.h generated/map-shift.h \35$(OFILES): Makefile *.h */*.h generated/map-shift.h \
36 ../../include/linux/*.h \36 ../../include/linux/*.h \
37 ../../include/asm/*.h \37 ../../include/asm/*.h \
38 ../../../include/linux/xarray.h \
38 ../../../include/linux/radix-tree.h \39 ../../../include/linux/radix-tree.h \
39 ../../../include/linux/idr.h40 ../../../include/linux/idr.h
40 41
@@ -44,6 +45,8 @@ radix-tree.c: ../../../lib/radix-tree.c · 3 unmodified lines
44idr.c: ../../../lib/idr.c45idr.c: ../../../lib/idr.c
45 sed -e 's/^static //' -e 's/__always_inline //' -e 's/inline //' < $< > $@46 sed -e 's/^static //' -e 's/__always_inline //' -e 's/inline //' < $< > $@
46 47
48xarray.o: ../../../lib/xarray.c
49
47generated/map-shift.h:50generated/map-shift.h:
48 @if ! grep -qws $(SHIFT) generated/map-shift.h; then \51 @if ! grep -qws $(SHIFT) generated/map-shift.h; then \
49 echo "#define XA_CHUNK_SHIFT $(SHIFT)" > \52 echo "#define XA_CHUNK_SHIFT $(SHIFT)" > \
tools/testing/radix-tree/linux/bug.h+1−0
@@ -1 +1,2 @@
1#include <stdio.h>
1#include "asm/bug.h"2#include "asm/bug.h"
tools/testing/radix-tree/linux/kconfig.h+1−0
@@ -0,0 +1 @@
1#include "../../../../include/linux/kconfig.h"
tools/testing/radix-tree/multiorder.c+3−3
@@ -192,13 +192,13 @@ static void multiorder_shrink(unsigned long index, int order) · 191 unmodified lines
192 192
193 assert(item_insert_order(&tree, 0, order) == 0);193 assert(item_insert_order(&tree, 0, order) == 0);
194 194
195 node = tree.rnode;195 node = tree.xa_head;
196 196
197 assert(item_insert(&tree, index) == 0);197 assert(item_insert(&tree, index) == 0);
198 assert(node != tree.rnode);198 assert(node != tree.xa_head);
199 199
200 assert(item_delete(&tree, index) != 0);200 assert(item_delete(&tree, index) != 0);
201 assert(node == tree.rnode);201 assert(node == tree.xa_head);
202 202
203 for (i = 0; i < max; i++) {203 for (i = 0; i < max; i++) {
204 struct item *item = item_lookup(&tree, i);204 struct item *item = item_lookup(&tree, i);
tools/testing/radix-tree/test.c+3−3
@@ -281,7 +281,7 @@ static int verify_node(struct radix_tree_node *slot, unsigned int tag, · 280 unmodified lines
281 281
282void verify_tag_consistency(struct radix_tree_root *root, unsigned int tag)282void verify_tag_consistency(struct radix_tree_root *root, unsigned int tag)
283{283{
284 struct radix_tree_node *node = root->rnode;284 struct radix_tree_node *node = root->xa_head;
285 if (!radix_tree_is_internal_node(node))285 if (!radix_tree_is_internal_node(node))
286 return;286 return;
287 verify_node(node, tag, !!root_tag_get(root, tag));287 verify_node(node, tag, !!root_tag_get(root, tag));
@@ -311,13 +311,13 @@ void item_kill_tree(struct radix_tree_root *root) · 23 unmodified lines
311 }311 }
312 }312 }
313 assert(radix_tree_gang_lookup(root, (void **)items, 0, 32) == 0);313 assert(radix_tree_gang_lookup(root, (void **)items, 0, 32) == 0);
314 assert(root->rnode == NULL);314 assert(root->xa_head == NULL);
315}315}
316 316
317void tree_verify_min_height(struct radix_tree_root *root, int maxindex)317void tree_verify_min_height(struct radix_tree_root *root, int maxindex)
318{318{
319 unsigned shift;319 unsigned shift;
320 struct radix_tree_node *node = root->rnode;320 struct radix_tree_node *node = root->xa_head;
321 if (!radix_tree_is_internal_node(node)) {321 if (!radix_tree_is_internal_node(node)) {
322 assert(maxindex == 0);322 assert(maxindex == 0);
323 return;323 return;
tools/testing/radix-tree/xarray.c+7−0
@@ -0,0 +1,7 @@
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * xarray.c: Userspace shim for XArray test-suite
4 * Copyright (c) 2018 Matthew Wilcox <willy@infradead.org>
5 */
6
7#include "../../../lib/xarray.c"

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t