Commit 00ed452c authored by Matthew Wilcox (Oracle)'s avatar Matthew Wilcox (Oracle)
Browse files

XArray: Add xa_for_each_range



This function supports iterating over a range of an array.  Also add
documentation links for xa_for_each_start().

Signed-off-by: default avatarMatthew Wilcox (Oracle) <willy@infradead.org>
parent c44aa5e8
Loading
Loading
Loading
Loading
+6 −4
Original line number Diff line number Diff line
@@ -82,10 +82,10 @@ at that index is ``NULL``, you can use xa_insert() which
returns ``-EBUSY`` if the entry is not empty.

You can copy entries out of the XArray into a plain array by calling
xa_extract().  Or you can iterate over the present entries in
the XArray by calling xa_for_each().  You may prefer to use
xa_find() or xa_find_after() to move to the next present
entry in the XArray.
xa_extract().  Or you can iterate over the present entries in the XArray
by calling xa_for_each(), xa_for_each_start() or xa_for_each_range().
You may prefer to use xa_find() or xa_find_after() to move to the next
present entry in the XArray.

Calling xa_store_range() stores the same entry in a range
of indices.  If you do this, some of the other operations will behave
@@ -193,6 +193,8 @@ No lock needed:
Takes RCU read lock:
 * xa_load()
 * xa_for_each()
 * xa_for_each_start()
 * xa_for_each_range()
 * xa_find()
 * xa_find_after()
 * xa_extract()
+32 −5
Original line number Diff line number Diff line
@@ -416,6 +416,36 @@ static inline bool xa_marked(const struct xarray *xa, xa_mark_t mark)
	return xa->xa_flags & XA_FLAGS_MARK(mark);
}

/**
 * xa_for_each_range() - Iterate over a portion of an XArray.
 * @xa: XArray.
 * @index: Index of @entry.
 * @entry: Entry retrieved from array.
 * @start: First index to retrieve from array.
 * @last: Last index to retrieve from array.
 *
 * During the iteration, @entry will have the value of the entry stored
 * in @xa at @index.  You may modify @index during the iteration if you
 * want to skip or reprocess indices.  It is safe to modify the array
 * during the iteration.  At the end of the iteration, @entry will be set
 * to NULL and @index will have a value less than or equal to max.
 *
 * xa_for_each_range() is O(n.log(n)) while xas_for_each() is O(n).  You have
 * to handle your own locking with xas_for_each(), and if you have to unlock
 * after each iteration, it will also end up being O(n.log(n)).
 * xa_for_each_range() will spin if it hits a retry entry; if you intend to
 * see retry entries, you should use the xas_for_each() iterator instead.
 * The xas_for_each() iterator will expand into more inline code than
 * xa_for_each_range().
 *
 * Context: Any context.  Takes and releases the RCU lock.
 */
#define xa_for_each_range(xa, index, entry, start, last)		\
	for (index = start,						\
	     entry = xa_find(xa, &index, last, XA_PRESENT);		\
	     entry;							\
	     entry = xa_find_after(xa, &index, last, XA_PRESENT))

/**
 * xa_for_each_start() - Iterate over a portion of an XArray.
 * @xa: XArray.
@@ -440,10 +470,7 @@ static inline bool xa_marked(const struct xarray *xa, xa_mark_t mark)
 * Context: Any context.  Takes and releases the RCU lock.
 */
#define xa_for_each_start(xa, index, entry, start) \
	for (index = start,						\
	     entry = xa_find(xa, &index, ULONG_MAX, XA_PRESENT);	\
	     entry;							\
	     entry = xa_find_after(xa, &index, ULONG_MAX, XA_PRESENT))
	xa_for_each_range(xa, index, entry, start, ULONG_MAX)

/**
 * xa_for_each() - Iterate over present entries in an XArray.