Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 48483614 authored by Matthew Wilcox's avatar Matthew Wilcox
Browse files

XArray: Fix xa_alloc when id exceeds max



Specifying a starting ID greater than the maximum ID isn't something
attempted very often, but it should fail.  It was succeeding due to
xas_find_marked() returning the wrong error state, so add tests for
both xa_alloc() and xas_find_marked().

Fixes: b803b428 ("xarray: Add XArray iterators")
Signed-off-by: default avatarMatthew Wilcox <willy@infradead.org>
parent 4f145cd6
Loading
Loading
Loading
Loading
+33 −0
Original line number Original line Diff line number Diff line
@@ -633,6 +633,15 @@ static noinline void check_xa_alloc(void)
				GFP_KERNEL) != -ENOSPC);
				GFP_KERNEL) != -ENOSPC);
	XA_BUG_ON(&xa0, id != 0xffffffffU);
	XA_BUG_ON(&xa0, id != 0xffffffffU);
	xa_destroy(&xa0);
	xa_destroy(&xa0);

	id = 10;
	XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, 5, xa_mk_index(id),
				GFP_KERNEL) != -ENOSPC);
	XA_BUG_ON(&xa0, xa_store_index(&xa0, 3, GFP_KERNEL) != 0);
	XA_BUG_ON(&xa0, xa_alloc(&xa0, &id, 5, xa_mk_index(id),
				GFP_KERNEL) != -ENOSPC);
	xa_erase_index(&xa0, 3);
	XA_BUG_ON(&xa0, !xa_empty(&xa0));
}
}


static noinline void __check_store_iter(struct xarray *xa, unsigned long start,
static noinline void __check_store_iter(struct xarray *xa, unsigned long start,
@@ -822,10 +831,34 @@ static noinline void check_find_2(struct xarray *xa)
	xa_destroy(xa);
	xa_destroy(xa);
}
}


static noinline void check_find_3(struct xarray *xa)
{
	XA_STATE(xas, xa, 0);
	unsigned long i, j, k;
	void *entry;

	for (i = 0; i < 100; i++) {
		for (j = 0; j < 100; j++) {
			for (k = 0; k < 100; k++) {
				xas_set(&xas, j);
				xas_for_each_marked(&xas, entry, k, XA_MARK_0)
					;
				if (j > k)
					XA_BUG_ON(xa,
						xas.xa_node != XAS_RESTART);
			}
		}
		xa_store_index(xa, i, GFP_KERNEL);
		xa_set_mark(xa, i, XA_MARK_0);
	}
	xa_destroy(xa);
}

static noinline void check_find(struct xarray *xa)
static noinline void check_find(struct xarray *xa)
{
{
	check_find_1(xa);
	check_find_1(xa);
	check_find_2(xa);
	check_find_2(xa);
	check_find_3(xa);
	check_multi_find(xa);
	check_multi_find(xa);
	check_multi_find_2(xa);
	check_multi_find_2(xa);
}
}
+3 −5
Original line number Original line Diff line number Diff line
@@ -1131,7 +1131,7 @@ void *xas_find_marked(struct xa_state *xas, unsigned long max, xa_mark_t mark)
		entry = xa_head(xas->xa);
		entry = xa_head(xas->xa);
		xas->xa_node = NULL;
		xas->xa_node = NULL;
		if (xas->xa_index > max_index(entry))
		if (xas->xa_index > max_index(entry))
			goto bounds;
			goto out;
		if (!xa_is_node(entry)) {
		if (!xa_is_node(entry)) {
			if (xa_marked(xas->xa, mark))
			if (xa_marked(xas->xa, mark))
				return entry;
				return entry;
@@ -1180,11 +1180,9 @@ void *xas_find_marked(struct xa_state *xas, unsigned long max, xa_mark_t mark)
	}
	}


out:
out:
	if (!max)
	if (xas->xa_index > max)
		goto max;
		goto max;
bounds:
	return set_bounds(xas);
	xas->xa_node = XAS_BOUNDS;
	return NULL;
max:
max:
	xas->xa_node = XAS_RESTART;
	xas->xa_node = XAS_RESTART;
	return NULL;
	return NULL;