xref: /linux-6.15/lib/xarray.c (revision 371c752d)
1f8d5d0ccSMatthew Wilcox // SPDX-License-Identifier: GPL-2.0+
2f8d5d0ccSMatthew Wilcox /*
3f8d5d0ccSMatthew Wilcox  * XArray implementation
4f8d5d0ccSMatthew Wilcox  * Copyright (c) 2017 Microsoft Corporation
5f8d5d0ccSMatthew Wilcox  * Author: Matthew Wilcox <[email protected]>
6f8d5d0ccSMatthew Wilcox  */
7f8d5d0ccSMatthew Wilcox 
89b89a035SMatthew Wilcox #include <linux/bitmap.h>
9f8d5d0ccSMatthew Wilcox #include <linux/export.h>
1058d6ea30SMatthew Wilcox #include <linux/list.h>
1158d6ea30SMatthew Wilcox #include <linux/slab.h>
12f8d5d0ccSMatthew Wilcox #include <linux/xarray.h>
13f8d5d0ccSMatthew Wilcox 
14f8d5d0ccSMatthew Wilcox /*
15f8d5d0ccSMatthew Wilcox  * Coding conventions in this file:
16f8d5d0ccSMatthew Wilcox  *
17f8d5d0ccSMatthew Wilcox  * @xa is used to refer to the entire xarray.
18f8d5d0ccSMatthew Wilcox  * @xas is the 'xarray operation state'.  It may be either a pointer to
19f8d5d0ccSMatthew Wilcox  * an xa_state, or an xa_state stored on the stack.  This is an unfortunate
20f8d5d0ccSMatthew Wilcox  * ambiguity.
21f8d5d0ccSMatthew Wilcox  * @index is the index of the entry being operated on
22f8d5d0ccSMatthew Wilcox  * @mark is an xa_mark_t; a small number indicating one of the mark bits.
23f8d5d0ccSMatthew Wilcox  * @node refers to an xa_node; usually the primary one being operated on by
24f8d5d0ccSMatthew Wilcox  * this function.
25f8d5d0ccSMatthew Wilcox  * @offset is the index into the slots array inside an xa_node.
26f8d5d0ccSMatthew Wilcox  * @parent refers to the @xa_node closer to the head than @node.
27f8d5d0ccSMatthew Wilcox  * @entry refers to something stored in a slot in the xarray
28f8d5d0ccSMatthew Wilcox  */
29f8d5d0ccSMatthew Wilcox 
3058d6ea30SMatthew Wilcox static inline unsigned int xa_lock_type(const struct xarray *xa)
3158d6ea30SMatthew Wilcox {
3258d6ea30SMatthew Wilcox 	return (__force unsigned int)xa->xa_flags & 3;
3358d6ea30SMatthew Wilcox }
3458d6ea30SMatthew Wilcox 
3558d6ea30SMatthew Wilcox static inline void xas_lock_type(struct xa_state *xas, unsigned int lock_type)
3658d6ea30SMatthew Wilcox {
3758d6ea30SMatthew Wilcox 	if (lock_type == XA_LOCK_IRQ)
3858d6ea30SMatthew Wilcox 		xas_lock_irq(xas);
3958d6ea30SMatthew Wilcox 	else if (lock_type == XA_LOCK_BH)
4058d6ea30SMatthew Wilcox 		xas_lock_bh(xas);
4158d6ea30SMatthew Wilcox 	else
4258d6ea30SMatthew Wilcox 		xas_lock(xas);
4358d6ea30SMatthew Wilcox }
4458d6ea30SMatthew Wilcox 
4558d6ea30SMatthew Wilcox static inline void xas_unlock_type(struct xa_state *xas, unsigned int lock_type)
4658d6ea30SMatthew Wilcox {
4758d6ea30SMatthew Wilcox 	if (lock_type == XA_LOCK_IRQ)
4858d6ea30SMatthew Wilcox 		xas_unlock_irq(xas);
4958d6ea30SMatthew Wilcox 	else if (lock_type == XA_LOCK_BH)
5058d6ea30SMatthew Wilcox 		xas_unlock_bh(xas);
5158d6ea30SMatthew Wilcox 	else
5258d6ea30SMatthew Wilcox 		xas_unlock(xas);
5358d6ea30SMatthew Wilcox }
5458d6ea30SMatthew Wilcox 
55*371c752dSMatthew Wilcox static inline bool xa_track_free(const struct xarray *xa)
56*371c752dSMatthew Wilcox {
57*371c752dSMatthew Wilcox 	return xa->xa_flags & XA_FLAGS_TRACK_FREE;
58*371c752dSMatthew Wilcox }
59*371c752dSMatthew Wilcox 
609b89a035SMatthew Wilcox static inline void xa_mark_set(struct xarray *xa, xa_mark_t mark)
619b89a035SMatthew Wilcox {
629b89a035SMatthew Wilcox 	if (!(xa->xa_flags & XA_FLAGS_MARK(mark)))
639b89a035SMatthew Wilcox 		xa->xa_flags |= XA_FLAGS_MARK(mark);
649b89a035SMatthew Wilcox }
659b89a035SMatthew Wilcox 
669b89a035SMatthew Wilcox static inline void xa_mark_clear(struct xarray *xa, xa_mark_t mark)
679b89a035SMatthew Wilcox {
689b89a035SMatthew Wilcox 	if (xa->xa_flags & XA_FLAGS_MARK(mark))
699b89a035SMatthew Wilcox 		xa->xa_flags &= ~(XA_FLAGS_MARK(mark));
709b89a035SMatthew Wilcox }
719b89a035SMatthew Wilcox 
729b89a035SMatthew Wilcox static inline unsigned long *node_marks(struct xa_node *node, xa_mark_t mark)
739b89a035SMatthew Wilcox {
749b89a035SMatthew Wilcox 	return node->marks[(__force unsigned)mark];
759b89a035SMatthew Wilcox }
769b89a035SMatthew Wilcox 
779b89a035SMatthew Wilcox static inline bool node_get_mark(struct xa_node *node,
789b89a035SMatthew Wilcox 		unsigned int offset, xa_mark_t mark)
799b89a035SMatthew Wilcox {
809b89a035SMatthew Wilcox 	return test_bit(offset, node_marks(node, mark));
819b89a035SMatthew Wilcox }
829b89a035SMatthew Wilcox 
839b89a035SMatthew Wilcox /* returns true if the bit was set */
849b89a035SMatthew Wilcox static inline bool node_set_mark(struct xa_node *node, unsigned int offset,
859b89a035SMatthew Wilcox 				xa_mark_t mark)
869b89a035SMatthew Wilcox {
879b89a035SMatthew Wilcox 	return __test_and_set_bit(offset, node_marks(node, mark));
889b89a035SMatthew Wilcox }
899b89a035SMatthew Wilcox 
909b89a035SMatthew Wilcox /* returns true if the bit was set */
919b89a035SMatthew Wilcox static inline bool node_clear_mark(struct xa_node *node, unsigned int offset,
929b89a035SMatthew Wilcox 				xa_mark_t mark)
939b89a035SMatthew Wilcox {
949b89a035SMatthew Wilcox 	return __test_and_clear_bit(offset, node_marks(node, mark));
959b89a035SMatthew Wilcox }
969b89a035SMatthew Wilcox 
979b89a035SMatthew Wilcox static inline bool node_any_mark(struct xa_node *node, xa_mark_t mark)
989b89a035SMatthew Wilcox {
999b89a035SMatthew Wilcox 	return !bitmap_empty(node_marks(node, mark), XA_CHUNK_SIZE);
1009b89a035SMatthew Wilcox }
1019b89a035SMatthew Wilcox 
102*371c752dSMatthew Wilcox static inline void node_mark_all(struct xa_node *node, xa_mark_t mark)
103*371c752dSMatthew Wilcox {
104*371c752dSMatthew Wilcox 	bitmap_fill(node_marks(node, mark), XA_CHUNK_SIZE);
105*371c752dSMatthew Wilcox }
106*371c752dSMatthew Wilcox 
10758d6ea30SMatthew Wilcox #define mark_inc(mark) do { \
10858d6ea30SMatthew Wilcox 	mark = (__force xa_mark_t)((__force unsigned)(mark) + 1); \
10958d6ea30SMatthew Wilcox } while (0)
11058d6ea30SMatthew Wilcox 
11158d6ea30SMatthew Wilcox /*
11258d6ea30SMatthew Wilcox  * xas_squash_marks() - Merge all marks to the first entry
11358d6ea30SMatthew Wilcox  * @xas: Array operation state.
11458d6ea30SMatthew Wilcox  *
11558d6ea30SMatthew Wilcox  * Set a mark on the first entry if any entry has it set.  Clear marks on
11658d6ea30SMatthew Wilcox  * all sibling entries.
11758d6ea30SMatthew Wilcox  */
11858d6ea30SMatthew Wilcox static void xas_squash_marks(const struct xa_state *xas)
11958d6ea30SMatthew Wilcox {
12058d6ea30SMatthew Wilcox 	unsigned int mark = 0;
12158d6ea30SMatthew Wilcox 	unsigned int limit = xas->xa_offset + xas->xa_sibs + 1;
12258d6ea30SMatthew Wilcox 
12358d6ea30SMatthew Wilcox 	if (!xas->xa_sibs)
12458d6ea30SMatthew Wilcox 		return;
12558d6ea30SMatthew Wilcox 
12658d6ea30SMatthew Wilcox 	do {
12758d6ea30SMatthew Wilcox 		unsigned long *marks = xas->xa_node->marks[mark];
12858d6ea30SMatthew Wilcox 		if (find_next_bit(marks, limit, xas->xa_offset + 1) == limit)
12958d6ea30SMatthew Wilcox 			continue;
13058d6ea30SMatthew Wilcox 		__set_bit(xas->xa_offset, marks);
13158d6ea30SMatthew Wilcox 		bitmap_clear(marks, xas->xa_offset + 1, xas->xa_sibs);
13258d6ea30SMatthew Wilcox 	} while (mark++ != (__force unsigned)XA_MARK_MAX);
13358d6ea30SMatthew Wilcox }
13458d6ea30SMatthew Wilcox 
135ad3d6c72SMatthew Wilcox /* extracts the offset within this node from the index */
136ad3d6c72SMatthew Wilcox static unsigned int get_offset(unsigned long index, struct xa_node *node)
137ad3d6c72SMatthew Wilcox {
138ad3d6c72SMatthew Wilcox 	return (index >> node->shift) & XA_CHUNK_MASK;
139ad3d6c72SMatthew Wilcox }
140ad3d6c72SMatthew Wilcox 
141b803b428SMatthew Wilcox static void xas_set_offset(struct xa_state *xas)
142b803b428SMatthew Wilcox {
143b803b428SMatthew Wilcox 	xas->xa_offset = get_offset(xas->xa_index, xas->xa_node);
144b803b428SMatthew Wilcox }
145b803b428SMatthew Wilcox 
146ad3d6c72SMatthew Wilcox /* move the index either forwards (find) or backwards (sibling slot) */
147ad3d6c72SMatthew Wilcox static void xas_move_index(struct xa_state *xas, unsigned long offset)
148ad3d6c72SMatthew Wilcox {
149ad3d6c72SMatthew Wilcox 	unsigned int shift = xas->xa_node->shift;
150ad3d6c72SMatthew Wilcox 	xas->xa_index &= ~XA_CHUNK_MASK << shift;
151ad3d6c72SMatthew Wilcox 	xas->xa_index += offset << shift;
152ad3d6c72SMatthew Wilcox }
153ad3d6c72SMatthew Wilcox 
154b803b428SMatthew Wilcox static void xas_advance(struct xa_state *xas)
155b803b428SMatthew Wilcox {
156b803b428SMatthew Wilcox 	xas->xa_offset++;
157b803b428SMatthew Wilcox 	xas_move_index(xas, xas->xa_offset);
158b803b428SMatthew Wilcox }
159b803b428SMatthew Wilcox 
160ad3d6c72SMatthew Wilcox static void *set_bounds(struct xa_state *xas)
161ad3d6c72SMatthew Wilcox {
162ad3d6c72SMatthew Wilcox 	xas->xa_node = XAS_BOUNDS;
163ad3d6c72SMatthew Wilcox 	return NULL;
164ad3d6c72SMatthew Wilcox }
165ad3d6c72SMatthew Wilcox 
166ad3d6c72SMatthew Wilcox /*
167ad3d6c72SMatthew Wilcox  * Starts a walk.  If the @xas is already valid, we assume that it's on
168ad3d6c72SMatthew Wilcox  * the right path and just return where we've got to.  If we're in an
169ad3d6c72SMatthew Wilcox  * error state, return NULL.  If the index is outside the current scope
170ad3d6c72SMatthew Wilcox  * of the xarray, return NULL without changing @xas->xa_node.  Otherwise
171ad3d6c72SMatthew Wilcox  * set @xas->xa_node to NULL and return the current head of the array.
172ad3d6c72SMatthew Wilcox  */
173ad3d6c72SMatthew Wilcox static void *xas_start(struct xa_state *xas)
174ad3d6c72SMatthew Wilcox {
175ad3d6c72SMatthew Wilcox 	void *entry;
176ad3d6c72SMatthew Wilcox 
177ad3d6c72SMatthew Wilcox 	if (xas_valid(xas))
178ad3d6c72SMatthew Wilcox 		return xas_reload(xas);
179ad3d6c72SMatthew Wilcox 	if (xas_error(xas))
180ad3d6c72SMatthew Wilcox 		return NULL;
181ad3d6c72SMatthew Wilcox 
182ad3d6c72SMatthew Wilcox 	entry = xa_head(xas->xa);
183ad3d6c72SMatthew Wilcox 	if (!xa_is_node(entry)) {
184ad3d6c72SMatthew Wilcox 		if (xas->xa_index)
185ad3d6c72SMatthew Wilcox 			return set_bounds(xas);
186ad3d6c72SMatthew Wilcox 	} else {
187ad3d6c72SMatthew Wilcox 		if ((xas->xa_index >> xa_to_node(entry)->shift) > XA_CHUNK_MASK)
188ad3d6c72SMatthew Wilcox 			return set_bounds(xas);
189ad3d6c72SMatthew Wilcox 	}
190ad3d6c72SMatthew Wilcox 
191ad3d6c72SMatthew Wilcox 	xas->xa_node = NULL;
192ad3d6c72SMatthew Wilcox 	return entry;
193ad3d6c72SMatthew Wilcox }
194ad3d6c72SMatthew Wilcox 
195ad3d6c72SMatthew Wilcox static void *xas_descend(struct xa_state *xas, struct xa_node *node)
196ad3d6c72SMatthew Wilcox {
197ad3d6c72SMatthew Wilcox 	unsigned int offset = get_offset(xas->xa_index, node);
198ad3d6c72SMatthew Wilcox 	void *entry = xa_entry(xas->xa, node, offset);
199ad3d6c72SMatthew Wilcox 
200ad3d6c72SMatthew Wilcox 	xas->xa_node = node;
201ad3d6c72SMatthew Wilcox 	if (xa_is_sibling(entry)) {
202ad3d6c72SMatthew Wilcox 		offset = xa_to_sibling(entry);
203ad3d6c72SMatthew Wilcox 		entry = xa_entry(xas->xa, node, offset);
204ad3d6c72SMatthew Wilcox 	}
205ad3d6c72SMatthew Wilcox 
206ad3d6c72SMatthew Wilcox 	xas->xa_offset = offset;
207ad3d6c72SMatthew Wilcox 	return entry;
208ad3d6c72SMatthew Wilcox }
209ad3d6c72SMatthew Wilcox 
210ad3d6c72SMatthew Wilcox /**
211ad3d6c72SMatthew Wilcox  * xas_load() - Load an entry from the XArray (advanced).
212ad3d6c72SMatthew Wilcox  * @xas: XArray operation state.
213ad3d6c72SMatthew Wilcox  *
214ad3d6c72SMatthew Wilcox  * Usually walks the @xas to the appropriate state to load the entry
215ad3d6c72SMatthew Wilcox  * stored at xa_index.  However, it will do nothing and return %NULL if
216ad3d6c72SMatthew Wilcox  * @xas is in an error state.  xas_load() will never expand the tree.
217ad3d6c72SMatthew Wilcox  *
218ad3d6c72SMatthew Wilcox  * If the xa_state is set up to operate on a multi-index entry, xas_load()
219ad3d6c72SMatthew Wilcox  * may return %NULL or an internal entry, even if there are entries
220ad3d6c72SMatthew Wilcox  * present within the range specified by @xas.
221ad3d6c72SMatthew Wilcox  *
222ad3d6c72SMatthew Wilcox  * Context: Any context.  The caller should hold the xa_lock or the RCU lock.
223ad3d6c72SMatthew Wilcox  * Return: Usually an entry in the XArray, but see description for exceptions.
224ad3d6c72SMatthew Wilcox  */
225ad3d6c72SMatthew Wilcox void *xas_load(struct xa_state *xas)
226ad3d6c72SMatthew Wilcox {
227ad3d6c72SMatthew Wilcox 	void *entry = xas_start(xas);
228ad3d6c72SMatthew Wilcox 
229ad3d6c72SMatthew Wilcox 	while (xa_is_node(entry)) {
230ad3d6c72SMatthew Wilcox 		struct xa_node *node = xa_to_node(entry);
231ad3d6c72SMatthew Wilcox 
232ad3d6c72SMatthew Wilcox 		if (xas->xa_shift > node->shift)
233ad3d6c72SMatthew Wilcox 			break;
234ad3d6c72SMatthew Wilcox 		entry = xas_descend(xas, node);
235ad3d6c72SMatthew Wilcox 	}
236ad3d6c72SMatthew Wilcox 	return entry;
237ad3d6c72SMatthew Wilcox }
238ad3d6c72SMatthew Wilcox EXPORT_SYMBOL_GPL(xas_load);
239ad3d6c72SMatthew Wilcox 
24058d6ea30SMatthew Wilcox /* Move the radix tree node cache here */
24158d6ea30SMatthew Wilcox extern struct kmem_cache *radix_tree_node_cachep;
24258d6ea30SMatthew Wilcox extern void radix_tree_node_rcu_free(struct rcu_head *head);
24358d6ea30SMatthew Wilcox 
24458d6ea30SMatthew Wilcox #define XA_RCU_FREE	((struct xarray *)1)
24558d6ea30SMatthew Wilcox 
24658d6ea30SMatthew Wilcox static void xa_node_free(struct xa_node *node)
24758d6ea30SMatthew Wilcox {
24858d6ea30SMatthew Wilcox 	XA_NODE_BUG_ON(node, !list_empty(&node->private_list));
24958d6ea30SMatthew Wilcox 	node->array = XA_RCU_FREE;
25058d6ea30SMatthew Wilcox 	call_rcu(&node->rcu_head, radix_tree_node_rcu_free);
25158d6ea30SMatthew Wilcox }
25258d6ea30SMatthew Wilcox 
25358d6ea30SMatthew Wilcox /*
25458d6ea30SMatthew Wilcox  * xas_destroy() - Free any resources allocated during the XArray operation.
25558d6ea30SMatthew Wilcox  * @xas: XArray operation state.
25658d6ea30SMatthew Wilcox  *
25758d6ea30SMatthew Wilcox  * This function is now internal-only.
25858d6ea30SMatthew Wilcox  */
25958d6ea30SMatthew Wilcox static void xas_destroy(struct xa_state *xas)
26058d6ea30SMatthew Wilcox {
26158d6ea30SMatthew Wilcox 	struct xa_node *node = xas->xa_alloc;
26258d6ea30SMatthew Wilcox 
26358d6ea30SMatthew Wilcox 	if (!node)
26458d6ea30SMatthew Wilcox 		return;
26558d6ea30SMatthew Wilcox 	XA_NODE_BUG_ON(node, !list_empty(&node->private_list));
26658d6ea30SMatthew Wilcox 	kmem_cache_free(radix_tree_node_cachep, node);
26758d6ea30SMatthew Wilcox 	xas->xa_alloc = NULL;
26858d6ea30SMatthew Wilcox }
26958d6ea30SMatthew Wilcox 
27058d6ea30SMatthew Wilcox /**
27158d6ea30SMatthew Wilcox  * xas_nomem() - Allocate memory if needed.
27258d6ea30SMatthew Wilcox  * @xas: XArray operation state.
27358d6ea30SMatthew Wilcox  * @gfp: Memory allocation flags.
27458d6ea30SMatthew Wilcox  *
27558d6ea30SMatthew Wilcox  * If we need to add new nodes to the XArray, we try to allocate memory
27658d6ea30SMatthew Wilcox  * with GFP_NOWAIT while holding the lock, which will usually succeed.
27758d6ea30SMatthew Wilcox  * If it fails, @xas is flagged as needing memory to continue.  The caller
27858d6ea30SMatthew Wilcox  * should drop the lock and call xas_nomem().  If xas_nomem() succeeds,
27958d6ea30SMatthew Wilcox  * the caller should retry the operation.
28058d6ea30SMatthew Wilcox  *
28158d6ea30SMatthew Wilcox  * Forward progress is guaranteed as one node is allocated here and
28258d6ea30SMatthew Wilcox  * stored in the xa_state where it will be found by xas_alloc().  More
28358d6ea30SMatthew Wilcox  * nodes will likely be found in the slab allocator, but we do not tie
28458d6ea30SMatthew Wilcox  * them up here.
28558d6ea30SMatthew Wilcox  *
28658d6ea30SMatthew Wilcox  * Return: true if memory was needed, and was successfully allocated.
28758d6ea30SMatthew Wilcox  */
28858d6ea30SMatthew Wilcox bool xas_nomem(struct xa_state *xas, gfp_t gfp)
28958d6ea30SMatthew Wilcox {
29058d6ea30SMatthew Wilcox 	if (xas->xa_node != XA_ERROR(-ENOMEM)) {
29158d6ea30SMatthew Wilcox 		xas_destroy(xas);
29258d6ea30SMatthew Wilcox 		return false;
29358d6ea30SMatthew Wilcox 	}
29458d6ea30SMatthew Wilcox 	xas->xa_alloc = kmem_cache_alloc(radix_tree_node_cachep, gfp);
29558d6ea30SMatthew Wilcox 	if (!xas->xa_alloc)
29658d6ea30SMatthew Wilcox 		return false;
29758d6ea30SMatthew Wilcox 	XA_NODE_BUG_ON(xas->xa_alloc, !list_empty(&xas->xa_alloc->private_list));
29858d6ea30SMatthew Wilcox 	xas->xa_node = XAS_RESTART;
29958d6ea30SMatthew Wilcox 	return true;
30058d6ea30SMatthew Wilcox }
30158d6ea30SMatthew Wilcox EXPORT_SYMBOL_GPL(xas_nomem);
30258d6ea30SMatthew Wilcox 
30358d6ea30SMatthew Wilcox /*
30458d6ea30SMatthew Wilcox  * __xas_nomem() - Drop locks and allocate memory if needed.
30558d6ea30SMatthew Wilcox  * @xas: XArray operation state.
30658d6ea30SMatthew Wilcox  * @gfp: Memory allocation flags.
30758d6ea30SMatthew Wilcox  *
30858d6ea30SMatthew Wilcox  * Internal variant of xas_nomem().
30958d6ea30SMatthew Wilcox  *
31058d6ea30SMatthew Wilcox  * Return: true if memory was needed, and was successfully allocated.
31158d6ea30SMatthew Wilcox  */
31258d6ea30SMatthew Wilcox static bool __xas_nomem(struct xa_state *xas, gfp_t gfp)
31358d6ea30SMatthew Wilcox 	__must_hold(xas->xa->xa_lock)
31458d6ea30SMatthew Wilcox {
31558d6ea30SMatthew Wilcox 	unsigned int lock_type = xa_lock_type(xas->xa);
31658d6ea30SMatthew Wilcox 
31758d6ea30SMatthew Wilcox 	if (xas->xa_node != XA_ERROR(-ENOMEM)) {
31858d6ea30SMatthew Wilcox 		xas_destroy(xas);
31958d6ea30SMatthew Wilcox 		return false;
32058d6ea30SMatthew Wilcox 	}
32158d6ea30SMatthew Wilcox 	if (gfpflags_allow_blocking(gfp)) {
32258d6ea30SMatthew Wilcox 		xas_unlock_type(xas, lock_type);
32358d6ea30SMatthew Wilcox 		xas->xa_alloc = kmem_cache_alloc(radix_tree_node_cachep, gfp);
32458d6ea30SMatthew Wilcox 		xas_lock_type(xas, lock_type);
32558d6ea30SMatthew Wilcox 	} else {
32658d6ea30SMatthew Wilcox 		xas->xa_alloc = kmem_cache_alloc(radix_tree_node_cachep, gfp);
32758d6ea30SMatthew Wilcox 	}
32858d6ea30SMatthew Wilcox 	if (!xas->xa_alloc)
32958d6ea30SMatthew Wilcox 		return false;
33058d6ea30SMatthew Wilcox 	XA_NODE_BUG_ON(xas->xa_alloc, !list_empty(&xas->xa_alloc->private_list));
33158d6ea30SMatthew Wilcox 	xas->xa_node = XAS_RESTART;
33258d6ea30SMatthew Wilcox 	return true;
33358d6ea30SMatthew Wilcox }
33458d6ea30SMatthew Wilcox 
33558d6ea30SMatthew Wilcox static void xas_update(struct xa_state *xas, struct xa_node *node)
33658d6ea30SMatthew Wilcox {
33758d6ea30SMatthew Wilcox 	if (xas->xa_update)
33858d6ea30SMatthew Wilcox 		xas->xa_update(node);
33958d6ea30SMatthew Wilcox 	else
34058d6ea30SMatthew Wilcox 		XA_NODE_BUG_ON(node, !list_empty(&node->private_list));
34158d6ea30SMatthew Wilcox }
34258d6ea30SMatthew Wilcox 
34358d6ea30SMatthew Wilcox static void *xas_alloc(struct xa_state *xas, unsigned int shift)
34458d6ea30SMatthew Wilcox {
34558d6ea30SMatthew Wilcox 	struct xa_node *parent = xas->xa_node;
34658d6ea30SMatthew Wilcox 	struct xa_node *node = xas->xa_alloc;
34758d6ea30SMatthew Wilcox 
34858d6ea30SMatthew Wilcox 	if (xas_invalid(xas))
34958d6ea30SMatthew Wilcox 		return NULL;
35058d6ea30SMatthew Wilcox 
35158d6ea30SMatthew Wilcox 	if (node) {
35258d6ea30SMatthew Wilcox 		xas->xa_alloc = NULL;
35358d6ea30SMatthew Wilcox 	} else {
35458d6ea30SMatthew Wilcox 		node = kmem_cache_alloc(radix_tree_node_cachep,
35558d6ea30SMatthew Wilcox 					GFP_NOWAIT | __GFP_NOWARN);
35658d6ea30SMatthew Wilcox 		if (!node) {
35758d6ea30SMatthew Wilcox 			xas_set_err(xas, -ENOMEM);
35858d6ea30SMatthew Wilcox 			return NULL;
35958d6ea30SMatthew Wilcox 		}
36058d6ea30SMatthew Wilcox 	}
36158d6ea30SMatthew Wilcox 
36258d6ea30SMatthew Wilcox 	if (parent) {
36358d6ea30SMatthew Wilcox 		node->offset = xas->xa_offset;
36458d6ea30SMatthew Wilcox 		parent->count++;
36558d6ea30SMatthew Wilcox 		XA_NODE_BUG_ON(node, parent->count > XA_CHUNK_SIZE);
36658d6ea30SMatthew Wilcox 		xas_update(xas, parent);
36758d6ea30SMatthew Wilcox 	}
36858d6ea30SMatthew Wilcox 	XA_NODE_BUG_ON(node, shift > BITS_PER_LONG);
36958d6ea30SMatthew Wilcox 	XA_NODE_BUG_ON(node, !list_empty(&node->private_list));
37058d6ea30SMatthew Wilcox 	node->shift = shift;
37158d6ea30SMatthew Wilcox 	node->count = 0;
37258d6ea30SMatthew Wilcox 	node->nr_values = 0;
37358d6ea30SMatthew Wilcox 	RCU_INIT_POINTER(node->parent, xas->xa_node);
37458d6ea30SMatthew Wilcox 	node->array = xas->xa;
37558d6ea30SMatthew Wilcox 
37658d6ea30SMatthew Wilcox 	return node;
37758d6ea30SMatthew Wilcox }
37858d6ea30SMatthew Wilcox 
37958d6ea30SMatthew Wilcox /*
38058d6ea30SMatthew Wilcox  * Use this to calculate the maximum index that will need to be created
38158d6ea30SMatthew Wilcox  * in order to add the entry described by @xas.  Because we cannot store a
38258d6ea30SMatthew Wilcox  * multiple-index entry at index 0, the calculation is a little more complex
38358d6ea30SMatthew Wilcox  * than you might expect.
38458d6ea30SMatthew Wilcox  */
38558d6ea30SMatthew Wilcox static unsigned long xas_max(struct xa_state *xas)
38658d6ea30SMatthew Wilcox {
38758d6ea30SMatthew Wilcox 	unsigned long max = xas->xa_index;
38858d6ea30SMatthew Wilcox 
38958d6ea30SMatthew Wilcox #ifdef CONFIG_XARRAY_MULTI
39058d6ea30SMatthew Wilcox 	if (xas->xa_shift || xas->xa_sibs) {
39158d6ea30SMatthew Wilcox 		unsigned long mask;
39258d6ea30SMatthew Wilcox 		mask = (((xas->xa_sibs + 1UL) << xas->xa_shift) - 1);
39358d6ea30SMatthew Wilcox 		max |= mask;
39458d6ea30SMatthew Wilcox 		if (mask == max)
39558d6ea30SMatthew Wilcox 			max++;
39658d6ea30SMatthew Wilcox 	}
39758d6ea30SMatthew Wilcox #endif
39858d6ea30SMatthew Wilcox 
39958d6ea30SMatthew Wilcox 	return max;
40058d6ea30SMatthew Wilcox }
40158d6ea30SMatthew Wilcox 
40258d6ea30SMatthew Wilcox /* The maximum index that can be contained in the array without expanding it */
40358d6ea30SMatthew Wilcox static unsigned long max_index(void *entry)
40458d6ea30SMatthew Wilcox {
40558d6ea30SMatthew Wilcox 	if (!xa_is_node(entry))
40658d6ea30SMatthew Wilcox 		return 0;
40758d6ea30SMatthew Wilcox 	return (XA_CHUNK_SIZE << xa_to_node(entry)->shift) - 1;
40858d6ea30SMatthew Wilcox }
40958d6ea30SMatthew Wilcox 
41058d6ea30SMatthew Wilcox static void xas_shrink(struct xa_state *xas)
41158d6ea30SMatthew Wilcox {
41258d6ea30SMatthew Wilcox 	struct xarray *xa = xas->xa;
41358d6ea30SMatthew Wilcox 	struct xa_node *node = xas->xa_node;
41458d6ea30SMatthew Wilcox 
41558d6ea30SMatthew Wilcox 	for (;;) {
41658d6ea30SMatthew Wilcox 		void *entry;
41758d6ea30SMatthew Wilcox 
41858d6ea30SMatthew Wilcox 		XA_NODE_BUG_ON(node, node->count > XA_CHUNK_SIZE);
41958d6ea30SMatthew Wilcox 		if (node->count != 1)
42058d6ea30SMatthew Wilcox 			break;
42158d6ea30SMatthew Wilcox 		entry = xa_entry_locked(xa, node, 0);
42258d6ea30SMatthew Wilcox 		if (!entry)
42358d6ea30SMatthew Wilcox 			break;
42458d6ea30SMatthew Wilcox 		if (!xa_is_node(entry) && node->shift)
42558d6ea30SMatthew Wilcox 			break;
42658d6ea30SMatthew Wilcox 		xas->xa_node = XAS_BOUNDS;
42758d6ea30SMatthew Wilcox 
42858d6ea30SMatthew Wilcox 		RCU_INIT_POINTER(xa->xa_head, entry);
429*371c752dSMatthew Wilcox 		if (xa_track_free(xa) && !node_get_mark(node, 0, XA_FREE_MARK))
430*371c752dSMatthew Wilcox 			xa_mark_clear(xa, XA_FREE_MARK);
43158d6ea30SMatthew Wilcox 
43258d6ea30SMatthew Wilcox 		node->count = 0;
43358d6ea30SMatthew Wilcox 		node->nr_values = 0;
43458d6ea30SMatthew Wilcox 		if (!xa_is_node(entry))
43558d6ea30SMatthew Wilcox 			RCU_INIT_POINTER(node->slots[0], XA_RETRY_ENTRY);
43658d6ea30SMatthew Wilcox 		xas_update(xas, node);
43758d6ea30SMatthew Wilcox 		xa_node_free(node);
43858d6ea30SMatthew Wilcox 		if (!xa_is_node(entry))
43958d6ea30SMatthew Wilcox 			break;
44058d6ea30SMatthew Wilcox 		node = xa_to_node(entry);
44158d6ea30SMatthew Wilcox 		node->parent = NULL;
44258d6ea30SMatthew Wilcox 	}
44358d6ea30SMatthew Wilcox }
44458d6ea30SMatthew Wilcox 
44558d6ea30SMatthew Wilcox /*
44658d6ea30SMatthew Wilcox  * xas_delete_node() - Attempt to delete an xa_node
44758d6ea30SMatthew Wilcox  * @xas: Array operation state.
44858d6ea30SMatthew Wilcox  *
44958d6ea30SMatthew Wilcox  * Attempts to delete the @xas->xa_node.  This will fail if xa->node has
45058d6ea30SMatthew Wilcox  * a non-zero reference count.
45158d6ea30SMatthew Wilcox  */
45258d6ea30SMatthew Wilcox static void xas_delete_node(struct xa_state *xas)
45358d6ea30SMatthew Wilcox {
45458d6ea30SMatthew Wilcox 	struct xa_node *node = xas->xa_node;
45558d6ea30SMatthew Wilcox 
45658d6ea30SMatthew Wilcox 	for (;;) {
45758d6ea30SMatthew Wilcox 		struct xa_node *parent;
45858d6ea30SMatthew Wilcox 
45958d6ea30SMatthew Wilcox 		XA_NODE_BUG_ON(node, node->count > XA_CHUNK_SIZE);
46058d6ea30SMatthew Wilcox 		if (node->count)
46158d6ea30SMatthew Wilcox 			break;
46258d6ea30SMatthew Wilcox 
46358d6ea30SMatthew Wilcox 		parent = xa_parent_locked(xas->xa, node);
46458d6ea30SMatthew Wilcox 		xas->xa_node = parent;
46558d6ea30SMatthew Wilcox 		xas->xa_offset = node->offset;
46658d6ea30SMatthew Wilcox 		xa_node_free(node);
46758d6ea30SMatthew Wilcox 
46858d6ea30SMatthew Wilcox 		if (!parent) {
46958d6ea30SMatthew Wilcox 			xas->xa->xa_head = NULL;
47058d6ea30SMatthew Wilcox 			xas->xa_node = XAS_BOUNDS;
47158d6ea30SMatthew Wilcox 			return;
47258d6ea30SMatthew Wilcox 		}
47358d6ea30SMatthew Wilcox 
47458d6ea30SMatthew Wilcox 		parent->slots[xas->xa_offset] = NULL;
47558d6ea30SMatthew Wilcox 		parent->count--;
47658d6ea30SMatthew Wilcox 		XA_NODE_BUG_ON(parent, parent->count > XA_CHUNK_SIZE);
47758d6ea30SMatthew Wilcox 		node = parent;
47858d6ea30SMatthew Wilcox 		xas_update(xas, node);
47958d6ea30SMatthew Wilcox 	}
48058d6ea30SMatthew Wilcox 
48158d6ea30SMatthew Wilcox 	if (!node->parent)
48258d6ea30SMatthew Wilcox 		xas_shrink(xas);
48358d6ea30SMatthew Wilcox }
48458d6ea30SMatthew Wilcox 
48558d6ea30SMatthew Wilcox /**
48658d6ea30SMatthew Wilcox  * xas_free_nodes() - Free this node and all nodes that it references
48758d6ea30SMatthew Wilcox  * @xas: Array operation state.
48858d6ea30SMatthew Wilcox  * @top: Node to free
48958d6ea30SMatthew Wilcox  *
49058d6ea30SMatthew Wilcox  * This node has been removed from the tree.  We must now free it and all
49158d6ea30SMatthew Wilcox  * of its subnodes.  There may be RCU walkers with references into the tree,
49258d6ea30SMatthew Wilcox  * so we must replace all entries with retry markers.
49358d6ea30SMatthew Wilcox  */
49458d6ea30SMatthew Wilcox static void xas_free_nodes(struct xa_state *xas, struct xa_node *top)
49558d6ea30SMatthew Wilcox {
49658d6ea30SMatthew Wilcox 	unsigned int offset = 0;
49758d6ea30SMatthew Wilcox 	struct xa_node *node = top;
49858d6ea30SMatthew Wilcox 
49958d6ea30SMatthew Wilcox 	for (;;) {
50058d6ea30SMatthew Wilcox 		void *entry = xa_entry_locked(xas->xa, node, offset);
50158d6ea30SMatthew Wilcox 
50258d6ea30SMatthew Wilcox 		if (xa_is_node(entry)) {
50358d6ea30SMatthew Wilcox 			node = xa_to_node(entry);
50458d6ea30SMatthew Wilcox 			offset = 0;
50558d6ea30SMatthew Wilcox 			continue;
50658d6ea30SMatthew Wilcox 		}
50758d6ea30SMatthew Wilcox 		if (entry)
50858d6ea30SMatthew Wilcox 			RCU_INIT_POINTER(node->slots[offset], XA_RETRY_ENTRY);
50958d6ea30SMatthew Wilcox 		offset++;
51058d6ea30SMatthew Wilcox 		while (offset == XA_CHUNK_SIZE) {
51158d6ea30SMatthew Wilcox 			struct xa_node *parent;
51258d6ea30SMatthew Wilcox 
51358d6ea30SMatthew Wilcox 			parent = xa_parent_locked(xas->xa, node);
51458d6ea30SMatthew Wilcox 			offset = node->offset + 1;
51558d6ea30SMatthew Wilcox 			node->count = 0;
51658d6ea30SMatthew Wilcox 			node->nr_values = 0;
51758d6ea30SMatthew Wilcox 			xas_update(xas, node);
51858d6ea30SMatthew Wilcox 			xa_node_free(node);
51958d6ea30SMatthew Wilcox 			if (node == top)
52058d6ea30SMatthew Wilcox 				return;
52158d6ea30SMatthew Wilcox 			node = parent;
52258d6ea30SMatthew Wilcox 		}
52358d6ea30SMatthew Wilcox 	}
52458d6ea30SMatthew Wilcox }
52558d6ea30SMatthew Wilcox 
52658d6ea30SMatthew Wilcox /*
52758d6ea30SMatthew Wilcox  * xas_expand adds nodes to the head of the tree until it has reached
52858d6ea30SMatthew Wilcox  * sufficient height to be able to contain @xas->xa_index
52958d6ea30SMatthew Wilcox  */
53058d6ea30SMatthew Wilcox static int xas_expand(struct xa_state *xas, void *head)
53158d6ea30SMatthew Wilcox {
53258d6ea30SMatthew Wilcox 	struct xarray *xa = xas->xa;
53358d6ea30SMatthew Wilcox 	struct xa_node *node = NULL;
53458d6ea30SMatthew Wilcox 	unsigned int shift = 0;
53558d6ea30SMatthew Wilcox 	unsigned long max = xas_max(xas);
53658d6ea30SMatthew Wilcox 
53758d6ea30SMatthew Wilcox 	if (!head) {
53858d6ea30SMatthew Wilcox 		if (max == 0)
53958d6ea30SMatthew Wilcox 			return 0;
54058d6ea30SMatthew Wilcox 		while ((max >> shift) >= XA_CHUNK_SIZE)
54158d6ea30SMatthew Wilcox 			shift += XA_CHUNK_SHIFT;
54258d6ea30SMatthew Wilcox 		return shift + XA_CHUNK_SHIFT;
54358d6ea30SMatthew Wilcox 	} else if (xa_is_node(head)) {
54458d6ea30SMatthew Wilcox 		node = xa_to_node(head);
54558d6ea30SMatthew Wilcox 		shift = node->shift + XA_CHUNK_SHIFT;
54658d6ea30SMatthew Wilcox 	}
54758d6ea30SMatthew Wilcox 	xas->xa_node = NULL;
54858d6ea30SMatthew Wilcox 
54958d6ea30SMatthew Wilcox 	while (max > max_index(head)) {
55058d6ea30SMatthew Wilcox 		xa_mark_t mark = 0;
55158d6ea30SMatthew Wilcox 
55258d6ea30SMatthew Wilcox 		XA_NODE_BUG_ON(node, shift > BITS_PER_LONG);
55358d6ea30SMatthew Wilcox 		node = xas_alloc(xas, shift);
55458d6ea30SMatthew Wilcox 		if (!node)
55558d6ea30SMatthew Wilcox 			return -ENOMEM;
55658d6ea30SMatthew Wilcox 
55758d6ea30SMatthew Wilcox 		node->count = 1;
55858d6ea30SMatthew Wilcox 		if (xa_is_value(head))
55958d6ea30SMatthew Wilcox 			node->nr_values = 1;
56058d6ea30SMatthew Wilcox 		RCU_INIT_POINTER(node->slots[0], head);
56158d6ea30SMatthew Wilcox 
56258d6ea30SMatthew Wilcox 		/* Propagate the aggregated mark info to the new child */
56358d6ea30SMatthew Wilcox 		for (;;) {
564*371c752dSMatthew Wilcox 			if (xa_track_free(xa) && mark == XA_FREE_MARK) {
565*371c752dSMatthew Wilcox 				node_mark_all(node, XA_FREE_MARK);
566*371c752dSMatthew Wilcox 				if (!xa_marked(xa, XA_FREE_MARK)) {
567*371c752dSMatthew Wilcox 					node_clear_mark(node, 0, XA_FREE_MARK);
568*371c752dSMatthew Wilcox 					xa_mark_set(xa, XA_FREE_MARK);
569*371c752dSMatthew Wilcox 				}
570*371c752dSMatthew Wilcox 			} else if (xa_marked(xa, mark)) {
57158d6ea30SMatthew Wilcox 				node_set_mark(node, 0, mark);
572*371c752dSMatthew Wilcox 			}
57358d6ea30SMatthew Wilcox 			if (mark == XA_MARK_MAX)
57458d6ea30SMatthew Wilcox 				break;
57558d6ea30SMatthew Wilcox 			mark_inc(mark);
57658d6ea30SMatthew Wilcox 		}
57758d6ea30SMatthew Wilcox 
57858d6ea30SMatthew Wilcox 		/*
57958d6ea30SMatthew Wilcox 		 * Now that the new node is fully initialised, we can add
58058d6ea30SMatthew Wilcox 		 * it to the tree
58158d6ea30SMatthew Wilcox 		 */
58258d6ea30SMatthew Wilcox 		if (xa_is_node(head)) {
58358d6ea30SMatthew Wilcox 			xa_to_node(head)->offset = 0;
58458d6ea30SMatthew Wilcox 			rcu_assign_pointer(xa_to_node(head)->parent, node);
58558d6ea30SMatthew Wilcox 		}
58658d6ea30SMatthew Wilcox 		head = xa_mk_node(node);
58758d6ea30SMatthew Wilcox 		rcu_assign_pointer(xa->xa_head, head);
58858d6ea30SMatthew Wilcox 		xas_update(xas, node);
58958d6ea30SMatthew Wilcox 
59058d6ea30SMatthew Wilcox 		shift += XA_CHUNK_SHIFT;
59158d6ea30SMatthew Wilcox 	}
59258d6ea30SMatthew Wilcox 
59358d6ea30SMatthew Wilcox 	xas->xa_node = node;
59458d6ea30SMatthew Wilcox 	return shift;
59558d6ea30SMatthew Wilcox }
59658d6ea30SMatthew Wilcox 
59758d6ea30SMatthew Wilcox /*
59858d6ea30SMatthew Wilcox  * xas_create() - Create a slot to store an entry in.
59958d6ea30SMatthew Wilcox  * @xas: XArray operation state.
60058d6ea30SMatthew Wilcox  *
60158d6ea30SMatthew Wilcox  * Most users will not need to call this function directly, as it is called
60258d6ea30SMatthew Wilcox  * by xas_store().  It is useful for doing conditional store operations
60358d6ea30SMatthew Wilcox  * (see the xa_cmpxchg() implementation for an example).
60458d6ea30SMatthew Wilcox  *
60558d6ea30SMatthew Wilcox  * Return: If the slot already existed, returns the contents of this slot.
60658d6ea30SMatthew Wilcox  * If the slot was newly created, returns NULL.  If it failed to create the
60758d6ea30SMatthew Wilcox  * slot, returns NULL and indicates the error in @xas.
60858d6ea30SMatthew Wilcox  */
60958d6ea30SMatthew Wilcox static void *xas_create(struct xa_state *xas)
61058d6ea30SMatthew Wilcox {
61158d6ea30SMatthew Wilcox 	struct xarray *xa = xas->xa;
61258d6ea30SMatthew Wilcox 	void *entry;
61358d6ea30SMatthew Wilcox 	void __rcu **slot;
61458d6ea30SMatthew Wilcox 	struct xa_node *node = xas->xa_node;
61558d6ea30SMatthew Wilcox 	int shift;
61658d6ea30SMatthew Wilcox 	unsigned int order = xas->xa_shift;
61758d6ea30SMatthew Wilcox 
61858d6ea30SMatthew Wilcox 	if (xas_top(node)) {
61958d6ea30SMatthew Wilcox 		entry = xa_head_locked(xa);
62058d6ea30SMatthew Wilcox 		xas->xa_node = NULL;
62158d6ea30SMatthew Wilcox 		shift = xas_expand(xas, entry);
62258d6ea30SMatthew Wilcox 		if (shift < 0)
62358d6ea30SMatthew Wilcox 			return NULL;
62458d6ea30SMatthew Wilcox 		entry = xa_head_locked(xa);
62558d6ea30SMatthew Wilcox 		slot = &xa->xa_head;
62658d6ea30SMatthew Wilcox 	} else if (xas_error(xas)) {
62758d6ea30SMatthew Wilcox 		return NULL;
62858d6ea30SMatthew Wilcox 	} else if (node) {
62958d6ea30SMatthew Wilcox 		unsigned int offset = xas->xa_offset;
63058d6ea30SMatthew Wilcox 
63158d6ea30SMatthew Wilcox 		shift = node->shift;
63258d6ea30SMatthew Wilcox 		entry = xa_entry_locked(xa, node, offset);
63358d6ea30SMatthew Wilcox 		slot = &node->slots[offset];
63458d6ea30SMatthew Wilcox 	} else {
63558d6ea30SMatthew Wilcox 		shift = 0;
63658d6ea30SMatthew Wilcox 		entry = xa_head_locked(xa);
63758d6ea30SMatthew Wilcox 		slot = &xa->xa_head;
63858d6ea30SMatthew Wilcox 	}
63958d6ea30SMatthew Wilcox 
64058d6ea30SMatthew Wilcox 	while (shift > order) {
64158d6ea30SMatthew Wilcox 		shift -= XA_CHUNK_SHIFT;
64258d6ea30SMatthew Wilcox 		if (!entry) {
64358d6ea30SMatthew Wilcox 			node = xas_alloc(xas, shift);
64458d6ea30SMatthew Wilcox 			if (!node)
64558d6ea30SMatthew Wilcox 				break;
646*371c752dSMatthew Wilcox 			if (xa_track_free(xa))
647*371c752dSMatthew Wilcox 				node_mark_all(node, XA_FREE_MARK);
64858d6ea30SMatthew Wilcox 			rcu_assign_pointer(*slot, xa_mk_node(node));
64958d6ea30SMatthew Wilcox 		} else if (xa_is_node(entry)) {
65058d6ea30SMatthew Wilcox 			node = xa_to_node(entry);
65158d6ea30SMatthew Wilcox 		} else {
65258d6ea30SMatthew Wilcox 			break;
65358d6ea30SMatthew Wilcox 		}
65458d6ea30SMatthew Wilcox 		entry = xas_descend(xas, node);
65558d6ea30SMatthew Wilcox 		slot = &node->slots[xas->xa_offset];
65658d6ea30SMatthew Wilcox 	}
65758d6ea30SMatthew Wilcox 
65858d6ea30SMatthew Wilcox 	return entry;
65958d6ea30SMatthew Wilcox }
66058d6ea30SMatthew Wilcox 
6612264f513SMatthew Wilcox /**
6622264f513SMatthew Wilcox  * xas_create_range() - Ensure that stores to this range will succeed
6632264f513SMatthew Wilcox  * @xas: XArray operation state.
6642264f513SMatthew Wilcox  *
6652264f513SMatthew Wilcox  * Creates all of the slots in the range covered by @xas.  Sets @xas to
6662264f513SMatthew Wilcox  * create single-index entries and positions it at the beginning of the
6672264f513SMatthew Wilcox  * range.  This is for the benefit of users which have not yet been
6682264f513SMatthew Wilcox  * converted to use multi-index entries.
6692264f513SMatthew Wilcox  */
6702264f513SMatthew Wilcox void xas_create_range(struct xa_state *xas)
6712264f513SMatthew Wilcox {
6722264f513SMatthew Wilcox 	unsigned long index = xas->xa_index;
6732264f513SMatthew Wilcox 	unsigned char shift = xas->xa_shift;
6742264f513SMatthew Wilcox 	unsigned char sibs = xas->xa_sibs;
6752264f513SMatthew Wilcox 
6762264f513SMatthew Wilcox 	xas->xa_index |= ((sibs + 1) << shift) - 1;
6772264f513SMatthew Wilcox 	if (xas_is_node(xas) && xas->xa_node->shift == xas->xa_shift)
6782264f513SMatthew Wilcox 		xas->xa_offset |= sibs;
6792264f513SMatthew Wilcox 	xas->xa_shift = 0;
6802264f513SMatthew Wilcox 	xas->xa_sibs = 0;
6812264f513SMatthew Wilcox 
6822264f513SMatthew Wilcox 	for (;;) {
6832264f513SMatthew Wilcox 		xas_create(xas);
6842264f513SMatthew Wilcox 		if (xas_error(xas))
6852264f513SMatthew Wilcox 			goto restore;
6862264f513SMatthew Wilcox 		if (xas->xa_index <= (index | XA_CHUNK_MASK))
6872264f513SMatthew Wilcox 			goto success;
6882264f513SMatthew Wilcox 		xas->xa_index -= XA_CHUNK_SIZE;
6892264f513SMatthew Wilcox 
6902264f513SMatthew Wilcox 		for (;;) {
6912264f513SMatthew Wilcox 			struct xa_node *node = xas->xa_node;
6922264f513SMatthew Wilcox 			xas->xa_node = xa_parent_locked(xas->xa, node);
6932264f513SMatthew Wilcox 			xas->xa_offset = node->offset - 1;
6942264f513SMatthew Wilcox 			if (node->offset != 0)
6952264f513SMatthew Wilcox 				break;
6962264f513SMatthew Wilcox 		}
6972264f513SMatthew Wilcox 	}
6982264f513SMatthew Wilcox 
6992264f513SMatthew Wilcox restore:
7002264f513SMatthew Wilcox 	xas->xa_shift = shift;
7012264f513SMatthew Wilcox 	xas->xa_sibs = sibs;
7022264f513SMatthew Wilcox 	xas->xa_index = index;
7032264f513SMatthew Wilcox 	return;
7042264f513SMatthew Wilcox success:
7052264f513SMatthew Wilcox 	xas->xa_index = index;
7062264f513SMatthew Wilcox 	if (xas->xa_node)
7072264f513SMatthew Wilcox 		xas_set_offset(xas);
7082264f513SMatthew Wilcox }
7092264f513SMatthew Wilcox EXPORT_SYMBOL_GPL(xas_create_range);
7102264f513SMatthew Wilcox 
71158d6ea30SMatthew Wilcox static void update_node(struct xa_state *xas, struct xa_node *node,
71258d6ea30SMatthew Wilcox 		int count, int values)
71358d6ea30SMatthew Wilcox {
71458d6ea30SMatthew Wilcox 	if (!node || (!count && !values))
71558d6ea30SMatthew Wilcox 		return;
71658d6ea30SMatthew Wilcox 
71758d6ea30SMatthew Wilcox 	node->count += count;
71858d6ea30SMatthew Wilcox 	node->nr_values += values;
71958d6ea30SMatthew Wilcox 	XA_NODE_BUG_ON(node, node->count > XA_CHUNK_SIZE);
72058d6ea30SMatthew Wilcox 	XA_NODE_BUG_ON(node, node->nr_values > XA_CHUNK_SIZE);
72158d6ea30SMatthew Wilcox 	xas_update(xas, node);
72258d6ea30SMatthew Wilcox 	if (count < 0)
72358d6ea30SMatthew Wilcox 		xas_delete_node(xas);
72458d6ea30SMatthew Wilcox }
72558d6ea30SMatthew Wilcox 
72658d6ea30SMatthew Wilcox /**
72758d6ea30SMatthew Wilcox  * xas_store() - Store this entry in the XArray.
72858d6ea30SMatthew Wilcox  * @xas: XArray operation state.
72958d6ea30SMatthew Wilcox  * @entry: New entry.
73058d6ea30SMatthew Wilcox  *
73158d6ea30SMatthew Wilcox  * If @xas is operating on a multi-index entry, the entry returned by this
73258d6ea30SMatthew Wilcox  * function is essentially meaningless (it may be an internal entry or it
73358d6ea30SMatthew Wilcox  * may be %NULL, even if there are non-NULL entries at some of the indices
73458d6ea30SMatthew Wilcox  * covered by the range).  This is not a problem for any current users,
73558d6ea30SMatthew Wilcox  * and can be changed if needed.
73658d6ea30SMatthew Wilcox  *
73758d6ea30SMatthew Wilcox  * Return: The old entry at this index.
73858d6ea30SMatthew Wilcox  */
73958d6ea30SMatthew Wilcox void *xas_store(struct xa_state *xas, void *entry)
74058d6ea30SMatthew Wilcox {
74158d6ea30SMatthew Wilcox 	struct xa_node *node;
74258d6ea30SMatthew Wilcox 	void __rcu **slot = &xas->xa->xa_head;
74358d6ea30SMatthew Wilcox 	unsigned int offset, max;
74458d6ea30SMatthew Wilcox 	int count = 0;
74558d6ea30SMatthew Wilcox 	int values = 0;
74658d6ea30SMatthew Wilcox 	void *first, *next;
74758d6ea30SMatthew Wilcox 	bool value = xa_is_value(entry);
74858d6ea30SMatthew Wilcox 
74958d6ea30SMatthew Wilcox 	if (entry)
75058d6ea30SMatthew Wilcox 		first = xas_create(xas);
75158d6ea30SMatthew Wilcox 	else
75258d6ea30SMatthew Wilcox 		first = xas_load(xas);
75358d6ea30SMatthew Wilcox 
75458d6ea30SMatthew Wilcox 	if (xas_invalid(xas))
75558d6ea30SMatthew Wilcox 		return first;
75658d6ea30SMatthew Wilcox 	node = xas->xa_node;
75758d6ea30SMatthew Wilcox 	if (node && (xas->xa_shift < node->shift))
75858d6ea30SMatthew Wilcox 		xas->xa_sibs = 0;
75958d6ea30SMatthew Wilcox 	if ((first == entry) && !xas->xa_sibs)
76058d6ea30SMatthew Wilcox 		return first;
76158d6ea30SMatthew Wilcox 
76258d6ea30SMatthew Wilcox 	next = first;
76358d6ea30SMatthew Wilcox 	offset = xas->xa_offset;
76458d6ea30SMatthew Wilcox 	max = xas->xa_offset + xas->xa_sibs;
76558d6ea30SMatthew Wilcox 	if (node) {
76658d6ea30SMatthew Wilcox 		slot = &node->slots[offset];
76758d6ea30SMatthew Wilcox 		if (xas->xa_sibs)
76858d6ea30SMatthew Wilcox 			xas_squash_marks(xas);
76958d6ea30SMatthew Wilcox 	}
77058d6ea30SMatthew Wilcox 	if (!entry)
77158d6ea30SMatthew Wilcox 		xas_init_marks(xas);
77258d6ea30SMatthew Wilcox 
77358d6ea30SMatthew Wilcox 	for (;;) {
77458d6ea30SMatthew Wilcox 		/*
77558d6ea30SMatthew Wilcox 		 * Must clear the marks before setting the entry to NULL,
77658d6ea30SMatthew Wilcox 		 * otherwise xas_for_each_marked may find a NULL entry and
77758d6ea30SMatthew Wilcox 		 * stop early.  rcu_assign_pointer contains a release barrier
77858d6ea30SMatthew Wilcox 		 * so the mark clearing will appear to happen before the
77958d6ea30SMatthew Wilcox 		 * entry is set to NULL.
78058d6ea30SMatthew Wilcox 		 */
78158d6ea30SMatthew Wilcox 		rcu_assign_pointer(*slot, entry);
78258d6ea30SMatthew Wilcox 		if (xa_is_node(next))
78358d6ea30SMatthew Wilcox 			xas_free_nodes(xas, xa_to_node(next));
78458d6ea30SMatthew Wilcox 		if (!node)
78558d6ea30SMatthew Wilcox 			break;
78658d6ea30SMatthew Wilcox 		count += !next - !entry;
78758d6ea30SMatthew Wilcox 		values += !xa_is_value(first) - !value;
78858d6ea30SMatthew Wilcox 		if (entry) {
78958d6ea30SMatthew Wilcox 			if (offset == max)
79058d6ea30SMatthew Wilcox 				break;
79158d6ea30SMatthew Wilcox 			if (!xa_is_sibling(entry))
79258d6ea30SMatthew Wilcox 				entry = xa_mk_sibling(xas->xa_offset);
79358d6ea30SMatthew Wilcox 		} else {
79458d6ea30SMatthew Wilcox 			if (offset == XA_CHUNK_MASK)
79558d6ea30SMatthew Wilcox 				break;
79658d6ea30SMatthew Wilcox 		}
79758d6ea30SMatthew Wilcox 		next = xa_entry_locked(xas->xa, node, ++offset);
79858d6ea30SMatthew Wilcox 		if (!xa_is_sibling(next)) {
79958d6ea30SMatthew Wilcox 			if (!entry && (offset > max))
80058d6ea30SMatthew Wilcox 				break;
80158d6ea30SMatthew Wilcox 			first = next;
80258d6ea30SMatthew Wilcox 		}
80358d6ea30SMatthew Wilcox 		slot++;
80458d6ea30SMatthew Wilcox 	}
80558d6ea30SMatthew Wilcox 
80658d6ea30SMatthew Wilcox 	update_node(xas, node, count, values);
80758d6ea30SMatthew Wilcox 	return first;
80858d6ea30SMatthew Wilcox }
80958d6ea30SMatthew Wilcox EXPORT_SYMBOL_GPL(xas_store);
81058d6ea30SMatthew Wilcox 
811f8d5d0ccSMatthew Wilcox /**
8129b89a035SMatthew Wilcox  * xas_get_mark() - Returns the state of this mark.
8139b89a035SMatthew Wilcox  * @xas: XArray operation state.
8149b89a035SMatthew Wilcox  * @mark: Mark number.
8159b89a035SMatthew Wilcox  *
8169b89a035SMatthew Wilcox  * Return: true if the mark is set, false if the mark is clear or @xas
8179b89a035SMatthew Wilcox  * is in an error state.
8189b89a035SMatthew Wilcox  */
8199b89a035SMatthew Wilcox bool xas_get_mark(const struct xa_state *xas, xa_mark_t mark)
8209b89a035SMatthew Wilcox {
8219b89a035SMatthew Wilcox 	if (xas_invalid(xas))
8229b89a035SMatthew Wilcox 		return false;
8239b89a035SMatthew Wilcox 	if (!xas->xa_node)
8249b89a035SMatthew Wilcox 		return xa_marked(xas->xa, mark);
8259b89a035SMatthew Wilcox 	return node_get_mark(xas->xa_node, xas->xa_offset, mark);
8269b89a035SMatthew Wilcox }
8279b89a035SMatthew Wilcox EXPORT_SYMBOL_GPL(xas_get_mark);
8289b89a035SMatthew Wilcox 
8299b89a035SMatthew Wilcox /**
8309b89a035SMatthew Wilcox  * xas_set_mark() - Sets the mark on this entry and its parents.
8319b89a035SMatthew Wilcox  * @xas: XArray operation state.
8329b89a035SMatthew Wilcox  * @mark: Mark number.
8339b89a035SMatthew Wilcox  *
8349b89a035SMatthew Wilcox  * Sets the specified mark on this entry, and walks up the tree setting it
8359b89a035SMatthew Wilcox  * on all the ancestor entries.  Does nothing if @xas has not been walked to
8369b89a035SMatthew Wilcox  * an entry, or is in an error state.
8379b89a035SMatthew Wilcox  */
8389b89a035SMatthew Wilcox void xas_set_mark(const struct xa_state *xas, xa_mark_t mark)
8399b89a035SMatthew Wilcox {
8409b89a035SMatthew Wilcox 	struct xa_node *node = xas->xa_node;
8419b89a035SMatthew Wilcox 	unsigned int offset = xas->xa_offset;
8429b89a035SMatthew Wilcox 
8439b89a035SMatthew Wilcox 	if (xas_invalid(xas))
8449b89a035SMatthew Wilcox 		return;
8459b89a035SMatthew Wilcox 
8469b89a035SMatthew Wilcox 	while (node) {
8479b89a035SMatthew Wilcox 		if (node_set_mark(node, offset, mark))
8489b89a035SMatthew Wilcox 			return;
8499b89a035SMatthew Wilcox 		offset = node->offset;
8509b89a035SMatthew Wilcox 		node = xa_parent_locked(xas->xa, node);
8519b89a035SMatthew Wilcox 	}
8529b89a035SMatthew Wilcox 
8539b89a035SMatthew Wilcox 	if (!xa_marked(xas->xa, mark))
8549b89a035SMatthew Wilcox 		xa_mark_set(xas->xa, mark);
8559b89a035SMatthew Wilcox }
8569b89a035SMatthew Wilcox EXPORT_SYMBOL_GPL(xas_set_mark);
8579b89a035SMatthew Wilcox 
8589b89a035SMatthew Wilcox /**
8599b89a035SMatthew Wilcox  * xas_clear_mark() - Clears the mark on this entry and its parents.
8609b89a035SMatthew Wilcox  * @xas: XArray operation state.
8619b89a035SMatthew Wilcox  * @mark: Mark number.
8629b89a035SMatthew Wilcox  *
8639b89a035SMatthew Wilcox  * Clears the specified mark on this entry, and walks back to the head
8649b89a035SMatthew Wilcox  * attempting to clear it on all the ancestor entries.  Does nothing if
8659b89a035SMatthew Wilcox  * @xas has not been walked to an entry, or is in an error state.
8669b89a035SMatthew Wilcox  */
8679b89a035SMatthew Wilcox void xas_clear_mark(const struct xa_state *xas, xa_mark_t mark)
8689b89a035SMatthew Wilcox {
8699b89a035SMatthew Wilcox 	struct xa_node *node = xas->xa_node;
8709b89a035SMatthew Wilcox 	unsigned int offset = xas->xa_offset;
8719b89a035SMatthew Wilcox 
8729b89a035SMatthew Wilcox 	if (xas_invalid(xas))
8739b89a035SMatthew Wilcox 		return;
8749b89a035SMatthew Wilcox 
8759b89a035SMatthew Wilcox 	while (node) {
8769b89a035SMatthew Wilcox 		if (!node_clear_mark(node, offset, mark))
8779b89a035SMatthew Wilcox 			return;
8789b89a035SMatthew Wilcox 		if (node_any_mark(node, mark))
8799b89a035SMatthew Wilcox 			return;
8809b89a035SMatthew Wilcox 
8819b89a035SMatthew Wilcox 		offset = node->offset;
8829b89a035SMatthew Wilcox 		node = xa_parent_locked(xas->xa, node);
8839b89a035SMatthew Wilcox 	}
8849b89a035SMatthew Wilcox 
8859b89a035SMatthew Wilcox 	if (xa_marked(xas->xa, mark))
8869b89a035SMatthew Wilcox 		xa_mark_clear(xas->xa, mark);
8879b89a035SMatthew Wilcox }
8889b89a035SMatthew Wilcox EXPORT_SYMBOL_GPL(xas_clear_mark);
8899b89a035SMatthew Wilcox 
8909b89a035SMatthew Wilcox /**
89158d6ea30SMatthew Wilcox  * xas_init_marks() - Initialise all marks for the entry
89258d6ea30SMatthew Wilcox  * @xas: Array operations state.
89358d6ea30SMatthew Wilcox  *
89458d6ea30SMatthew Wilcox  * Initialise all marks for the entry specified by @xas.  If we're tracking
89558d6ea30SMatthew Wilcox  * free entries with a mark, we need to set it on all entries.  All other
89658d6ea30SMatthew Wilcox  * marks are cleared.
89758d6ea30SMatthew Wilcox  *
89858d6ea30SMatthew Wilcox  * This implementation is not as efficient as it could be; we may walk
89958d6ea30SMatthew Wilcox  * up the tree multiple times.
90058d6ea30SMatthew Wilcox  */
90158d6ea30SMatthew Wilcox void xas_init_marks(const struct xa_state *xas)
90258d6ea30SMatthew Wilcox {
90358d6ea30SMatthew Wilcox 	xa_mark_t mark = 0;
90458d6ea30SMatthew Wilcox 
90558d6ea30SMatthew Wilcox 	for (;;) {
906*371c752dSMatthew Wilcox 		if (xa_track_free(xas->xa) && mark == XA_FREE_MARK)
907*371c752dSMatthew Wilcox 			xas_set_mark(xas, mark);
908*371c752dSMatthew Wilcox 		else
90958d6ea30SMatthew Wilcox 			xas_clear_mark(xas, mark);
91058d6ea30SMatthew Wilcox 		if (mark == XA_MARK_MAX)
91158d6ea30SMatthew Wilcox 			break;
91258d6ea30SMatthew Wilcox 		mark_inc(mark);
91358d6ea30SMatthew Wilcox 	}
91458d6ea30SMatthew Wilcox }
91558d6ea30SMatthew Wilcox EXPORT_SYMBOL_GPL(xas_init_marks);
91658d6ea30SMatthew Wilcox 
91758d6ea30SMatthew Wilcox /**
918b803b428SMatthew Wilcox  * xas_pause() - Pause a walk to drop a lock.
919b803b428SMatthew Wilcox  * @xas: XArray operation state.
920b803b428SMatthew Wilcox  *
921b803b428SMatthew Wilcox  * Some users need to pause a walk and drop the lock they're holding in
922b803b428SMatthew Wilcox  * order to yield to a higher priority thread or carry out an operation
923b803b428SMatthew Wilcox  * on an entry.  Those users should call this function before they drop
924b803b428SMatthew Wilcox  * the lock.  It resets the @xas to be suitable for the next iteration
925b803b428SMatthew Wilcox  * of the loop after the user has reacquired the lock.  If most entries
926b803b428SMatthew Wilcox  * found during a walk require you to call xas_pause(), the xa_for_each()
927b803b428SMatthew Wilcox  * iterator may be more appropriate.
928b803b428SMatthew Wilcox  *
929b803b428SMatthew Wilcox  * Note that xas_pause() only works for forward iteration.  If a user needs
930b803b428SMatthew Wilcox  * to pause a reverse iteration, we will need a xas_pause_rev().
931b803b428SMatthew Wilcox  */
932b803b428SMatthew Wilcox void xas_pause(struct xa_state *xas)
933b803b428SMatthew Wilcox {
934b803b428SMatthew Wilcox 	struct xa_node *node = xas->xa_node;
935b803b428SMatthew Wilcox 
936b803b428SMatthew Wilcox 	if (xas_invalid(xas))
937b803b428SMatthew Wilcox 		return;
938b803b428SMatthew Wilcox 
939b803b428SMatthew Wilcox 	if (node) {
940b803b428SMatthew Wilcox 		unsigned int offset = xas->xa_offset;
941b803b428SMatthew Wilcox 		while (++offset < XA_CHUNK_SIZE) {
942b803b428SMatthew Wilcox 			if (!xa_is_sibling(xa_entry(xas->xa, node, offset)))
943b803b428SMatthew Wilcox 				break;
944b803b428SMatthew Wilcox 		}
945b803b428SMatthew Wilcox 		xas->xa_index += (offset - xas->xa_offset) << node->shift;
946b803b428SMatthew Wilcox 	} else {
947b803b428SMatthew Wilcox 		xas->xa_index++;
948b803b428SMatthew Wilcox 	}
949b803b428SMatthew Wilcox 	xas->xa_node = XAS_RESTART;
950b803b428SMatthew Wilcox }
951b803b428SMatthew Wilcox EXPORT_SYMBOL_GPL(xas_pause);
952b803b428SMatthew Wilcox 
95364d3e9a9SMatthew Wilcox /*
95464d3e9a9SMatthew Wilcox  * __xas_prev() - Find the previous entry in the XArray.
95564d3e9a9SMatthew Wilcox  * @xas: XArray operation state.
95664d3e9a9SMatthew Wilcox  *
95764d3e9a9SMatthew Wilcox  * Helper function for xas_prev() which handles all the complex cases
95864d3e9a9SMatthew Wilcox  * out of line.
95964d3e9a9SMatthew Wilcox  */
96064d3e9a9SMatthew Wilcox void *__xas_prev(struct xa_state *xas)
96164d3e9a9SMatthew Wilcox {
96264d3e9a9SMatthew Wilcox 	void *entry;
96364d3e9a9SMatthew Wilcox 
96464d3e9a9SMatthew Wilcox 	if (!xas_frozen(xas->xa_node))
96564d3e9a9SMatthew Wilcox 		xas->xa_index--;
96664d3e9a9SMatthew Wilcox 	if (xas_not_node(xas->xa_node))
96764d3e9a9SMatthew Wilcox 		return xas_load(xas);
96864d3e9a9SMatthew Wilcox 
96964d3e9a9SMatthew Wilcox 	if (xas->xa_offset != get_offset(xas->xa_index, xas->xa_node))
97064d3e9a9SMatthew Wilcox 		xas->xa_offset--;
97164d3e9a9SMatthew Wilcox 
97264d3e9a9SMatthew Wilcox 	while (xas->xa_offset == 255) {
97364d3e9a9SMatthew Wilcox 		xas->xa_offset = xas->xa_node->offset - 1;
97464d3e9a9SMatthew Wilcox 		xas->xa_node = xa_parent(xas->xa, xas->xa_node);
97564d3e9a9SMatthew Wilcox 		if (!xas->xa_node)
97664d3e9a9SMatthew Wilcox 			return set_bounds(xas);
97764d3e9a9SMatthew Wilcox 	}
97864d3e9a9SMatthew Wilcox 
97964d3e9a9SMatthew Wilcox 	for (;;) {
98064d3e9a9SMatthew Wilcox 		entry = xa_entry(xas->xa, xas->xa_node, xas->xa_offset);
98164d3e9a9SMatthew Wilcox 		if (!xa_is_node(entry))
98264d3e9a9SMatthew Wilcox 			return entry;
98364d3e9a9SMatthew Wilcox 
98464d3e9a9SMatthew Wilcox 		xas->xa_node = xa_to_node(entry);
98564d3e9a9SMatthew Wilcox 		xas_set_offset(xas);
98664d3e9a9SMatthew Wilcox 	}
98764d3e9a9SMatthew Wilcox }
98864d3e9a9SMatthew Wilcox EXPORT_SYMBOL_GPL(__xas_prev);
98964d3e9a9SMatthew Wilcox 
99064d3e9a9SMatthew Wilcox /*
99164d3e9a9SMatthew Wilcox  * __xas_next() - Find the next entry in the XArray.
99264d3e9a9SMatthew Wilcox  * @xas: XArray operation state.
99364d3e9a9SMatthew Wilcox  *
99464d3e9a9SMatthew Wilcox  * Helper function for xas_next() which handles all the complex cases
99564d3e9a9SMatthew Wilcox  * out of line.
99664d3e9a9SMatthew Wilcox  */
99764d3e9a9SMatthew Wilcox void *__xas_next(struct xa_state *xas)
99864d3e9a9SMatthew Wilcox {
99964d3e9a9SMatthew Wilcox 	void *entry;
100064d3e9a9SMatthew Wilcox 
100164d3e9a9SMatthew Wilcox 	if (!xas_frozen(xas->xa_node))
100264d3e9a9SMatthew Wilcox 		xas->xa_index++;
100364d3e9a9SMatthew Wilcox 	if (xas_not_node(xas->xa_node))
100464d3e9a9SMatthew Wilcox 		return xas_load(xas);
100564d3e9a9SMatthew Wilcox 
100664d3e9a9SMatthew Wilcox 	if (xas->xa_offset != get_offset(xas->xa_index, xas->xa_node))
100764d3e9a9SMatthew Wilcox 		xas->xa_offset++;
100864d3e9a9SMatthew Wilcox 
100964d3e9a9SMatthew Wilcox 	while (xas->xa_offset == XA_CHUNK_SIZE) {
101064d3e9a9SMatthew Wilcox 		xas->xa_offset = xas->xa_node->offset + 1;
101164d3e9a9SMatthew Wilcox 		xas->xa_node = xa_parent(xas->xa, xas->xa_node);
101264d3e9a9SMatthew Wilcox 		if (!xas->xa_node)
101364d3e9a9SMatthew Wilcox 			return set_bounds(xas);
101464d3e9a9SMatthew Wilcox 	}
101564d3e9a9SMatthew Wilcox 
101664d3e9a9SMatthew Wilcox 	for (;;) {
101764d3e9a9SMatthew Wilcox 		entry = xa_entry(xas->xa, xas->xa_node, xas->xa_offset);
101864d3e9a9SMatthew Wilcox 		if (!xa_is_node(entry))
101964d3e9a9SMatthew Wilcox 			return entry;
102064d3e9a9SMatthew Wilcox 
102164d3e9a9SMatthew Wilcox 		xas->xa_node = xa_to_node(entry);
102264d3e9a9SMatthew Wilcox 		xas_set_offset(xas);
102364d3e9a9SMatthew Wilcox 	}
102464d3e9a9SMatthew Wilcox }
102564d3e9a9SMatthew Wilcox EXPORT_SYMBOL_GPL(__xas_next);
102664d3e9a9SMatthew Wilcox 
1027b803b428SMatthew Wilcox /**
1028b803b428SMatthew Wilcox  * xas_find() - Find the next present entry in the XArray.
1029b803b428SMatthew Wilcox  * @xas: XArray operation state.
1030b803b428SMatthew Wilcox  * @max: Highest index to return.
1031b803b428SMatthew Wilcox  *
1032b803b428SMatthew Wilcox  * If the @xas has not yet been walked to an entry, return the entry
1033b803b428SMatthew Wilcox  * which has an index >= xas.xa_index.  If it has been walked, the entry
1034b803b428SMatthew Wilcox  * currently being pointed at has been processed, and so we move to the
1035b803b428SMatthew Wilcox  * next entry.
1036b803b428SMatthew Wilcox  *
1037b803b428SMatthew Wilcox  * If no entry is found and the array is smaller than @max, the iterator
1038b803b428SMatthew Wilcox  * is set to the smallest index not yet in the array.  This allows @xas
1039b803b428SMatthew Wilcox  * to be immediately passed to xas_store().
1040b803b428SMatthew Wilcox  *
1041b803b428SMatthew Wilcox  * Return: The entry, if found, otherwise %NULL.
1042b803b428SMatthew Wilcox  */
1043b803b428SMatthew Wilcox void *xas_find(struct xa_state *xas, unsigned long max)
1044b803b428SMatthew Wilcox {
1045b803b428SMatthew Wilcox 	void *entry;
1046b803b428SMatthew Wilcox 
1047b803b428SMatthew Wilcox 	if (xas_error(xas))
1048b803b428SMatthew Wilcox 		return NULL;
1049b803b428SMatthew Wilcox 
1050b803b428SMatthew Wilcox 	if (!xas->xa_node) {
1051b803b428SMatthew Wilcox 		xas->xa_index = 1;
1052b803b428SMatthew Wilcox 		return set_bounds(xas);
1053b803b428SMatthew Wilcox 	} else if (xas_top(xas->xa_node)) {
1054b803b428SMatthew Wilcox 		entry = xas_load(xas);
1055b803b428SMatthew Wilcox 		if (entry || xas_not_node(xas->xa_node))
1056b803b428SMatthew Wilcox 			return entry;
1057b803b428SMatthew Wilcox 	} else if (!xas->xa_node->shift &&
1058b803b428SMatthew Wilcox 		    xas->xa_offset != (xas->xa_index & XA_CHUNK_MASK)) {
1059b803b428SMatthew Wilcox 		xas->xa_offset = ((xas->xa_index - 1) & XA_CHUNK_MASK) + 1;
1060b803b428SMatthew Wilcox 	}
1061b803b428SMatthew Wilcox 
1062b803b428SMatthew Wilcox 	xas_advance(xas);
1063b803b428SMatthew Wilcox 
1064b803b428SMatthew Wilcox 	while (xas->xa_node && (xas->xa_index <= max)) {
1065b803b428SMatthew Wilcox 		if (unlikely(xas->xa_offset == XA_CHUNK_SIZE)) {
1066b803b428SMatthew Wilcox 			xas->xa_offset = xas->xa_node->offset + 1;
1067b803b428SMatthew Wilcox 			xas->xa_node = xa_parent(xas->xa, xas->xa_node);
1068b803b428SMatthew Wilcox 			continue;
1069b803b428SMatthew Wilcox 		}
1070b803b428SMatthew Wilcox 
1071b803b428SMatthew Wilcox 		entry = xa_entry(xas->xa, xas->xa_node, xas->xa_offset);
1072b803b428SMatthew Wilcox 		if (xa_is_node(entry)) {
1073b803b428SMatthew Wilcox 			xas->xa_node = xa_to_node(entry);
1074b803b428SMatthew Wilcox 			xas->xa_offset = 0;
1075b803b428SMatthew Wilcox 			continue;
1076b803b428SMatthew Wilcox 		}
1077b803b428SMatthew Wilcox 		if (entry && !xa_is_sibling(entry))
1078b803b428SMatthew Wilcox 			return entry;
1079b803b428SMatthew Wilcox 
1080b803b428SMatthew Wilcox 		xas_advance(xas);
1081b803b428SMatthew Wilcox 	}
1082b803b428SMatthew Wilcox 
1083b803b428SMatthew Wilcox 	if (!xas->xa_node)
1084b803b428SMatthew Wilcox 		xas->xa_node = XAS_BOUNDS;
1085b803b428SMatthew Wilcox 	return NULL;
1086b803b428SMatthew Wilcox }
1087b803b428SMatthew Wilcox EXPORT_SYMBOL_GPL(xas_find);
1088b803b428SMatthew Wilcox 
1089b803b428SMatthew Wilcox /**
1090b803b428SMatthew Wilcox  * xas_find_marked() - Find the next marked entry in the XArray.
1091b803b428SMatthew Wilcox  * @xas: XArray operation state.
1092b803b428SMatthew Wilcox  * @max: Highest index to return.
1093b803b428SMatthew Wilcox  * @mark: Mark number to search for.
1094b803b428SMatthew Wilcox  *
1095b803b428SMatthew Wilcox  * If the @xas has not yet been walked to an entry, return the marked entry
1096b803b428SMatthew Wilcox  * which has an index >= xas.xa_index.  If it has been walked, the entry
1097b803b428SMatthew Wilcox  * currently being pointed at has been processed, and so we return the
1098b803b428SMatthew Wilcox  * first marked entry with an index > xas.xa_index.
1099b803b428SMatthew Wilcox  *
1100b803b428SMatthew Wilcox  * If no marked entry is found and the array is smaller than @max, @xas is
1101b803b428SMatthew Wilcox  * set to the bounds state and xas->xa_index is set to the smallest index
1102b803b428SMatthew Wilcox  * not yet in the array.  This allows @xas to be immediately passed to
1103b803b428SMatthew Wilcox  * xas_store().
1104b803b428SMatthew Wilcox  *
1105b803b428SMatthew Wilcox  * If no entry is found before @max is reached, @xas is set to the restart
1106b803b428SMatthew Wilcox  * state.
1107b803b428SMatthew Wilcox  *
1108b803b428SMatthew Wilcox  * Return: The entry, if found, otherwise %NULL.
1109b803b428SMatthew Wilcox  */
1110b803b428SMatthew Wilcox void *xas_find_marked(struct xa_state *xas, unsigned long max, xa_mark_t mark)
1111b803b428SMatthew Wilcox {
1112b803b428SMatthew Wilcox 	bool advance = true;
1113b803b428SMatthew Wilcox 	unsigned int offset;
1114b803b428SMatthew Wilcox 	void *entry;
1115b803b428SMatthew Wilcox 
1116b803b428SMatthew Wilcox 	if (xas_error(xas))
1117b803b428SMatthew Wilcox 		return NULL;
1118b803b428SMatthew Wilcox 
1119b803b428SMatthew Wilcox 	if (!xas->xa_node) {
1120b803b428SMatthew Wilcox 		xas->xa_index = 1;
1121b803b428SMatthew Wilcox 		goto out;
1122b803b428SMatthew Wilcox 	} else if (xas_top(xas->xa_node)) {
1123b803b428SMatthew Wilcox 		advance = false;
1124b803b428SMatthew Wilcox 		entry = xa_head(xas->xa);
1125b803b428SMatthew Wilcox 		xas->xa_node = NULL;
1126b803b428SMatthew Wilcox 		if (xas->xa_index > max_index(entry))
1127b803b428SMatthew Wilcox 			goto bounds;
1128b803b428SMatthew Wilcox 		if (!xa_is_node(entry)) {
1129b803b428SMatthew Wilcox 			if (xa_marked(xas->xa, mark))
1130b803b428SMatthew Wilcox 				return entry;
1131b803b428SMatthew Wilcox 			xas->xa_index = 1;
1132b803b428SMatthew Wilcox 			goto out;
1133b803b428SMatthew Wilcox 		}
1134b803b428SMatthew Wilcox 		xas->xa_node = xa_to_node(entry);
1135b803b428SMatthew Wilcox 		xas->xa_offset = xas->xa_index >> xas->xa_node->shift;
1136b803b428SMatthew Wilcox 	}
1137b803b428SMatthew Wilcox 
1138b803b428SMatthew Wilcox 	while (xas->xa_index <= max) {
1139b803b428SMatthew Wilcox 		if (unlikely(xas->xa_offset == XA_CHUNK_SIZE)) {
1140b803b428SMatthew Wilcox 			xas->xa_offset = xas->xa_node->offset + 1;
1141b803b428SMatthew Wilcox 			xas->xa_node = xa_parent(xas->xa, xas->xa_node);
1142b803b428SMatthew Wilcox 			if (!xas->xa_node)
1143b803b428SMatthew Wilcox 				break;
1144b803b428SMatthew Wilcox 			advance = false;
1145b803b428SMatthew Wilcox 			continue;
1146b803b428SMatthew Wilcox 		}
1147b803b428SMatthew Wilcox 
1148b803b428SMatthew Wilcox 		if (!advance) {
1149b803b428SMatthew Wilcox 			entry = xa_entry(xas->xa, xas->xa_node, xas->xa_offset);
1150b803b428SMatthew Wilcox 			if (xa_is_sibling(entry)) {
1151b803b428SMatthew Wilcox 				xas->xa_offset = xa_to_sibling(entry);
1152b803b428SMatthew Wilcox 				xas_move_index(xas, xas->xa_offset);
1153b803b428SMatthew Wilcox 			}
1154b803b428SMatthew Wilcox 		}
1155b803b428SMatthew Wilcox 
1156b803b428SMatthew Wilcox 		offset = xas_find_chunk(xas, advance, mark);
1157b803b428SMatthew Wilcox 		if (offset > xas->xa_offset) {
1158b803b428SMatthew Wilcox 			advance = false;
1159b803b428SMatthew Wilcox 			xas_move_index(xas, offset);
1160b803b428SMatthew Wilcox 			/* Mind the wrap */
1161b803b428SMatthew Wilcox 			if ((xas->xa_index - 1) >= max)
1162b803b428SMatthew Wilcox 				goto max;
1163b803b428SMatthew Wilcox 			xas->xa_offset = offset;
1164b803b428SMatthew Wilcox 			if (offset == XA_CHUNK_SIZE)
1165b803b428SMatthew Wilcox 				continue;
1166b803b428SMatthew Wilcox 		}
1167b803b428SMatthew Wilcox 
1168b803b428SMatthew Wilcox 		entry = xa_entry(xas->xa, xas->xa_node, xas->xa_offset);
1169b803b428SMatthew Wilcox 		if (!xa_is_node(entry))
1170b803b428SMatthew Wilcox 			return entry;
1171b803b428SMatthew Wilcox 		xas->xa_node = xa_to_node(entry);
1172b803b428SMatthew Wilcox 		xas_set_offset(xas);
1173b803b428SMatthew Wilcox 	}
1174b803b428SMatthew Wilcox 
1175b803b428SMatthew Wilcox out:
1176b803b428SMatthew Wilcox 	if (!max)
1177b803b428SMatthew Wilcox 		goto max;
1178b803b428SMatthew Wilcox bounds:
1179b803b428SMatthew Wilcox 	xas->xa_node = XAS_BOUNDS;
1180b803b428SMatthew Wilcox 	return NULL;
1181b803b428SMatthew Wilcox max:
1182b803b428SMatthew Wilcox 	xas->xa_node = XAS_RESTART;
1183b803b428SMatthew Wilcox 	return NULL;
1184b803b428SMatthew Wilcox }
1185b803b428SMatthew Wilcox EXPORT_SYMBOL_GPL(xas_find_marked);
1186b803b428SMatthew Wilcox 
1187b803b428SMatthew Wilcox /**
11884e99d4e9SMatthew Wilcox  * xas_find_conflict() - Find the next present entry in a range.
11894e99d4e9SMatthew Wilcox  * @xas: XArray operation state.
11904e99d4e9SMatthew Wilcox  *
11914e99d4e9SMatthew Wilcox  * The @xas describes both a range and a position within that range.
11924e99d4e9SMatthew Wilcox  *
11934e99d4e9SMatthew Wilcox  * Context: Any context.  Expects xa_lock to be held.
11944e99d4e9SMatthew Wilcox  * Return: The next entry in the range covered by @xas or %NULL.
11954e99d4e9SMatthew Wilcox  */
11964e99d4e9SMatthew Wilcox void *xas_find_conflict(struct xa_state *xas)
11974e99d4e9SMatthew Wilcox {
11984e99d4e9SMatthew Wilcox 	void *curr;
11994e99d4e9SMatthew Wilcox 
12004e99d4e9SMatthew Wilcox 	if (xas_error(xas))
12014e99d4e9SMatthew Wilcox 		return NULL;
12024e99d4e9SMatthew Wilcox 
12034e99d4e9SMatthew Wilcox 	if (!xas->xa_node)
12044e99d4e9SMatthew Wilcox 		return NULL;
12054e99d4e9SMatthew Wilcox 
12064e99d4e9SMatthew Wilcox 	if (xas_top(xas->xa_node)) {
12074e99d4e9SMatthew Wilcox 		curr = xas_start(xas);
12084e99d4e9SMatthew Wilcox 		if (!curr)
12094e99d4e9SMatthew Wilcox 			return NULL;
12104e99d4e9SMatthew Wilcox 		while (xa_is_node(curr)) {
12114e99d4e9SMatthew Wilcox 			struct xa_node *node = xa_to_node(curr);
12124e99d4e9SMatthew Wilcox 			curr = xas_descend(xas, node);
12134e99d4e9SMatthew Wilcox 		}
12144e99d4e9SMatthew Wilcox 		if (curr)
12154e99d4e9SMatthew Wilcox 			return curr;
12164e99d4e9SMatthew Wilcox 	}
12174e99d4e9SMatthew Wilcox 
12184e99d4e9SMatthew Wilcox 	if (xas->xa_node->shift > xas->xa_shift)
12194e99d4e9SMatthew Wilcox 		return NULL;
12204e99d4e9SMatthew Wilcox 
12214e99d4e9SMatthew Wilcox 	for (;;) {
12224e99d4e9SMatthew Wilcox 		if (xas->xa_node->shift == xas->xa_shift) {
12234e99d4e9SMatthew Wilcox 			if ((xas->xa_offset & xas->xa_sibs) == xas->xa_sibs)
12244e99d4e9SMatthew Wilcox 				break;
12254e99d4e9SMatthew Wilcox 		} else if (xas->xa_offset == XA_CHUNK_MASK) {
12264e99d4e9SMatthew Wilcox 			xas->xa_offset = xas->xa_node->offset;
12274e99d4e9SMatthew Wilcox 			xas->xa_node = xa_parent_locked(xas->xa, xas->xa_node);
12284e99d4e9SMatthew Wilcox 			if (!xas->xa_node)
12294e99d4e9SMatthew Wilcox 				break;
12304e99d4e9SMatthew Wilcox 			continue;
12314e99d4e9SMatthew Wilcox 		}
12324e99d4e9SMatthew Wilcox 		curr = xa_entry_locked(xas->xa, xas->xa_node, ++xas->xa_offset);
12334e99d4e9SMatthew Wilcox 		if (xa_is_sibling(curr))
12344e99d4e9SMatthew Wilcox 			continue;
12354e99d4e9SMatthew Wilcox 		while (xa_is_node(curr)) {
12364e99d4e9SMatthew Wilcox 			xas->xa_node = xa_to_node(curr);
12374e99d4e9SMatthew Wilcox 			xas->xa_offset = 0;
12384e99d4e9SMatthew Wilcox 			curr = xa_entry_locked(xas->xa, xas->xa_node, 0);
12394e99d4e9SMatthew Wilcox 		}
12404e99d4e9SMatthew Wilcox 		if (curr)
12414e99d4e9SMatthew Wilcox 			return curr;
12424e99d4e9SMatthew Wilcox 	}
12434e99d4e9SMatthew Wilcox 	xas->xa_offset -= xas->xa_sibs;
12444e99d4e9SMatthew Wilcox 	return NULL;
12454e99d4e9SMatthew Wilcox }
12464e99d4e9SMatthew Wilcox EXPORT_SYMBOL_GPL(xas_find_conflict);
12474e99d4e9SMatthew Wilcox 
12484e99d4e9SMatthew Wilcox /**
1249f8d5d0ccSMatthew Wilcox  * xa_init_flags() - Initialise an empty XArray with flags.
1250f8d5d0ccSMatthew Wilcox  * @xa: XArray.
1251f8d5d0ccSMatthew Wilcox  * @flags: XA_FLAG values.
1252f8d5d0ccSMatthew Wilcox  *
1253f8d5d0ccSMatthew Wilcox  * If you need to initialise an XArray with special flags (eg you need
1254f8d5d0ccSMatthew Wilcox  * to take the lock from interrupt context), use this function instead
1255f8d5d0ccSMatthew Wilcox  * of xa_init().
1256f8d5d0ccSMatthew Wilcox  *
1257f8d5d0ccSMatthew Wilcox  * Context: Any context.
1258f8d5d0ccSMatthew Wilcox  */
1259f8d5d0ccSMatthew Wilcox void xa_init_flags(struct xarray *xa, gfp_t flags)
1260f8d5d0ccSMatthew Wilcox {
126158d6ea30SMatthew Wilcox 	unsigned int lock_type;
126258d6ea30SMatthew Wilcox 	static struct lock_class_key xa_lock_irq;
126358d6ea30SMatthew Wilcox 	static struct lock_class_key xa_lock_bh;
126458d6ea30SMatthew Wilcox 
1265f8d5d0ccSMatthew Wilcox 	spin_lock_init(&xa->xa_lock);
1266f8d5d0ccSMatthew Wilcox 	xa->xa_flags = flags;
1267f8d5d0ccSMatthew Wilcox 	xa->xa_head = NULL;
126858d6ea30SMatthew Wilcox 
126958d6ea30SMatthew Wilcox 	lock_type = xa_lock_type(xa);
127058d6ea30SMatthew Wilcox 	if (lock_type == XA_LOCK_IRQ)
127158d6ea30SMatthew Wilcox 		lockdep_set_class(&xa->xa_lock, &xa_lock_irq);
127258d6ea30SMatthew Wilcox 	else if (lock_type == XA_LOCK_BH)
127358d6ea30SMatthew Wilcox 		lockdep_set_class(&xa->xa_lock, &xa_lock_bh);
1274f8d5d0ccSMatthew Wilcox }
1275f8d5d0ccSMatthew Wilcox EXPORT_SYMBOL(xa_init_flags);
1276ad3d6c72SMatthew Wilcox 
1277ad3d6c72SMatthew Wilcox /**
1278ad3d6c72SMatthew Wilcox  * xa_load() - Load an entry from an XArray.
1279ad3d6c72SMatthew Wilcox  * @xa: XArray.
1280ad3d6c72SMatthew Wilcox  * @index: index into array.
1281ad3d6c72SMatthew Wilcox  *
1282ad3d6c72SMatthew Wilcox  * Context: Any context.  Takes and releases the RCU lock.
1283ad3d6c72SMatthew Wilcox  * Return: The entry at @index in @xa.
1284ad3d6c72SMatthew Wilcox  */
1285ad3d6c72SMatthew Wilcox void *xa_load(struct xarray *xa, unsigned long index)
1286ad3d6c72SMatthew Wilcox {
1287ad3d6c72SMatthew Wilcox 	XA_STATE(xas, xa, index);
1288ad3d6c72SMatthew Wilcox 	void *entry;
1289ad3d6c72SMatthew Wilcox 
1290ad3d6c72SMatthew Wilcox 	rcu_read_lock();
1291ad3d6c72SMatthew Wilcox 	do {
1292ad3d6c72SMatthew Wilcox 		entry = xas_load(&xas);
12939f14d4f1SMatthew Wilcox 		if (xa_is_zero(entry))
12949f14d4f1SMatthew Wilcox 			entry = NULL;
1295ad3d6c72SMatthew Wilcox 	} while (xas_retry(&xas, entry));
1296ad3d6c72SMatthew Wilcox 	rcu_read_unlock();
1297ad3d6c72SMatthew Wilcox 
1298ad3d6c72SMatthew Wilcox 	return entry;
1299ad3d6c72SMatthew Wilcox }
1300ad3d6c72SMatthew Wilcox EXPORT_SYMBOL(xa_load);
1301ad3d6c72SMatthew Wilcox 
130258d6ea30SMatthew Wilcox static void *xas_result(struct xa_state *xas, void *curr)
130358d6ea30SMatthew Wilcox {
13049f14d4f1SMatthew Wilcox 	if (xa_is_zero(curr))
13059f14d4f1SMatthew Wilcox 		return NULL;
130658d6ea30SMatthew Wilcox 	XA_NODE_BUG_ON(xas->xa_node, xa_is_internal(curr));
130758d6ea30SMatthew Wilcox 	if (xas_error(xas))
130858d6ea30SMatthew Wilcox 		curr = xas->xa_node;
130958d6ea30SMatthew Wilcox 	return curr;
131058d6ea30SMatthew Wilcox }
131158d6ea30SMatthew Wilcox 
131258d6ea30SMatthew Wilcox /**
131358d6ea30SMatthew Wilcox  * __xa_erase() - Erase this entry from the XArray while locked.
131458d6ea30SMatthew Wilcox  * @xa: XArray.
131558d6ea30SMatthew Wilcox  * @index: Index into array.
131658d6ea30SMatthew Wilcox  *
131758d6ea30SMatthew Wilcox  * If the entry at this index is a multi-index entry then all indices will
131858d6ea30SMatthew Wilcox  * be erased, and the entry will no longer be a multi-index entry.
131958d6ea30SMatthew Wilcox  * This function expects the xa_lock to be held on entry.
132058d6ea30SMatthew Wilcox  *
132158d6ea30SMatthew Wilcox  * Context: Any context.  Expects xa_lock to be held on entry.  May
132258d6ea30SMatthew Wilcox  * release and reacquire xa_lock if @gfp flags permit.
132358d6ea30SMatthew Wilcox  * Return: The old entry at this index.
132458d6ea30SMatthew Wilcox  */
132558d6ea30SMatthew Wilcox void *__xa_erase(struct xarray *xa, unsigned long index)
132658d6ea30SMatthew Wilcox {
132758d6ea30SMatthew Wilcox 	XA_STATE(xas, xa, index);
132858d6ea30SMatthew Wilcox 	return xas_result(&xas, xas_store(&xas, NULL));
132958d6ea30SMatthew Wilcox }
133058d6ea30SMatthew Wilcox EXPORT_SYMBOL_GPL(__xa_erase);
133158d6ea30SMatthew Wilcox 
133258d6ea30SMatthew Wilcox /**
133358d6ea30SMatthew Wilcox  * xa_store() - Store this entry in the XArray.
133458d6ea30SMatthew Wilcox  * @xa: XArray.
133558d6ea30SMatthew Wilcox  * @index: Index into array.
133658d6ea30SMatthew Wilcox  * @entry: New entry.
133758d6ea30SMatthew Wilcox  * @gfp: Memory allocation flags.
133858d6ea30SMatthew Wilcox  *
133958d6ea30SMatthew Wilcox  * After this function returns, loads from this index will return @entry.
134058d6ea30SMatthew Wilcox  * Storing into an existing multislot entry updates the entry of every index.
134158d6ea30SMatthew Wilcox  * The marks associated with @index are unaffected unless @entry is %NULL.
134258d6ea30SMatthew Wilcox  *
134358d6ea30SMatthew Wilcox  * Context: Process context.  Takes and releases the xa_lock.  May sleep
134458d6ea30SMatthew Wilcox  * if the @gfp flags permit.
134558d6ea30SMatthew Wilcox  * Return: The old entry at this index on success, xa_err(-EINVAL) if @entry
134658d6ea30SMatthew Wilcox  * cannot be stored in an XArray, or xa_err(-ENOMEM) if memory allocation
134758d6ea30SMatthew Wilcox  * failed.
134858d6ea30SMatthew Wilcox  */
134958d6ea30SMatthew Wilcox void *xa_store(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp)
135058d6ea30SMatthew Wilcox {
135158d6ea30SMatthew Wilcox 	XA_STATE(xas, xa, index);
135258d6ea30SMatthew Wilcox 	void *curr;
135358d6ea30SMatthew Wilcox 
135458d6ea30SMatthew Wilcox 	if (WARN_ON_ONCE(xa_is_internal(entry)))
135558d6ea30SMatthew Wilcox 		return XA_ERROR(-EINVAL);
135658d6ea30SMatthew Wilcox 
135758d6ea30SMatthew Wilcox 	do {
135858d6ea30SMatthew Wilcox 		xas_lock(&xas);
135958d6ea30SMatthew Wilcox 		curr = xas_store(&xas, entry);
1360*371c752dSMatthew Wilcox 		if (xa_track_free(xa) && entry)
1361*371c752dSMatthew Wilcox 			xas_clear_mark(&xas, XA_FREE_MARK);
136258d6ea30SMatthew Wilcox 		xas_unlock(&xas);
136358d6ea30SMatthew Wilcox 	} while (xas_nomem(&xas, gfp));
136458d6ea30SMatthew Wilcox 
136558d6ea30SMatthew Wilcox 	return xas_result(&xas, curr);
136658d6ea30SMatthew Wilcox }
136758d6ea30SMatthew Wilcox EXPORT_SYMBOL(xa_store);
136858d6ea30SMatthew Wilcox 
136958d6ea30SMatthew Wilcox /**
137058d6ea30SMatthew Wilcox  * __xa_store() - Store this entry in the XArray.
137158d6ea30SMatthew Wilcox  * @xa: XArray.
137258d6ea30SMatthew Wilcox  * @index: Index into array.
137358d6ea30SMatthew Wilcox  * @entry: New entry.
137458d6ea30SMatthew Wilcox  * @gfp: Memory allocation flags.
137558d6ea30SMatthew Wilcox  *
137658d6ea30SMatthew Wilcox  * You must already be holding the xa_lock when calling this function.
137758d6ea30SMatthew Wilcox  * It will drop the lock if needed to allocate memory, and then reacquire
137858d6ea30SMatthew Wilcox  * it afterwards.
137958d6ea30SMatthew Wilcox  *
138058d6ea30SMatthew Wilcox  * Context: Any context.  Expects xa_lock to be held on entry.  May
138158d6ea30SMatthew Wilcox  * release and reacquire xa_lock if @gfp flags permit.
138258d6ea30SMatthew Wilcox  * Return: The old entry at this index or xa_err() if an error happened.
138358d6ea30SMatthew Wilcox  */
138458d6ea30SMatthew Wilcox void *__xa_store(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp)
138558d6ea30SMatthew Wilcox {
138658d6ea30SMatthew Wilcox 	XA_STATE(xas, xa, index);
138758d6ea30SMatthew Wilcox 	void *curr;
138858d6ea30SMatthew Wilcox 
138958d6ea30SMatthew Wilcox 	if (WARN_ON_ONCE(xa_is_internal(entry)))
139058d6ea30SMatthew Wilcox 		return XA_ERROR(-EINVAL);
139158d6ea30SMatthew Wilcox 
139258d6ea30SMatthew Wilcox 	do {
139358d6ea30SMatthew Wilcox 		curr = xas_store(&xas, entry);
1394*371c752dSMatthew Wilcox 		if (xa_track_free(xa) && entry)
1395*371c752dSMatthew Wilcox 			xas_clear_mark(&xas, XA_FREE_MARK);
139658d6ea30SMatthew Wilcox 	} while (__xas_nomem(&xas, gfp));
139758d6ea30SMatthew Wilcox 
139858d6ea30SMatthew Wilcox 	return xas_result(&xas, curr);
139958d6ea30SMatthew Wilcox }
140058d6ea30SMatthew Wilcox EXPORT_SYMBOL(__xa_store);
140158d6ea30SMatthew Wilcox 
14029b89a035SMatthew Wilcox /**
140341aec91fSMatthew Wilcox  * xa_cmpxchg() - Conditionally replace an entry in the XArray.
140441aec91fSMatthew Wilcox  * @xa: XArray.
140541aec91fSMatthew Wilcox  * @index: Index into array.
140641aec91fSMatthew Wilcox  * @old: Old value to test against.
140741aec91fSMatthew Wilcox  * @entry: New value to place in array.
140841aec91fSMatthew Wilcox  * @gfp: Memory allocation flags.
140941aec91fSMatthew Wilcox  *
141041aec91fSMatthew Wilcox  * If the entry at @index is the same as @old, replace it with @entry.
141141aec91fSMatthew Wilcox  * If the return value is equal to @old, then the exchange was successful.
141241aec91fSMatthew Wilcox  *
141341aec91fSMatthew Wilcox  * Context: Process context.  Takes and releases the xa_lock.  May sleep
141441aec91fSMatthew Wilcox  * if the @gfp flags permit.
141541aec91fSMatthew Wilcox  * Return: The old value at this index or xa_err() if an error happened.
141641aec91fSMatthew Wilcox  */
141741aec91fSMatthew Wilcox void *xa_cmpxchg(struct xarray *xa, unsigned long index,
141841aec91fSMatthew Wilcox 			void *old, void *entry, gfp_t gfp)
141941aec91fSMatthew Wilcox {
142041aec91fSMatthew Wilcox 	XA_STATE(xas, xa, index);
142141aec91fSMatthew Wilcox 	void *curr;
142241aec91fSMatthew Wilcox 
142341aec91fSMatthew Wilcox 	if (WARN_ON_ONCE(xa_is_internal(entry)))
142441aec91fSMatthew Wilcox 		return XA_ERROR(-EINVAL);
142541aec91fSMatthew Wilcox 
142641aec91fSMatthew Wilcox 	do {
142741aec91fSMatthew Wilcox 		xas_lock(&xas);
142841aec91fSMatthew Wilcox 		curr = xas_load(&xas);
14299f14d4f1SMatthew Wilcox 		if (curr == XA_ZERO_ENTRY)
14309f14d4f1SMatthew Wilcox 			curr = NULL;
1431*371c752dSMatthew Wilcox 		if (curr == old) {
143241aec91fSMatthew Wilcox 			xas_store(&xas, entry);
1433*371c752dSMatthew Wilcox 			if (xa_track_free(xa) && entry)
1434*371c752dSMatthew Wilcox 				xas_clear_mark(&xas, XA_FREE_MARK);
1435*371c752dSMatthew Wilcox 		}
143641aec91fSMatthew Wilcox 		xas_unlock(&xas);
143741aec91fSMatthew Wilcox 	} while (xas_nomem(&xas, gfp));
143841aec91fSMatthew Wilcox 
143941aec91fSMatthew Wilcox 	return xas_result(&xas, curr);
144041aec91fSMatthew Wilcox }
144141aec91fSMatthew Wilcox EXPORT_SYMBOL(xa_cmpxchg);
144241aec91fSMatthew Wilcox 
144341aec91fSMatthew Wilcox /**
144441aec91fSMatthew Wilcox  * __xa_cmpxchg() - Store this entry in the XArray.
144541aec91fSMatthew Wilcox  * @xa: XArray.
144641aec91fSMatthew Wilcox  * @index: Index into array.
144741aec91fSMatthew Wilcox  * @old: Old value to test against.
144841aec91fSMatthew Wilcox  * @entry: New entry.
144941aec91fSMatthew Wilcox  * @gfp: Memory allocation flags.
145041aec91fSMatthew Wilcox  *
145141aec91fSMatthew Wilcox  * You must already be holding the xa_lock when calling this function.
145241aec91fSMatthew Wilcox  * It will drop the lock if needed to allocate memory, and then reacquire
145341aec91fSMatthew Wilcox  * it afterwards.
145441aec91fSMatthew Wilcox  *
145541aec91fSMatthew Wilcox  * Context: Any context.  Expects xa_lock to be held on entry.  May
145641aec91fSMatthew Wilcox  * release and reacquire xa_lock if @gfp flags permit.
145741aec91fSMatthew Wilcox  * Return: The old entry at this index or xa_err() if an error happened.
145841aec91fSMatthew Wilcox  */
145941aec91fSMatthew Wilcox void *__xa_cmpxchg(struct xarray *xa, unsigned long index,
146041aec91fSMatthew Wilcox 			void *old, void *entry, gfp_t gfp)
146141aec91fSMatthew Wilcox {
146241aec91fSMatthew Wilcox 	XA_STATE(xas, xa, index);
146341aec91fSMatthew Wilcox 	void *curr;
146441aec91fSMatthew Wilcox 
146541aec91fSMatthew Wilcox 	if (WARN_ON_ONCE(xa_is_internal(entry)))
146641aec91fSMatthew Wilcox 		return XA_ERROR(-EINVAL);
146741aec91fSMatthew Wilcox 
146841aec91fSMatthew Wilcox 	do {
146941aec91fSMatthew Wilcox 		curr = xas_load(&xas);
14709f14d4f1SMatthew Wilcox 		if (curr == XA_ZERO_ENTRY)
14719f14d4f1SMatthew Wilcox 			curr = NULL;
1472*371c752dSMatthew Wilcox 		if (curr == old) {
147341aec91fSMatthew Wilcox 			xas_store(&xas, entry);
1474*371c752dSMatthew Wilcox 			if (xa_track_free(xa) && entry)
1475*371c752dSMatthew Wilcox 				xas_clear_mark(&xas, XA_FREE_MARK);
1476*371c752dSMatthew Wilcox 		}
147741aec91fSMatthew Wilcox 	} while (__xas_nomem(&xas, gfp));
147841aec91fSMatthew Wilcox 
147941aec91fSMatthew Wilcox 	return xas_result(&xas, curr);
148041aec91fSMatthew Wilcox }
148141aec91fSMatthew Wilcox EXPORT_SYMBOL(__xa_cmpxchg);
148241aec91fSMatthew Wilcox 
148341aec91fSMatthew Wilcox /**
14849f14d4f1SMatthew Wilcox  * xa_reserve() - Reserve this index in the XArray.
14859f14d4f1SMatthew Wilcox  * @xa: XArray.
14869f14d4f1SMatthew Wilcox  * @index: Index into array.
14879f14d4f1SMatthew Wilcox  * @gfp: Memory allocation flags.
14889f14d4f1SMatthew Wilcox  *
14899f14d4f1SMatthew Wilcox  * Ensures there is somewhere to store an entry at @index in the array.
14909f14d4f1SMatthew Wilcox  * If there is already something stored at @index, this function does
14919f14d4f1SMatthew Wilcox  * nothing.  If there was nothing there, the entry is marked as reserved.
14929f14d4f1SMatthew Wilcox  * Loads from @index will continue to see a %NULL pointer until a
14939f14d4f1SMatthew Wilcox  * subsequent store to @index.
14949f14d4f1SMatthew Wilcox  *
14959f14d4f1SMatthew Wilcox  * If you do not use the entry that you have reserved, call xa_release()
14969f14d4f1SMatthew Wilcox  * or xa_erase() to free any unnecessary memory.
14979f14d4f1SMatthew Wilcox  *
14989f14d4f1SMatthew Wilcox  * Context: Process context.  Takes and releases the xa_lock, IRQ or BH safe
14999f14d4f1SMatthew Wilcox  * if specified in XArray flags.  May sleep if the @gfp flags permit.
15009f14d4f1SMatthew Wilcox  * Return: 0 if the reservation succeeded or -ENOMEM if it failed.
15019f14d4f1SMatthew Wilcox  */
15029f14d4f1SMatthew Wilcox int xa_reserve(struct xarray *xa, unsigned long index, gfp_t gfp)
15039f14d4f1SMatthew Wilcox {
15049f14d4f1SMatthew Wilcox 	XA_STATE(xas, xa, index);
15059f14d4f1SMatthew Wilcox 	unsigned int lock_type = xa_lock_type(xa);
15069f14d4f1SMatthew Wilcox 	void *curr;
15079f14d4f1SMatthew Wilcox 
15089f14d4f1SMatthew Wilcox 	do {
15099f14d4f1SMatthew Wilcox 		xas_lock_type(&xas, lock_type);
15109f14d4f1SMatthew Wilcox 		curr = xas_load(&xas);
15119f14d4f1SMatthew Wilcox 		if (!curr)
15129f14d4f1SMatthew Wilcox 			xas_store(&xas, XA_ZERO_ENTRY);
15139f14d4f1SMatthew Wilcox 		xas_unlock_type(&xas, lock_type);
15149f14d4f1SMatthew Wilcox 	} while (xas_nomem(&xas, gfp));
15159f14d4f1SMatthew Wilcox 
15169f14d4f1SMatthew Wilcox 	return xas_error(&xas);
15179f14d4f1SMatthew Wilcox }
15189f14d4f1SMatthew Wilcox EXPORT_SYMBOL(xa_reserve);
15199f14d4f1SMatthew Wilcox 
15209f14d4f1SMatthew Wilcox /**
1521*371c752dSMatthew Wilcox  * __xa_alloc() - Find somewhere to store this entry in the XArray.
1522*371c752dSMatthew Wilcox  * @xa: XArray.
1523*371c752dSMatthew Wilcox  * @id: Pointer to ID.
1524*371c752dSMatthew Wilcox  * @max: Maximum ID to allocate (inclusive).
1525*371c752dSMatthew Wilcox  * @entry: New entry.
1526*371c752dSMatthew Wilcox  * @gfp: Memory allocation flags.
1527*371c752dSMatthew Wilcox  *
1528*371c752dSMatthew Wilcox  * Allocates an unused ID in the range specified by @id and @max.
1529*371c752dSMatthew Wilcox  * Updates the @id pointer with the index, then stores the entry at that
1530*371c752dSMatthew Wilcox  * index.  A concurrent lookup will not see an uninitialised @id.
1531*371c752dSMatthew Wilcox  *
1532*371c752dSMatthew Wilcox  * Context: Any context.  Expects xa_lock to be held on entry.  May
1533*371c752dSMatthew Wilcox  * release and reacquire xa_lock if @gfp flags permit.
1534*371c752dSMatthew Wilcox  * Return: 0 on success, -ENOMEM if memory allocation fails or -ENOSPC if
1535*371c752dSMatthew Wilcox  * there is no more space in the XArray.
1536*371c752dSMatthew Wilcox  */
1537*371c752dSMatthew Wilcox int __xa_alloc(struct xarray *xa, u32 *id, u32 max, void *entry, gfp_t gfp)
1538*371c752dSMatthew Wilcox {
1539*371c752dSMatthew Wilcox 	XA_STATE(xas, xa, 0);
1540*371c752dSMatthew Wilcox 	int err;
1541*371c752dSMatthew Wilcox 
1542*371c752dSMatthew Wilcox 	if (WARN_ON_ONCE(xa_is_internal(entry)))
1543*371c752dSMatthew Wilcox 		return -EINVAL;
1544*371c752dSMatthew Wilcox 	if (WARN_ON_ONCE(!xa_track_free(xa)))
1545*371c752dSMatthew Wilcox 		return -EINVAL;
1546*371c752dSMatthew Wilcox 
1547*371c752dSMatthew Wilcox 	if (!entry)
1548*371c752dSMatthew Wilcox 		entry = XA_ZERO_ENTRY;
1549*371c752dSMatthew Wilcox 
1550*371c752dSMatthew Wilcox 	do {
1551*371c752dSMatthew Wilcox 		xas.xa_index = *id;
1552*371c752dSMatthew Wilcox 		xas_find_marked(&xas, max, XA_FREE_MARK);
1553*371c752dSMatthew Wilcox 		if (xas.xa_node == XAS_RESTART)
1554*371c752dSMatthew Wilcox 			xas_set_err(&xas, -ENOSPC);
1555*371c752dSMatthew Wilcox 		xas_store(&xas, entry);
1556*371c752dSMatthew Wilcox 		xas_clear_mark(&xas, XA_FREE_MARK);
1557*371c752dSMatthew Wilcox 	} while (__xas_nomem(&xas, gfp));
1558*371c752dSMatthew Wilcox 
1559*371c752dSMatthew Wilcox 	err = xas_error(&xas);
1560*371c752dSMatthew Wilcox 	if (!err)
1561*371c752dSMatthew Wilcox 		*id = xas.xa_index;
1562*371c752dSMatthew Wilcox 	return err;
1563*371c752dSMatthew Wilcox }
1564*371c752dSMatthew Wilcox EXPORT_SYMBOL(__xa_alloc);
1565*371c752dSMatthew Wilcox 
1566*371c752dSMatthew Wilcox /**
15679b89a035SMatthew Wilcox  * __xa_set_mark() - Set this mark on this entry while locked.
15689b89a035SMatthew Wilcox  * @xa: XArray.
15699b89a035SMatthew Wilcox  * @index: Index of entry.
15709b89a035SMatthew Wilcox  * @mark: Mark number.
15719b89a035SMatthew Wilcox  *
15729b89a035SMatthew Wilcox  * Attempting to set a mark on a NULL entry does not succeed.
15739b89a035SMatthew Wilcox  *
15749b89a035SMatthew Wilcox  * Context: Any context.  Expects xa_lock to be held on entry.
15759b89a035SMatthew Wilcox  */
15769b89a035SMatthew Wilcox void __xa_set_mark(struct xarray *xa, unsigned long index, xa_mark_t mark)
15779b89a035SMatthew Wilcox {
15789b89a035SMatthew Wilcox 	XA_STATE(xas, xa, index);
15799b89a035SMatthew Wilcox 	void *entry = xas_load(&xas);
15809b89a035SMatthew Wilcox 
15819b89a035SMatthew Wilcox 	if (entry)
15829b89a035SMatthew Wilcox 		xas_set_mark(&xas, mark);
15839b89a035SMatthew Wilcox }
15849b89a035SMatthew Wilcox EXPORT_SYMBOL_GPL(__xa_set_mark);
15859b89a035SMatthew Wilcox 
15869b89a035SMatthew Wilcox /**
15879b89a035SMatthew Wilcox  * __xa_clear_mark() - Clear this mark on this entry while locked.
15889b89a035SMatthew Wilcox  * @xa: XArray.
15899b89a035SMatthew Wilcox  * @index: Index of entry.
15909b89a035SMatthew Wilcox  * @mark: Mark number.
15919b89a035SMatthew Wilcox  *
15929b89a035SMatthew Wilcox  * Context: Any context.  Expects xa_lock to be held on entry.
15939b89a035SMatthew Wilcox  */
15949b89a035SMatthew Wilcox void __xa_clear_mark(struct xarray *xa, unsigned long index, xa_mark_t mark)
15959b89a035SMatthew Wilcox {
15969b89a035SMatthew Wilcox 	XA_STATE(xas, xa, index);
15979b89a035SMatthew Wilcox 	void *entry = xas_load(&xas);
15989b89a035SMatthew Wilcox 
15999b89a035SMatthew Wilcox 	if (entry)
16009b89a035SMatthew Wilcox 		xas_clear_mark(&xas, mark);
16019b89a035SMatthew Wilcox }
16029b89a035SMatthew Wilcox EXPORT_SYMBOL_GPL(__xa_clear_mark);
16039b89a035SMatthew Wilcox 
16049b89a035SMatthew Wilcox /**
16059b89a035SMatthew Wilcox  * xa_get_mark() - Inquire whether this mark is set on this entry.
16069b89a035SMatthew Wilcox  * @xa: XArray.
16079b89a035SMatthew Wilcox  * @index: Index of entry.
16089b89a035SMatthew Wilcox  * @mark: Mark number.
16099b89a035SMatthew Wilcox  *
16109b89a035SMatthew Wilcox  * This function uses the RCU read lock, so the result may be out of date
16119b89a035SMatthew Wilcox  * by the time it returns.  If you need the result to be stable, use a lock.
16129b89a035SMatthew Wilcox  *
16139b89a035SMatthew Wilcox  * Context: Any context.  Takes and releases the RCU lock.
16149b89a035SMatthew Wilcox  * Return: True if the entry at @index has this mark set, false if it doesn't.
16159b89a035SMatthew Wilcox  */
16169b89a035SMatthew Wilcox bool xa_get_mark(struct xarray *xa, unsigned long index, xa_mark_t mark)
16179b89a035SMatthew Wilcox {
16189b89a035SMatthew Wilcox 	XA_STATE(xas, xa, index);
16199b89a035SMatthew Wilcox 	void *entry;
16209b89a035SMatthew Wilcox 
16219b89a035SMatthew Wilcox 	rcu_read_lock();
16229b89a035SMatthew Wilcox 	entry = xas_start(&xas);
16239b89a035SMatthew Wilcox 	while (xas_get_mark(&xas, mark)) {
16249b89a035SMatthew Wilcox 		if (!xa_is_node(entry))
16259b89a035SMatthew Wilcox 			goto found;
16269b89a035SMatthew Wilcox 		entry = xas_descend(&xas, xa_to_node(entry));
16279b89a035SMatthew Wilcox 	}
16289b89a035SMatthew Wilcox 	rcu_read_unlock();
16299b89a035SMatthew Wilcox 	return false;
16309b89a035SMatthew Wilcox  found:
16319b89a035SMatthew Wilcox 	rcu_read_unlock();
16329b89a035SMatthew Wilcox 	return true;
16339b89a035SMatthew Wilcox }
16349b89a035SMatthew Wilcox EXPORT_SYMBOL(xa_get_mark);
16359b89a035SMatthew Wilcox 
16369b89a035SMatthew Wilcox /**
16379b89a035SMatthew Wilcox  * xa_set_mark() - Set this mark on this entry.
16389b89a035SMatthew Wilcox  * @xa: XArray.
16399b89a035SMatthew Wilcox  * @index: Index of entry.
16409b89a035SMatthew Wilcox  * @mark: Mark number.
16419b89a035SMatthew Wilcox  *
16429b89a035SMatthew Wilcox  * Attempting to set a mark on a NULL entry does not succeed.
16439b89a035SMatthew Wilcox  *
16449b89a035SMatthew Wilcox  * Context: Process context.  Takes and releases the xa_lock.
16459b89a035SMatthew Wilcox  */
16469b89a035SMatthew Wilcox void xa_set_mark(struct xarray *xa, unsigned long index, xa_mark_t mark)
16479b89a035SMatthew Wilcox {
16489b89a035SMatthew Wilcox 	xa_lock(xa);
16499b89a035SMatthew Wilcox 	__xa_set_mark(xa, index, mark);
16509b89a035SMatthew Wilcox 	xa_unlock(xa);
16519b89a035SMatthew Wilcox }
16529b89a035SMatthew Wilcox EXPORT_SYMBOL(xa_set_mark);
16539b89a035SMatthew Wilcox 
16549b89a035SMatthew Wilcox /**
16559b89a035SMatthew Wilcox  * xa_clear_mark() - Clear this mark on this entry.
16569b89a035SMatthew Wilcox  * @xa: XArray.
16579b89a035SMatthew Wilcox  * @index: Index of entry.
16589b89a035SMatthew Wilcox  * @mark: Mark number.
16599b89a035SMatthew Wilcox  *
16609b89a035SMatthew Wilcox  * Clearing a mark always succeeds.
16619b89a035SMatthew Wilcox  *
16629b89a035SMatthew Wilcox  * Context: Process context.  Takes and releases the xa_lock.
16639b89a035SMatthew Wilcox  */
16649b89a035SMatthew Wilcox void xa_clear_mark(struct xarray *xa, unsigned long index, xa_mark_t mark)
16659b89a035SMatthew Wilcox {
16669b89a035SMatthew Wilcox 	xa_lock(xa);
16679b89a035SMatthew Wilcox 	__xa_clear_mark(xa, index, mark);
16689b89a035SMatthew Wilcox 	xa_unlock(xa);
16699b89a035SMatthew Wilcox }
16709b89a035SMatthew Wilcox EXPORT_SYMBOL(xa_clear_mark);
16719b89a035SMatthew Wilcox 
1672b803b428SMatthew Wilcox /**
1673b803b428SMatthew Wilcox  * xa_find() - Search the XArray for an entry.
1674b803b428SMatthew Wilcox  * @xa: XArray.
1675b803b428SMatthew Wilcox  * @indexp: Pointer to an index.
1676b803b428SMatthew Wilcox  * @max: Maximum index to search to.
1677b803b428SMatthew Wilcox  * @filter: Selection criterion.
1678b803b428SMatthew Wilcox  *
1679b803b428SMatthew Wilcox  * Finds the entry in @xa which matches the @filter, and has the lowest
1680b803b428SMatthew Wilcox  * index that is at least @indexp and no more than @max.
1681b803b428SMatthew Wilcox  * If an entry is found, @indexp is updated to be the index of the entry.
1682b803b428SMatthew Wilcox  * This function is protected by the RCU read lock, so it may not find
1683b803b428SMatthew Wilcox  * entries which are being simultaneously added.  It will not return an
1684b803b428SMatthew Wilcox  * %XA_RETRY_ENTRY; if you need to see retry entries, use xas_find().
1685b803b428SMatthew Wilcox  *
1686b803b428SMatthew Wilcox  * Context: Any context.  Takes and releases the RCU lock.
1687b803b428SMatthew Wilcox  * Return: The entry, if found, otherwise %NULL.
1688b803b428SMatthew Wilcox  */
1689b803b428SMatthew Wilcox void *xa_find(struct xarray *xa, unsigned long *indexp,
1690b803b428SMatthew Wilcox 			unsigned long max, xa_mark_t filter)
1691b803b428SMatthew Wilcox {
1692b803b428SMatthew Wilcox 	XA_STATE(xas, xa, *indexp);
1693b803b428SMatthew Wilcox 	void *entry;
1694b803b428SMatthew Wilcox 
1695b803b428SMatthew Wilcox 	rcu_read_lock();
1696b803b428SMatthew Wilcox 	do {
1697b803b428SMatthew Wilcox 		if ((__force unsigned int)filter < XA_MAX_MARKS)
1698b803b428SMatthew Wilcox 			entry = xas_find_marked(&xas, max, filter);
1699b803b428SMatthew Wilcox 		else
1700b803b428SMatthew Wilcox 			entry = xas_find(&xas, max);
1701b803b428SMatthew Wilcox 	} while (xas_retry(&xas, entry));
1702b803b428SMatthew Wilcox 	rcu_read_unlock();
1703b803b428SMatthew Wilcox 
1704b803b428SMatthew Wilcox 	if (entry)
1705b803b428SMatthew Wilcox 		*indexp = xas.xa_index;
1706b803b428SMatthew Wilcox 	return entry;
1707b803b428SMatthew Wilcox }
1708b803b428SMatthew Wilcox EXPORT_SYMBOL(xa_find);
1709b803b428SMatthew Wilcox 
1710b803b428SMatthew Wilcox /**
1711b803b428SMatthew Wilcox  * xa_find_after() - Search the XArray for a present entry.
1712b803b428SMatthew Wilcox  * @xa: XArray.
1713b803b428SMatthew Wilcox  * @indexp: Pointer to an index.
1714b803b428SMatthew Wilcox  * @max: Maximum index to search to.
1715b803b428SMatthew Wilcox  * @filter: Selection criterion.
1716b803b428SMatthew Wilcox  *
1717b803b428SMatthew Wilcox  * Finds the entry in @xa which matches the @filter and has the lowest
1718b803b428SMatthew Wilcox  * index that is above @indexp and no more than @max.
1719b803b428SMatthew Wilcox  * If an entry is found, @indexp is updated to be the index of the entry.
1720b803b428SMatthew Wilcox  * This function is protected by the RCU read lock, so it may miss entries
1721b803b428SMatthew Wilcox  * which are being simultaneously added.  It will not return an
1722b803b428SMatthew Wilcox  * %XA_RETRY_ENTRY; if you need to see retry entries, use xas_find().
1723b803b428SMatthew Wilcox  *
1724b803b428SMatthew Wilcox  * Context: Any context.  Takes and releases the RCU lock.
1725b803b428SMatthew Wilcox  * Return: The pointer, if found, otherwise %NULL.
1726b803b428SMatthew Wilcox  */
1727b803b428SMatthew Wilcox void *xa_find_after(struct xarray *xa, unsigned long *indexp,
1728b803b428SMatthew Wilcox 			unsigned long max, xa_mark_t filter)
1729b803b428SMatthew Wilcox {
1730b803b428SMatthew Wilcox 	XA_STATE(xas, xa, *indexp + 1);
1731b803b428SMatthew Wilcox 	void *entry;
1732b803b428SMatthew Wilcox 
1733b803b428SMatthew Wilcox 	rcu_read_lock();
1734b803b428SMatthew Wilcox 	for (;;) {
1735b803b428SMatthew Wilcox 		if ((__force unsigned int)filter < XA_MAX_MARKS)
1736b803b428SMatthew Wilcox 			entry = xas_find_marked(&xas, max, filter);
1737b803b428SMatthew Wilcox 		else
1738b803b428SMatthew Wilcox 			entry = xas_find(&xas, max);
1739b803b428SMatthew Wilcox 		if (xas.xa_shift) {
1740b803b428SMatthew Wilcox 			if (xas.xa_index & ((1UL << xas.xa_shift) - 1))
1741b803b428SMatthew Wilcox 				continue;
1742b803b428SMatthew Wilcox 		} else {
1743b803b428SMatthew Wilcox 			if (xas.xa_offset < (xas.xa_index & XA_CHUNK_MASK))
1744b803b428SMatthew Wilcox 				continue;
1745b803b428SMatthew Wilcox 		}
1746b803b428SMatthew Wilcox 		if (!xas_retry(&xas, entry))
1747b803b428SMatthew Wilcox 			break;
1748b803b428SMatthew Wilcox 	}
1749b803b428SMatthew Wilcox 	rcu_read_unlock();
1750b803b428SMatthew Wilcox 
1751b803b428SMatthew Wilcox 	if (entry)
1752b803b428SMatthew Wilcox 		*indexp = xas.xa_index;
1753b803b428SMatthew Wilcox 	return entry;
1754b803b428SMatthew Wilcox }
1755b803b428SMatthew Wilcox EXPORT_SYMBOL(xa_find_after);
1756b803b428SMatthew Wilcox 
175780a0a1a9SMatthew Wilcox static unsigned int xas_extract_present(struct xa_state *xas, void **dst,
175880a0a1a9SMatthew Wilcox 			unsigned long max, unsigned int n)
175980a0a1a9SMatthew Wilcox {
176080a0a1a9SMatthew Wilcox 	void *entry;
176180a0a1a9SMatthew Wilcox 	unsigned int i = 0;
176280a0a1a9SMatthew Wilcox 
176380a0a1a9SMatthew Wilcox 	rcu_read_lock();
176480a0a1a9SMatthew Wilcox 	xas_for_each(xas, entry, max) {
176580a0a1a9SMatthew Wilcox 		if (xas_retry(xas, entry))
176680a0a1a9SMatthew Wilcox 			continue;
176780a0a1a9SMatthew Wilcox 		dst[i++] = entry;
176880a0a1a9SMatthew Wilcox 		if (i == n)
176980a0a1a9SMatthew Wilcox 			break;
177080a0a1a9SMatthew Wilcox 	}
177180a0a1a9SMatthew Wilcox 	rcu_read_unlock();
177280a0a1a9SMatthew Wilcox 
177380a0a1a9SMatthew Wilcox 	return i;
177480a0a1a9SMatthew Wilcox }
177580a0a1a9SMatthew Wilcox 
177680a0a1a9SMatthew Wilcox static unsigned int xas_extract_marked(struct xa_state *xas, void **dst,
177780a0a1a9SMatthew Wilcox 			unsigned long max, unsigned int n, xa_mark_t mark)
177880a0a1a9SMatthew Wilcox {
177980a0a1a9SMatthew Wilcox 	void *entry;
178080a0a1a9SMatthew Wilcox 	unsigned int i = 0;
178180a0a1a9SMatthew Wilcox 
178280a0a1a9SMatthew Wilcox 	rcu_read_lock();
178380a0a1a9SMatthew Wilcox 	xas_for_each_marked(xas, entry, max, mark) {
178480a0a1a9SMatthew Wilcox 		if (xas_retry(xas, entry))
178580a0a1a9SMatthew Wilcox 			continue;
178680a0a1a9SMatthew Wilcox 		dst[i++] = entry;
178780a0a1a9SMatthew Wilcox 		if (i == n)
178880a0a1a9SMatthew Wilcox 			break;
178980a0a1a9SMatthew Wilcox 	}
179080a0a1a9SMatthew Wilcox 	rcu_read_unlock();
179180a0a1a9SMatthew Wilcox 
179280a0a1a9SMatthew Wilcox 	return i;
179380a0a1a9SMatthew Wilcox }
179480a0a1a9SMatthew Wilcox 
179580a0a1a9SMatthew Wilcox /**
179680a0a1a9SMatthew Wilcox  * xa_extract() - Copy selected entries from the XArray into a normal array.
179780a0a1a9SMatthew Wilcox  * @xa: The source XArray to copy from.
179880a0a1a9SMatthew Wilcox  * @dst: The buffer to copy entries into.
179980a0a1a9SMatthew Wilcox  * @start: The first index in the XArray eligible to be selected.
180080a0a1a9SMatthew Wilcox  * @max: The last index in the XArray eligible to be selected.
180180a0a1a9SMatthew Wilcox  * @n: The maximum number of entries to copy.
180280a0a1a9SMatthew Wilcox  * @filter: Selection criterion.
180380a0a1a9SMatthew Wilcox  *
180480a0a1a9SMatthew Wilcox  * Copies up to @n entries that match @filter from the XArray.  The
180580a0a1a9SMatthew Wilcox  * copied entries will have indices between @start and @max, inclusive.
180680a0a1a9SMatthew Wilcox  *
180780a0a1a9SMatthew Wilcox  * The @filter may be an XArray mark value, in which case entries which are
180880a0a1a9SMatthew Wilcox  * marked with that mark will be copied.  It may also be %XA_PRESENT, in
180980a0a1a9SMatthew Wilcox  * which case all entries which are not NULL will be copied.
181080a0a1a9SMatthew Wilcox  *
181180a0a1a9SMatthew Wilcox  * The entries returned may not represent a snapshot of the XArray at a
181280a0a1a9SMatthew Wilcox  * moment in time.  For example, if another thread stores to index 5, then
181380a0a1a9SMatthew Wilcox  * index 10, calling xa_extract() may return the old contents of index 5
181480a0a1a9SMatthew Wilcox  * and the new contents of index 10.  Indices not modified while this
181580a0a1a9SMatthew Wilcox  * function is running will not be skipped.
181680a0a1a9SMatthew Wilcox  *
181780a0a1a9SMatthew Wilcox  * If you need stronger guarantees, holding the xa_lock across calls to this
181880a0a1a9SMatthew Wilcox  * function will prevent concurrent modification.
181980a0a1a9SMatthew Wilcox  *
182080a0a1a9SMatthew Wilcox  * Context: Any context.  Takes and releases the RCU lock.
182180a0a1a9SMatthew Wilcox  * Return: The number of entries copied.
182280a0a1a9SMatthew Wilcox  */
182380a0a1a9SMatthew Wilcox unsigned int xa_extract(struct xarray *xa, void **dst, unsigned long start,
182480a0a1a9SMatthew Wilcox 			unsigned long max, unsigned int n, xa_mark_t filter)
182580a0a1a9SMatthew Wilcox {
182680a0a1a9SMatthew Wilcox 	XA_STATE(xas, xa, start);
182780a0a1a9SMatthew Wilcox 
182880a0a1a9SMatthew Wilcox 	if (!n)
182980a0a1a9SMatthew Wilcox 		return 0;
183080a0a1a9SMatthew Wilcox 
183180a0a1a9SMatthew Wilcox 	if ((__force unsigned int)filter < XA_MAX_MARKS)
183280a0a1a9SMatthew Wilcox 		return xas_extract_marked(&xas, dst, max, n, filter);
183380a0a1a9SMatthew Wilcox 	return xas_extract_present(&xas, dst, max, n);
183480a0a1a9SMatthew Wilcox }
183580a0a1a9SMatthew Wilcox EXPORT_SYMBOL(xa_extract);
183680a0a1a9SMatthew Wilcox 
1837687149fcSMatthew Wilcox /**
1838687149fcSMatthew Wilcox  * xa_destroy() - Free all internal data structures.
1839687149fcSMatthew Wilcox  * @xa: XArray.
1840687149fcSMatthew Wilcox  *
1841687149fcSMatthew Wilcox  * After calling this function, the XArray is empty and has freed all memory
1842687149fcSMatthew Wilcox  * allocated for its internal data structures.  You are responsible for
1843687149fcSMatthew Wilcox  * freeing the objects referenced by the XArray.
1844687149fcSMatthew Wilcox  *
1845687149fcSMatthew Wilcox  * Context: Any context.  Takes and releases the xa_lock, interrupt-safe.
1846687149fcSMatthew Wilcox  */
1847687149fcSMatthew Wilcox void xa_destroy(struct xarray *xa)
1848687149fcSMatthew Wilcox {
1849687149fcSMatthew Wilcox 	XA_STATE(xas, xa, 0);
1850687149fcSMatthew Wilcox 	unsigned long flags;
1851687149fcSMatthew Wilcox 	void *entry;
1852687149fcSMatthew Wilcox 
1853687149fcSMatthew Wilcox 	xas.xa_node = NULL;
1854687149fcSMatthew Wilcox 	xas_lock_irqsave(&xas, flags);
1855687149fcSMatthew Wilcox 	entry = xa_head_locked(xa);
1856687149fcSMatthew Wilcox 	RCU_INIT_POINTER(xa->xa_head, NULL);
1857687149fcSMatthew Wilcox 	xas_init_marks(&xas);
1858687149fcSMatthew Wilcox 	/* lockdep checks we're still holding the lock in xas_free_nodes() */
1859687149fcSMatthew Wilcox 	if (xa_is_node(entry))
1860687149fcSMatthew Wilcox 		xas_free_nodes(&xas, xa_to_node(entry));
1861687149fcSMatthew Wilcox 	xas_unlock_irqrestore(&xas, flags);
1862687149fcSMatthew Wilcox }
1863687149fcSMatthew Wilcox EXPORT_SYMBOL(xa_destroy);
1864687149fcSMatthew Wilcox 
1865ad3d6c72SMatthew Wilcox #ifdef XA_DEBUG
1866ad3d6c72SMatthew Wilcox void xa_dump_node(const struct xa_node *node)
1867ad3d6c72SMatthew Wilcox {
1868ad3d6c72SMatthew Wilcox 	unsigned i, j;
1869ad3d6c72SMatthew Wilcox 
1870ad3d6c72SMatthew Wilcox 	if (!node)
1871ad3d6c72SMatthew Wilcox 		return;
1872ad3d6c72SMatthew Wilcox 	if ((unsigned long)node & 3) {
1873ad3d6c72SMatthew Wilcox 		pr_cont("node %px\n", node);
1874ad3d6c72SMatthew Wilcox 		return;
1875ad3d6c72SMatthew Wilcox 	}
1876ad3d6c72SMatthew Wilcox 
1877ad3d6c72SMatthew Wilcox 	pr_cont("node %px %s %d parent %px shift %d count %d values %d "
1878ad3d6c72SMatthew Wilcox 		"array %px list %px %px marks",
1879ad3d6c72SMatthew Wilcox 		node, node->parent ? "offset" : "max", node->offset,
1880ad3d6c72SMatthew Wilcox 		node->parent, node->shift, node->count, node->nr_values,
1881ad3d6c72SMatthew Wilcox 		node->array, node->private_list.prev, node->private_list.next);
1882ad3d6c72SMatthew Wilcox 	for (i = 0; i < XA_MAX_MARKS; i++)
1883ad3d6c72SMatthew Wilcox 		for (j = 0; j < XA_MARK_LONGS; j++)
1884ad3d6c72SMatthew Wilcox 			pr_cont(" %lx", node->marks[i][j]);
1885ad3d6c72SMatthew Wilcox 	pr_cont("\n");
1886ad3d6c72SMatthew Wilcox }
1887ad3d6c72SMatthew Wilcox 
1888ad3d6c72SMatthew Wilcox void xa_dump_index(unsigned long index, unsigned int shift)
1889ad3d6c72SMatthew Wilcox {
1890ad3d6c72SMatthew Wilcox 	if (!shift)
1891ad3d6c72SMatthew Wilcox 		pr_info("%lu: ", index);
1892ad3d6c72SMatthew Wilcox 	else if (shift >= BITS_PER_LONG)
1893ad3d6c72SMatthew Wilcox 		pr_info("0-%lu: ", ~0UL);
1894ad3d6c72SMatthew Wilcox 	else
1895ad3d6c72SMatthew Wilcox 		pr_info("%lu-%lu: ", index, index | ((1UL << shift) - 1));
1896ad3d6c72SMatthew Wilcox }
1897ad3d6c72SMatthew Wilcox 
1898ad3d6c72SMatthew Wilcox void xa_dump_entry(const void *entry, unsigned long index, unsigned long shift)
1899ad3d6c72SMatthew Wilcox {
1900ad3d6c72SMatthew Wilcox 	if (!entry)
1901ad3d6c72SMatthew Wilcox 		return;
1902ad3d6c72SMatthew Wilcox 
1903ad3d6c72SMatthew Wilcox 	xa_dump_index(index, shift);
1904ad3d6c72SMatthew Wilcox 
1905ad3d6c72SMatthew Wilcox 	if (xa_is_node(entry)) {
1906ad3d6c72SMatthew Wilcox 		if (shift == 0) {
1907ad3d6c72SMatthew Wilcox 			pr_cont("%px\n", entry);
1908ad3d6c72SMatthew Wilcox 		} else {
1909ad3d6c72SMatthew Wilcox 			unsigned long i;
1910ad3d6c72SMatthew Wilcox 			struct xa_node *node = xa_to_node(entry);
1911ad3d6c72SMatthew Wilcox 			xa_dump_node(node);
1912ad3d6c72SMatthew Wilcox 			for (i = 0; i < XA_CHUNK_SIZE; i++)
1913ad3d6c72SMatthew Wilcox 				xa_dump_entry(node->slots[i],
1914ad3d6c72SMatthew Wilcox 				      index + (i << node->shift), node->shift);
1915ad3d6c72SMatthew Wilcox 		}
1916ad3d6c72SMatthew Wilcox 	} else if (xa_is_value(entry))
1917ad3d6c72SMatthew Wilcox 		pr_cont("value %ld (0x%lx) [%px]\n", xa_to_value(entry),
1918ad3d6c72SMatthew Wilcox 						xa_to_value(entry), entry);
1919ad3d6c72SMatthew Wilcox 	else if (!xa_is_internal(entry))
1920ad3d6c72SMatthew Wilcox 		pr_cont("%px\n", entry);
1921ad3d6c72SMatthew Wilcox 	else if (xa_is_retry(entry))
1922ad3d6c72SMatthew Wilcox 		pr_cont("retry (%ld)\n", xa_to_internal(entry));
1923ad3d6c72SMatthew Wilcox 	else if (xa_is_sibling(entry))
1924ad3d6c72SMatthew Wilcox 		pr_cont("sibling (slot %ld)\n", xa_to_sibling(entry));
19259f14d4f1SMatthew Wilcox 	else if (xa_is_zero(entry))
19269f14d4f1SMatthew Wilcox 		pr_cont("zero (%ld)\n", xa_to_internal(entry));
1927ad3d6c72SMatthew Wilcox 	else
1928ad3d6c72SMatthew Wilcox 		pr_cont("UNKNOWN ENTRY (%px)\n", entry);
1929ad3d6c72SMatthew Wilcox }
1930ad3d6c72SMatthew Wilcox 
1931ad3d6c72SMatthew Wilcox void xa_dump(const struct xarray *xa)
1932ad3d6c72SMatthew Wilcox {
1933ad3d6c72SMatthew Wilcox 	void *entry = xa->xa_head;
1934ad3d6c72SMatthew Wilcox 	unsigned int shift = 0;
1935ad3d6c72SMatthew Wilcox 
1936ad3d6c72SMatthew Wilcox 	pr_info("xarray: %px head %px flags %x marks %d %d %d\n", xa, entry,
19379b89a035SMatthew Wilcox 			xa->xa_flags, xa_marked(xa, XA_MARK_0),
19389b89a035SMatthew Wilcox 			xa_marked(xa, XA_MARK_1), xa_marked(xa, XA_MARK_2));
1939ad3d6c72SMatthew Wilcox 	if (xa_is_node(entry))
1940ad3d6c72SMatthew Wilcox 		shift = xa_to_node(entry)->shift + XA_CHUNK_SHIFT;
1941ad3d6c72SMatthew Wilcox 	xa_dump_entry(entry, 0, shift);
1942ad3d6c72SMatthew Wilcox }
1943ad3d6c72SMatthew Wilcox #endif
1944