On Tue, Feb 04, 2020 at 03:25:08PM +0100, Jan Kara wrote: > +void *xas_erase(struct xa_state *xas) > +{ > + void *entry; > + > + entry = xas_store(xas, NULL); > + xas_init_marks(xas); > + > + return entry; > +} > +EXPORT_SYMBOL(xas_erase); I didn't have a test case to show this, but ... +static noinline void check_multi_store_4(struct xarray *xa) +{ + XA_BUG_ON(xa, xa_marked(xa, XA_MARK_0)); + XA_BUG_ON(xa, !xa_empty(xa)); + + xa_store_index(xa, 0, GFP_KERNEL); + xa_store_index(xa, 2, GFP_KERNEL); + xa_set_mark(xa, 0, XA_MARK_0); + xa_set_mark(xa, 2, XA_MARK_0); + + xa_store_order(xa, 0, 2, NULL, GFP_KERNEL); + XA_BUG_ON(xa, xa_marked(xa, XA_MARK_0)); + xa_destroy(xa); +} shows a problem. Because we delete all the entries in the tree, xas_delete_node() sets the xas->xa_node to XAS_BOUNDS. This fixes it: @@ -492,7 +492,6 @@ static void xas_delete_node(struct xa_state *xas) if (!parent) { xas->xa->xa_head = NULL; - xas->xa_node = XAS_BOUNDS; return; } (it leaves xas->xa_node set to NULL, which makes the above work correctly because NULL is used to mean the one element at index 0 of the array) Now I'm wondering if it's going to break anything, though. The test suite runs successfully, but it can't be exhaustive.