__xa_store() does not set up xas->xa_sibs, and when it calls xas_store(), xas_store() stops prematurely and does not update node->nr_values to count all values and siblings. Hence, when working with multi-index XArrays, __xa_store() cannot be used. Fix tests by calling xas_store() directly with xas->xa_sibs correctly set up. Signed-off-by: Ackerley Tng --- lib/test_xarray.c | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/lib/test_xarray.c b/lib/test_xarray.c index 5ca0aefee9aa5..e71e8ff76900b 100644 --- a/lib/test_xarray.c +++ b/lib/test_xarray.c @@ -1846,8 +1846,14 @@ static void check_split_1(struct xarray *xa, unsigned long index, xas_split_alloc(&xas, xa, order, GFP_KERNEL); xas_lock(&xas); xas_split(&xas, xa, order); - for (i = 0; i < (1 << order); i += (1 << new_order)) - __xa_store(xa, index + i, xa_mk_index(index + i), 0); + for (i = 0; i < (1 << order); i += (1 << new_order)) { + xas_set_order(&xas, index + i, new_order); + /* + * Don't worry about -ENOMEM, xas_split_alloc() and + * xas_split() ensures that all nodes are allocated. + */ + xas_store(&xas, xa_mk_index(index + i)); + } xas_unlock(&xas); for (i = 0; i < (1 << order); i++) { @@ -1893,8 +1899,14 @@ static void check_split_2(struct xarray *xa, unsigned long index, xas_unlock(&xas); goto out; } - for (i = 0; i < (1 << order); i += (1 << new_order)) - __xa_store(xa, index + i, xa_mk_index(index + i), 0); + for (i = 0; i < (1 << order); i += (1 << new_order)) { + xas_set_order(&xas, index + i, new_order); + /* + * Don't worry about -ENOMEM, xas_split_alloc() and + * xas_split() ensures that all nodes are allocated. + */ + xas_store(&xas, xa_mk_index(index + i)); + } xas_unlock(&xas); for (i = 0; i < (1 << order); i++) { -- 2.53.0.345.g96ddfc5eaa-goog Both __xa_store() and xa_erase() use xas_store() under the hood, but when the entry being stored is NULL (as in the case of xa_erase()), xas->xa_sibs (and max) is only checked if the next entry is not a sibling, hence allowing xas_store() to keep iterating, hence updating node->nr_values correctly. Add xa_erase() to check_split tests that verify functionality, with the added intent to illustrate the usage differences between __xa_store(), xas_store() and xa_erase() with regard to multi-index XArrays. Signed-off-by: Ackerley Tng --- lib/test_xarray.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/test_xarray.c b/lib/test_xarray.c index e71e8ff76900b..bb9471a3df65c 100644 --- a/lib/test_xarray.c +++ b/lib/test_xarray.c @@ -1874,6 +1874,10 @@ static void check_split_1(struct xarray *xa, unsigned long index, rcu_read_unlock(); XA_BUG_ON(xa, found != 1 << (order - new_order)); + for (i = 0; i < (1 << order); i += (1 << new_order)) + xa_erase(xa, index + i); + XA_BUG_ON(xa, !xa_empty(xa)); + xa_destroy(xa); } @@ -1926,6 +1930,10 @@ static void check_split_2(struct xarray *xa, unsigned long index, } rcu_read_unlock(); XA_BUG_ON(xa, found != 1 << (order - new_order)); + + for (i = 0; i < (1 << order); i += (1 << new_order)) + xa_erase(xa, index + i); + XA_BUG_ON(xa, !xa_empty(xa)); out: xas_destroy(&xas); xa_destroy(xa); -- 2.53.0.345.g96ddfc5eaa-goog