diff options
author | Matthew Wilcox <willy@infradead.org> | 2017-11-07 16:30:10 -0500 |
---|---|---|
committer | Matthew Wilcox <willy@infradead.org> | 2018-10-21 10:45:53 -0400 |
commit | f8d5d0cc145cc21bfc56ef807dc28102aebbf228 (patch) | |
tree | 0fcba575e83fb02fd2cb49df1ce1cc55bcd927d3 | |
parent | 02c02bf12c5d838603eed44195d3e91f094e2ab2 (diff) |
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.
Signed-off-by: Matthew Wilcox <willy@infradead.org>
Reviewed-by: Josef Bacik <jbacik@fb.com>
-rw-r--r-- | include/linux/radix-tree.h | 28 | ||||
-rw-r--r-- | include/linux/xarray.h | 70 | ||||
-rw-r--r-- | lib/Makefile | 2 | ||||
-rw-r--r-- | lib/idr.c | 4 | ||||
-rw-r--r-- | lib/radix-tree.c | 75 | ||||
-rw-r--r-- | lib/xarray.c | 44 | ||||
-rw-r--r-- | tools/testing/radix-tree/Makefile | 5 | ||||
-rw-r--r-- | tools/testing/radix-tree/linux/bug.h | 1 | ||||
-rw-r--r-- | tools/testing/radix-tree/linux/kconfig.h | 1 | ||||
-rw-r--r-- | tools/testing/radix-tree/multiorder.c | 6 | ||||
-rw-r--r-- | tools/testing/radix-tree/test.c | 6 | ||||
-rw-r--r-- | tools/testing/radix-tree/xarray.c | 7 |
12 files changed, 181 insertions, 68 deletions
diff --git a/include/linux/radix-tree.h b/include/linux/radix-tree.h index 60f3d8eb2cb7..0b080bd88ab7 100644 --- a/include/linux/radix-tree.h +++ b/include/linux/radix-tree.h | |||
@@ -30,6 +30,9 @@ | |||
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 the | 37 | * 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 { | |||
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 | ||
100 | struct 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) |
116 | do { \ | ||
117 | spin_lock_init(&(root)->xa_lock); \ | ||
118 | (root)->gfp_mask = (mask); \ | ||
119 | (root)->rnode = NULL; \ | ||
120 | } while (0) | ||
121 | 109 | ||
122 | static inline bool radix_tree_empty(const struct radix_tree_root *root) | 110 | static 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 | /** |
diff --git a/include/linux/xarray.h b/include/linux/xarray.h index 4d1cd7a083e8..9122cf8bf52a 100644 --- a/include/linux/xarray.h +++ b/include/linux/xarray.h | |||
@@ -10,6 +10,8 @@ | |||
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) | |||
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 | */ | ||
174 | struct 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 | |||
211 | void 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 | */ | ||
221 | static 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) |
diff --git a/lib/Makefile b/lib/Makefile index ca3f7ebb900d..057385f1f145 100644 --- a/lib/Makefile +++ b/lib/Makefile | |||
@@ -18,7 +18,7 @@ KCOV_INSTRUMENT_debugobjects.o := n | |||
18 | KCOV_INSTRUMENT_dynamic_debug.o := n | 18 | KCOV_INSTRUMENT_dynamic_debug.o := n |
19 | 19 | ||
20 | lib-y := ctype.o string.o vsprintf.o cmdline.o \ | 20 | lib-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 \ |
@@ -39,8 +39,8 @@ int idr_alloc_u32(struct idr *idr, void *ptr, u32 *nextid, | |||
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); |
diff --git a/lib/radix-tree.c b/lib/radix-tree.c index 59b28111eabc..299d4bdba109 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c | |||
@@ -124,7 +124,7 @@ static unsigned int radix_tree_descend(const struct radix_tree_node *parent, | |||
124 | 124 | ||
125 | static inline gfp_t root_gfp_mask(const struct radix_tree_root *root) | 125 | static 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 | ||
130 | static inline void tag_set(struct radix_tree_node *node, unsigned int tag, | 130 | static 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, | |||
147 | 147 | ||
148 | static inline void root_tag_set(struct radix_tree_root *root, unsigned tag) | 148 | static 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 | ||
153 | static inline void root_tag_clear(struct radix_tree_root *root, unsigned tag) | 153 | static 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 | ||
158 | static inline void root_tag_clear_all(struct radix_tree_root *root) | 158 | static 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 | ||
163 | static inline int root_tag_get(const struct radix_tree_root *root, unsigned tag) | 163 | static 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 | ||
168 | static inline unsigned root_tags_get(const struct radix_tree_root *root) | 168 | static 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 | ||
173 | static inline bool is_idr(const struct radix_tree_root *root) | 173 | static 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) | |||
291 | /* For debug */ | 291 | /* For debug */ |
292 | static void radix_tree_dump(struct radix_tree_root *root) | 292 | static 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 | ||
302 | static void dump_ida_node(void *entry, unsigned long index) | 302 | static void dump_ida_node(void *entry, unsigned long index) |
@@ -340,9 +340,9 @@ static void dump_ida_node(void *entry, unsigned long index) | |||
340 | static void ida_dump(struct ida *ida) | 340 | static 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 | #endif | 347 | #endif |
348 | 348 | ||
@@ -576,7 +576,7 @@ int radix_tree_maybe_preload_order(gfp_t gfp_mask, int order) | |||
576 | static unsigned radix_tree_load_root(const struct radix_tree_root *root, | 576 | static 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, | |||
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, | |||
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, | |||
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); |
648 | out: | 648 | out: |
@@ -659,7 +659,7 @@ static inline bool radix_tree_shrink(struct radix_tree_root *root, | |||
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, | |||
695 | * moving the node from one part of the tree to another: if it | 695 | * moving the node from one part of the tree to another: if it |
696 | * was safe to dereference the old pointer to it | 696 | * was safe to dereference the old pointer to it |
697 | * (node->slots[0]), it will be safe to dereference the new | 697 | * (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, | |||
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, | |||
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, | |||
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 are | 788 | * 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 of | 789 | * 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, | |||
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, | |||
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); | |||
1004 | * tree @root. | 1003 | * tree @root. |
1005 | * | 1004 | * |
1006 | * Until there is more than one item in the tree, no nodes are | 1005 | * 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 of | 1006 | * 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 | */ |
1010 | void *__radix_tree_lookup(const struct radix_tree_root *root, | 1009 | void *__radix_tree_lookup(const struct radix_tree_root *root, |
@@ -1017,7 +1016,7 @@ void *__radix_tree_lookup(const struct radix_tree_root *root, | |||
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, | |||
1168 | /* | 1167 | /* |
1169 | * This function supports replacing exceptional entries and | 1168 | * This function supports replacing exceptional entries and |
1170 | * deleting entries, but that needs accounting against the | 1169 | * 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, | |||
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, | |||
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, | |||
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, | |||
2190 | */ | 2189 | */ |
2191 | void idr_destroy(struct idr *idr) | 2190 | void 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 | } |
2199 | EXPORT_SYMBOL(idr_destroy); | 2198 | EXPORT_SYMBOL(idr_destroy); |
diff --git a/lib/xarray.c b/lib/xarray.c new file mode 100644 index 000000000000..862f4c64c754 --- /dev/null +++ b/lib/xarray.c | |||
@@ -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 | */ | ||
38 | void 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 | } | ||
44 | EXPORT_SYMBOL(xa_init_flags); | ||
diff --git a/tools/testing/radix-tree/Makefile b/tools/testing/radix-tree/Makefile index 12adcf9ffe86..c0cf1c79efd5 100644 --- a/tools/testing/radix-tree/Makefile +++ b/tools/testing/radix-tree/Makefile | |||
@@ -5,7 +5,7 @@ CFLAGS += -I. -I../../include -g -Og -Wall -D_LGPL_SOURCE -fsanitize=address \ | |||
5 | LDFLAGS += -fsanitize=address -fsanitize=undefined | 5 | LDFLAGS += -fsanitize=address -fsanitize=undefined |
6 | LDLIBS+= -lpthread -lurcu | 6 | LDLIBS+= -lpthread -lurcu |
7 | TARGETS = main idr-test multiorder | 7 | TARGETS = main idr-test multiorder |
8 | CORE_OFILES := radix-tree.o idr.o linux.o test.o find_bit.o | 8 | CORE_OFILES := xarray.o radix-tree.o idr.o linux.o test.o find_bit.o |
9 | OFILES = main.o $(CORE_OFILES) regression1.o regression2.o regression3.o \ | 9 | OFILES = main.o $(CORE_OFILES) regression1.o regression2.o regression3.o \ |
10 | tag_check.o multiorder.o idr-test.o iteration_check.o benchmark.o | 10 | tag_check.o multiorder.o idr-test.o iteration_check.o benchmark.o |
11 | 11 | ||
@@ -35,6 +35,7 @@ vpath %.c ../../lib | |||
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.h | 40 | ../../../include/linux/idr.h |
40 | 41 | ||
@@ -44,6 +45,8 @@ radix-tree.c: ../../../lib/radix-tree.c | |||
44 | idr.c: ../../../lib/idr.c | 45 | idr.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 | ||
48 | xarray.o: ../../../lib/xarray.c | ||
49 | |||
47 | generated/map-shift.h: | 50 | generated/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)" > \ |
diff --git a/tools/testing/radix-tree/linux/bug.h b/tools/testing/radix-tree/linux/bug.h index 23b8ed52f8c8..03dc8a57eb99 100644 --- a/tools/testing/radix-tree/linux/bug.h +++ b/tools/testing/radix-tree/linux/bug.h | |||
@@ -1 +1,2 @@ | |||
1 | #include <stdio.h> | ||
1 | #include "asm/bug.h" | 2 | #include "asm/bug.h" |
diff --git a/tools/testing/radix-tree/linux/kconfig.h b/tools/testing/radix-tree/linux/kconfig.h new file mode 100644 index 000000000000..6c8675859913 --- /dev/null +++ b/tools/testing/radix-tree/linux/kconfig.h | |||
@@ -0,0 +1 @@ | |||
#include "../../../../include/linux/kconfig.h" | |||
diff --git a/tools/testing/radix-tree/multiorder.c b/tools/testing/radix-tree/multiorder.c index 2b4f4dba1882..080aea450430 100644 --- a/tools/testing/radix-tree/multiorder.c +++ b/tools/testing/radix-tree/multiorder.c | |||
@@ -192,13 +192,13 @@ static void multiorder_shrink(unsigned long index, int order) | |||
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); |
diff --git a/tools/testing/radix-tree/test.c b/tools/testing/radix-tree/test.c index 62de66c314b7..70ddf964d51c 100644 --- a/tools/testing/radix-tree/test.c +++ b/tools/testing/radix-tree/test.c | |||
@@ -281,7 +281,7 @@ static int verify_node(struct radix_tree_node *slot, unsigned int tag, | |||
281 | 281 | ||
282 | void verify_tag_consistency(struct radix_tree_root *root, unsigned int tag) | 282 | void 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) | |||
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 | ||
317 | void tree_verify_min_height(struct radix_tree_root *root, int maxindex) | 317 | void 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; |
diff --git a/tools/testing/radix-tree/xarray.c b/tools/testing/radix-tree/xarray.c new file mode 100644 index 000000000000..9bbd667172a7 --- /dev/null +++ b/tools/testing/radix-tree/xarray.c | |||
@@ -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" | ||