Commit 5a3fe95d authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'xarray-5.18' of git://git.infradead.org/users/willy/xarray

Pull XArray updates from Matthew Wilcox:

 - Documentation update

 - Fix test-suite build after move of bitmap.h

 - Fix xas_create_range() when a large entry is already present

 - Fix xas_split() of a shadow entry

* tag 'xarray-5.18' of git://git.infradead.org/users/willy/xarray:
  XArray: Update the LRU list in xas_split()
  XArray: Fix xas_create_range() when multi-order entry present
  XArray: Include bitmap.h from xarray.h
  XArray: Document the locking requirement for the xa_state
parents a3dfc532 3ed4bb77
Loading
Loading
Loading
Loading
+9 −5
Original line number Diff line number Diff line
@@ -315,11 +315,15 @@ indeed the normal API is implemented in terms of the advanced API. The
advanced API is only available to modules with a GPL-compatible license.

The advanced API is based around the xa_state.  This is an opaque data
structure which you declare on the stack using the XA_STATE()
macro.  This macro initialises the xa_state ready to start walking
around the XArray.  It is used as a cursor to maintain the position
in the XArray and let you compose various operations together without
having to restart from the top every time.
structure which you declare on the stack using the XA_STATE() macro.
This macro initialises the xa_state ready to start walking around the
XArray.  It is used as a cursor to maintain the position in the XArray
and let you compose various operations together without having to restart
from the top every time.  The contents of the xa_state are protected by
the rcu_read_lock() or the xas_lock().  If you need to drop whichever of
those locks is protecting your state and tree, you must call xas_pause()
so that future calls do not rely on the parts of the state which were
left unprotected.

The xa_state is also used to store errors.  You can call
xas_error() to retrieve the error.  All operations check whether
+1 −0
Original line number Diff line number Diff line
@@ -9,6 +9,7 @@
 * See Documentation/core-api/xarray.rst for how to use the XArray.
 */

#include <linux/bitmap.h>
#include <linux/bug.h>
#include <linux/compiler.h>
#include <linux/gfp.h>
+22 −0
Original line number Diff line number Diff line
@@ -1463,6 +1463,25 @@ static noinline void check_create_range_4(struct xarray *xa,
	XA_BUG_ON(xa, !xa_empty(xa));
}

static noinline void check_create_range_5(struct xarray *xa,
		unsigned long index, unsigned int order)
{
	XA_STATE_ORDER(xas, xa, index, order);
	unsigned int i;

	xa_store_order(xa, index, order, xa_mk_index(index), GFP_KERNEL);

	for (i = 0; i < order + 10; i++) {
		do {
			xas_lock(&xas);
			xas_create_range(&xas);
			xas_unlock(&xas);
		} while (xas_nomem(&xas, GFP_KERNEL));
	}

	xa_destroy(xa);
}

static noinline void check_create_range(struct xarray *xa)
{
	unsigned int order;
@@ -1490,6 +1509,9 @@ static noinline void check_create_range(struct xarray *xa)
		check_create_range_4(xa, (3U << order) + 1, order);
		check_create_range_4(xa, (3U << order) - 1, order);
		check_create_range_4(xa, (1U << 24) + 1, order);

		check_create_range_5(xa, 0, order);
		check_create_range_5(xa, (1U << order), order);
	}

	check_create_range_3();
+4 −0
Original line number Diff line number Diff line
@@ -722,6 +722,8 @@ void xas_create_range(struct xa_state *xas)

		for (;;) {
			struct xa_node *node = xas->xa_node;
			if (node->shift >= shift)
				break;
			xas->xa_node = xa_parent_locked(xas->xa, node);
			xas->xa_offset = node->offset - 1;
			if (node->offset != 0)
@@ -1079,6 +1081,7 @@ void xas_split(struct xa_state *xas, void *entry, unsigned int order)
					xa_mk_node(child));
			if (xa_is_value(curr))
				values--;
			xas_update(xas, child);
		} else {
			unsigned int canon = offset - xas->xa_sibs;

@@ -1093,6 +1096,7 @@ void xas_split(struct xa_state *xas, void *entry, unsigned int order)
	} while (offset-- > xas->xa_offset);

	node->nr_values += values;
	xas_update(xas, node);
}
EXPORT_SYMBOL_GPL(xas_split);
#endif