xarray: Add xas_for_each_conflict
This iterator iterates over each entry that is stored in the index or indices specified by the xa_state. This is intended for use for a conditional store of a multiindex entry, or to allow entries which are about to be removed from the xarray to be disposed of properly. Signed-off-by: Matthew Wilcox <willy@infradead.org>
This commit is contained in:
@@ -365,6 +365,73 @@ static noinline void check_multi_store(struct xarray *xa)
|
||||
#endif
|
||||
}
|
||||
|
||||
static noinline void __check_store_iter(struct xarray *xa, unsigned long start,
|
||||
unsigned int order, unsigned int present)
|
||||
{
|
||||
XA_STATE_ORDER(xas, xa, start, order);
|
||||
void *entry;
|
||||
unsigned int count = 0;
|
||||
|
||||
retry:
|
||||
xas_lock(&xas);
|
||||
xas_for_each_conflict(&xas, entry) {
|
||||
XA_BUG_ON(xa, !xa_is_value(entry));
|
||||
XA_BUG_ON(xa, entry < xa_mk_value(start));
|
||||
XA_BUG_ON(xa, entry > xa_mk_value(start + (1UL << order) - 1));
|
||||
count++;
|
||||
}
|
||||
xas_store(&xas, xa_mk_value(start));
|
||||
xas_unlock(&xas);
|
||||
if (xas_nomem(&xas, GFP_KERNEL)) {
|
||||
count = 0;
|
||||
goto retry;
|
||||
}
|
||||
XA_BUG_ON(xa, xas_error(&xas));
|
||||
XA_BUG_ON(xa, count != present);
|
||||
XA_BUG_ON(xa, xa_load(xa, start) != xa_mk_value(start));
|
||||
XA_BUG_ON(xa, xa_load(xa, start + (1UL << order) - 1) !=
|
||||
xa_mk_value(start));
|
||||
xa_erase_index(xa, start);
|
||||
}
|
||||
|
||||
static noinline void check_store_iter(struct xarray *xa)
|
||||
{
|
||||
unsigned int i, j;
|
||||
unsigned int max_order = IS_ENABLED(CONFIG_XARRAY_MULTI) ? 20 : 1;
|
||||
|
||||
for (i = 0; i < max_order; i++) {
|
||||
unsigned int min = 1 << i;
|
||||
unsigned int max = (2 << i) - 1;
|
||||
__check_store_iter(xa, 0, i, 0);
|
||||
XA_BUG_ON(xa, !xa_empty(xa));
|
||||
__check_store_iter(xa, min, i, 0);
|
||||
XA_BUG_ON(xa, !xa_empty(xa));
|
||||
|
||||
xa_store_index(xa, min, GFP_KERNEL);
|
||||
__check_store_iter(xa, min, i, 1);
|
||||
XA_BUG_ON(xa, !xa_empty(xa));
|
||||
xa_store_index(xa, max, GFP_KERNEL);
|
||||
__check_store_iter(xa, min, i, 1);
|
||||
XA_BUG_ON(xa, !xa_empty(xa));
|
||||
|
||||
for (j = 0; j < min; j++)
|
||||
xa_store_index(xa, j, GFP_KERNEL);
|
||||
__check_store_iter(xa, 0, i, min);
|
||||
XA_BUG_ON(xa, !xa_empty(xa));
|
||||
for (j = 0; j < min; j++)
|
||||
xa_store_index(xa, min + j, GFP_KERNEL);
|
||||
__check_store_iter(xa, min, i, min);
|
||||
XA_BUG_ON(xa, !xa_empty(xa));
|
||||
}
|
||||
#ifdef CONFIG_XARRAY_MULTI
|
||||
xa_store_index(xa, 63, GFP_KERNEL);
|
||||
xa_store_index(xa, 65, GFP_KERNEL);
|
||||
__check_store_iter(xa, 64, 2, 1);
|
||||
xa_erase_index(xa, 63);
|
||||
#endif
|
||||
XA_BUG_ON(xa, !xa_empty(xa));
|
||||
}
|
||||
|
||||
static noinline void check_multi_find(struct xarray *xa)
|
||||
{
|
||||
#ifdef CONFIG_XARRAY_MULTI
|
||||
@@ -627,6 +694,7 @@ static int xarray_checks(void)
|
||||
check_find(&array);
|
||||
check_destroy(&array);
|
||||
check_move(&array);
|
||||
check_store_iter(&array);
|
||||
|
||||
printk("XArray: %u of %u tests passed\n", tests_passed, tests_run);
|
||||
return (tests_run == tests_passed) ? 0 : -EINVAL;
|
||||
|
Reference in New Issue
Block a user