Commit c4d6fe73 authored by Linus Torvalds's avatar Linus Torvalds
Browse files

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

Pull XArray updates from Matthew Wilcox:

 - Fix the test suite after introduction of the local_lock

 - Fix a bug in the IDA spotted by Coverity

 - Change the API that allows the workingset code to delete a node

 - Fix xas_reload() when dealing with entries that occupy multiple
   indices

 - Add a few more tests to the test suite

 - Fix an unsigned int being shifted into an unsigned long

* tag 'xarray-5.9' of git://git.infradead.org/users/willy/xarray:
  XArray: Fix xas_create_range for ranges above 4 billion
  radix-tree: fix the comment of radix_tree_next_slot()
  XArray: Fix xas_reload for multi-index entries
  XArray: Add private interface for workingset node deletion
  XArray: Fix xas_for_each_conflict documentation
  XArray: Test marked multiorder iterations
  XArray: Test two more things about xa_cmpxchg
  ida: Free allocated bitmap in error path
  radix tree test suite: Fix compilation
parents 59f0e7eb 84c34df1
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@
#include <linux/bitops.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/percpu.h>
#include <linux/preempt.h>
#include <linux/rcupdate.h>
#include <linux/spinlock.h>
@@ -376,7 +377,7 @@ radix_tree_chunk_size(struct radix_tree_iter *iter)
 * radix_tree_next_slot - find next slot in chunk
 *
 * @slot:	pointer to current slot
 * @iter:	pointer to interator state
 * @iter:	pointer to iterator state
 * @flags:	RADIX_TREE_ITER_*, should be constant
 * Returns:	pointer to next slot, or NULL if there no more left
 *
+23 −11
Original line number Diff line number Diff line
@@ -1286,6 +1286,8 @@ static inline bool xa_is_advanced(const void *entry)
 */
typedef void (*xa_update_node_t)(struct xa_node *node);

void xa_delete_node(struct xa_node *, xa_update_node_t);

/*
 * The xa_state is opaque to its users.  It contains various different pieces
 * of state involved in the current operation on the XArray.  It should be
@@ -1544,10 +1546,21 @@ static inline void xas_split_alloc(struct xa_state *xas, void *entry,
static inline void *xas_reload(struct xa_state *xas)
{
	struct xa_node *node = xas->xa_node;
	void *entry;
	char offset;

	if (node)
		return xa_entry(xas->xa, node, xas->xa_offset);
	if (!node)
		return xa_head(xas->xa);
	if (IS_ENABLED(CONFIG_XARRAY_MULTI)) {
		offset = (xas->xa_index >> node->shift) & XA_CHUNK_MASK;
		entry = xa_entry(xas->xa, node, offset);
		if (!xa_is_sibling(entry))
			return entry;
		offset = xa_to_sibling(entry);
	} else {
		offset = xas->xa_offset;
	}
	return xa_entry(xas->xa, node, offset);
}

/**
@@ -1736,13 +1749,12 @@ enum {
 * @xas: XArray operation state.
 * @entry: Entry retrieved from the array.
 *
 * The loop body will be executed for each entry in the XArray that lies
 * within the range specified by @xas.  If the loop completes successfully,
 * any entries that lie in this range will be replaced by @entry.  The caller
 * may break out of the loop; if they do so, the contents of the XArray will
 * be unchanged.  The operation may fail due to an out of memory condition.
 * The caller may also call xa_set_err() to exit the loop while setting an
 * error to record the reason.
 * The loop body will be executed for each entry in the XArray that
 * lies within the range specified by @xas.  If the loop terminates
 * normally, @entry will be %NULL.  The user may break out of the loop,
 * which will leave @entry set to the conflicting entry.  The caller
 * may also call xa_set_err() to exit the loop while setting an error
 * to record the reason.
 */
#define xas_for_each_conflict(xas, entry) \
	while ((entry = xas_find_conflict(xas)))
+1 −0
Original line number Diff line number Diff line
@@ -471,6 +471,7 @@ alloc:
	goto retry;
nospc:
	xas_unlock_irqrestore(&xas, flags);
	kfree(alloc);
	return -ENOSPC;
}
EXPORT_SYMBOL(ida_alloc_range);
+0 −1
Original line number Diff line number Diff line
@@ -20,7 +20,6 @@
#include <linux/kernel.h>
#include <linux/kmemleak.h>
#include <linux/percpu.h>
#include <linux/local_lock.h>
#include <linux/preempt.h>		/* in_interrupt() */
#include <linux/radix-tree.h>
#include <linux/rcupdate.h>
+26 −6
Original line number Diff line number Diff line
@@ -289,6 +289,27 @@ static noinline void check_xa_mark_2(struct xarray *xa)
	xa_destroy(xa);
}

static noinline void check_xa_mark_3(struct xarray *xa)
{
#ifdef CONFIG_XARRAY_MULTI
	XA_STATE(xas, xa, 0x41);
	void *entry;
	int count = 0;

	xa_store_order(xa, 0x40, 2, xa_mk_index(0x40), GFP_KERNEL);
	xa_set_mark(xa, 0x41, XA_MARK_0);

	rcu_read_lock();
	xas_for_each_marked(&xas, entry, ULONG_MAX, XA_MARK_0) {
		count++;
		XA_BUG_ON(xa, entry != xa_mk_index(0x40));
	}
	XA_BUG_ON(xa, count != 1);
	rcu_read_unlock();
	xa_destroy(xa);
#endif
}

static noinline void check_xa_mark(struct xarray *xa)
{
	unsigned long index;
@@ -297,6 +318,7 @@ static noinline void check_xa_mark(struct xarray *xa)
		check_xa_mark_1(xa, index);

	check_xa_mark_2(xa);
	check_xa_mark_3(xa);
}

static noinline void check_xa_shrink(struct xarray *xa)
@@ -393,6 +415,9 @@ static noinline void check_cmpxchg(struct xarray *xa)
	XA_BUG_ON(xa, xa_cmpxchg(xa, 12345678, FIVE, LOTS, GFP_KERNEL) != FIVE);
	XA_BUG_ON(xa, xa_cmpxchg(xa, 5, FIVE, NULL, GFP_KERNEL) != NULL);
	XA_BUG_ON(xa, xa_cmpxchg(xa, 5, NULL, FIVE, GFP_KERNEL) != NULL);
	XA_BUG_ON(xa, xa_insert(xa, 5, FIVE, GFP_KERNEL) != -EBUSY);
	XA_BUG_ON(xa, xa_cmpxchg(xa, 5, FIVE, NULL, GFP_KERNEL) != FIVE);
	XA_BUG_ON(xa, xa_insert(xa, 5, FIVE, GFP_KERNEL) == -EBUSY);
	xa_erase_index(xa, 12345678);
	xa_erase_index(xa, 5);
	XA_BUG_ON(xa, !xa_empty(xa));
@@ -1618,14 +1643,9 @@ static noinline void shadow_remove(struct xarray *xa)
	xa_lock(xa);
	while ((node = list_first_entry_or_null(&shadow_nodes,
					struct xa_node, private_list))) {
		XA_STATE(xas, node->array, 0);
		XA_BUG_ON(xa, node->array != xa);
		list_del_init(&node->private_list);
		xas.xa_node = xa_parent_locked(node->array, node);
		xas.xa_offset = node->offset;
		xas.xa_shift = node->shift + XA_CHUNK_SHIFT;
		xas_set_update(&xas, test_update_node);
		xas_store(&xas, NULL);
		xa_delete_node(node, test_update_node);
	}
	xa_unlock(xa);
}
Loading