Loading include/linux/xarray.h +1 −0 Original line number Diff line number Diff line Loading @@ -286,6 +286,7 @@ void *xa_find_after(struct xarray *xa, unsigned long *index, unsigned long max, xa_mark_t) __attribute__((nonnull(2))); unsigned int xa_extract(struct xarray *, void **dst, unsigned long start, unsigned long max, unsigned int n, xa_mark_t); void xa_destroy(struct xarray *); /** * xa_init() - Initialise an empty XArray. Loading lib/test_xarray.c +34 −0 Original line number Diff line number Diff line Loading @@ -465,6 +465,39 @@ static noinline void check_find(struct xarray *xa) check_multi_find_2(xa); } static noinline void check_destroy(struct xarray *xa) { unsigned long index; XA_BUG_ON(xa, !xa_empty(xa)); /* Destroying an empty array is a no-op */ xa_destroy(xa); XA_BUG_ON(xa, !xa_empty(xa)); /* Destroying an array with a single entry */ for (index = 0; index < 1000; index++) { xa_store_index(xa, index, GFP_KERNEL); XA_BUG_ON(xa, xa_empty(xa)); xa_destroy(xa); XA_BUG_ON(xa, !xa_empty(xa)); } /* Destroying an array with a single entry at ULONG_MAX */ xa_store(xa, ULONG_MAX, xa, GFP_KERNEL); XA_BUG_ON(xa, xa_empty(xa)); xa_destroy(xa); XA_BUG_ON(xa, !xa_empty(xa)); #ifdef CONFIG_XARRAY_MULTI /* Destroying an array with a multi-index entry */ xa_store_order(xa, 1 << 11, 11, xa, GFP_KERNEL); XA_BUG_ON(xa, xa_empty(xa)); xa_destroy(xa); XA_BUG_ON(xa, !xa_empty(xa)); #endif } static DEFINE_XARRAY(array); static int xarray_checks(void) Loading @@ -478,6 +511,7 @@ static int xarray_checks(void) check_cmpxchg(&array); check_multi_store(&array); check_find(&array); check_destroy(&array); printk("XArray: %u of %u tests passed\n", tests_passed, tests_run); return (tests_run == tests_passed) ? 0 : -EINVAL; Loading lib/xarray.c +28 −0 Original line number Diff line number Diff line Loading @@ -1524,6 +1524,34 @@ unsigned int xa_extract(struct xarray *xa, void **dst, unsigned long start, } EXPORT_SYMBOL(xa_extract); /** * xa_destroy() - Free all internal data structures. * @xa: XArray. * * After calling this function, the XArray is empty and has freed all memory * allocated for its internal data structures. You are responsible for * freeing the objects referenced by the XArray. * * Context: Any context. Takes and releases the xa_lock, interrupt-safe. */ void xa_destroy(struct xarray *xa) { XA_STATE(xas, xa, 0); unsigned long flags; void *entry; xas.xa_node = NULL; xas_lock_irqsave(&xas, flags); entry = xa_head_locked(xa); RCU_INIT_POINTER(xa->xa_head, NULL); xas_init_marks(&xas); /* lockdep checks we're still holding the lock in xas_free_nodes() */ if (xa_is_node(entry)) xas_free_nodes(&xas, xa_to_node(entry)); xas_unlock_irqrestore(&xas, flags); } EXPORT_SYMBOL(xa_destroy); #ifdef XA_DEBUG void xa_dump_node(const struct xa_node *node) { Loading Loading
include/linux/xarray.h +1 −0 Original line number Diff line number Diff line Loading @@ -286,6 +286,7 @@ void *xa_find_after(struct xarray *xa, unsigned long *index, unsigned long max, xa_mark_t) __attribute__((nonnull(2))); unsigned int xa_extract(struct xarray *, void **dst, unsigned long start, unsigned long max, unsigned int n, xa_mark_t); void xa_destroy(struct xarray *); /** * xa_init() - Initialise an empty XArray. Loading
lib/test_xarray.c +34 −0 Original line number Diff line number Diff line Loading @@ -465,6 +465,39 @@ static noinline void check_find(struct xarray *xa) check_multi_find_2(xa); } static noinline void check_destroy(struct xarray *xa) { unsigned long index; XA_BUG_ON(xa, !xa_empty(xa)); /* Destroying an empty array is a no-op */ xa_destroy(xa); XA_BUG_ON(xa, !xa_empty(xa)); /* Destroying an array with a single entry */ for (index = 0; index < 1000; index++) { xa_store_index(xa, index, GFP_KERNEL); XA_BUG_ON(xa, xa_empty(xa)); xa_destroy(xa); XA_BUG_ON(xa, !xa_empty(xa)); } /* Destroying an array with a single entry at ULONG_MAX */ xa_store(xa, ULONG_MAX, xa, GFP_KERNEL); XA_BUG_ON(xa, xa_empty(xa)); xa_destroy(xa); XA_BUG_ON(xa, !xa_empty(xa)); #ifdef CONFIG_XARRAY_MULTI /* Destroying an array with a multi-index entry */ xa_store_order(xa, 1 << 11, 11, xa, GFP_KERNEL); XA_BUG_ON(xa, xa_empty(xa)); xa_destroy(xa); XA_BUG_ON(xa, !xa_empty(xa)); #endif } static DEFINE_XARRAY(array); static int xarray_checks(void) Loading @@ -478,6 +511,7 @@ static int xarray_checks(void) check_cmpxchg(&array); check_multi_store(&array); check_find(&array); check_destroy(&array); printk("XArray: %u of %u tests passed\n", tests_passed, tests_run); return (tests_run == tests_passed) ? 0 : -EINVAL; Loading
lib/xarray.c +28 −0 Original line number Diff line number Diff line Loading @@ -1524,6 +1524,34 @@ unsigned int xa_extract(struct xarray *xa, void **dst, unsigned long start, } EXPORT_SYMBOL(xa_extract); /** * xa_destroy() - Free all internal data structures. * @xa: XArray. * * After calling this function, the XArray is empty and has freed all memory * allocated for its internal data structures. You are responsible for * freeing the objects referenced by the XArray. * * Context: Any context. Takes and releases the xa_lock, interrupt-safe. */ void xa_destroy(struct xarray *xa) { XA_STATE(xas, xa, 0); unsigned long flags; void *entry; xas.xa_node = NULL; xas_lock_irqsave(&xas, flags); entry = xa_head_locked(xa); RCU_INIT_POINTER(xa->xa_head, NULL); xas_init_marks(&xas); /* lockdep checks we're still holding the lock in xas_free_nodes() */ if (xa_is_node(entry)) xas_free_nodes(&xas, xa_to_node(entry)); xas_unlock_irqrestore(&xas, flags); } EXPORT_SYMBOL(xa_destroy); #ifdef XA_DEBUG void xa_dump_node(const struct xa_node *node) { Loading