lib/xarray: introduce a new helper xas_get_order
commit a4864671ca0bf51c8e78242951741df52c06766f upstream. It can be used after xas_load to check the order of loaded entries. Compared to xa_get_order, it saves an XA_STATE and avoid a rewalk. Added new test for xas_get_order, to make the test work, we have to export xas_get_order with EXPORT_SYMBOL_GPL. Also fix a sparse warning by checking the slot value with xa_entry instead of accessing it directly, as suggested by Matthew Wilcox. [kasong@tencent.com: simplify comment, sparse warning fix, per Matthew Wilcox] Link: https://lkml.kernel.org/r/20240416071722.45997-4-ryncsn@gmail.com Link: https://lkml.kernel.org/r/20240415171857.19244-4-ryncsn@gmail.com Signed-off-by: Kairui Song <kasong@tencent.com> Cc: Matthew Wilcox (Oracle) <willy@infradead.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Stable-dep-of: 6758c1128ceb ("mm/filemap: optimize filemap folio adding") Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
0e7877d1bb
commit
3714f62ecb
@ -1530,6 +1530,7 @@ void xas_create_range(struct xa_state *);
|
|||||||
|
|
||||||
#ifdef CONFIG_XARRAY_MULTI
|
#ifdef CONFIG_XARRAY_MULTI
|
||||||
int xa_get_order(struct xarray *, unsigned long index);
|
int xa_get_order(struct xarray *, unsigned long index);
|
||||||
|
int xas_get_order(struct xa_state *xas);
|
||||||
void xas_split(struct xa_state *, void *entry, unsigned int order);
|
void xas_split(struct xa_state *, void *entry, unsigned int order);
|
||||||
void xas_split_alloc(struct xa_state *, void *entry, unsigned int order, gfp_t);
|
void xas_split_alloc(struct xa_state *, void *entry, unsigned int order, gfp_t);
|
||||||
#else
|
#else
|
||||||
@ -1538,6 +1539,11 @@ static inline int xa_get_order(struct xarray *xa, unsigned long index)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline int xas_get_order(struct xa_state *xas)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void xas_split(struct xa_state *xas, void *entry,
|
static inline void xas_split(struct xa_state *xas, void *entry,
|
||||||
unsigned int order)
|
unsigned int order)
|
||||||
{
|
{
|
||||||
|
@ -1756,6 +1756,39 @@ static noinline void check_get_order(struct xarray *xa)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static noinline void check_xas_get_order(struct xarray *xa)
|
||||||
|
{
|
||||||
|
XA_STATE(xas, xa, 0);
|
||||||
|
|
||||||
|
unsigned int max_order = IS_ENABLED(CONFIG_XARRAY_MULTI) ? 20 : 1;
|
||||||
|
unsigned int order;
|
||||||
|
unsigned long i, j;
|
||||||
|
|
||||||
|
for (order = 0; order < max_order; order++) {
|
||||||
|
for (i = 0; i < 10; i++) {
|
||||||
|
xas_set_order(&xas, i << order, order);
|
||||||
|
do {
|
||||||
|
xas_lock(&xas);
|
||||||
|
xas_store(&xas, xa_mk_value(i));
|
||||||
|
xas_unlock(&xas);
|
||||||
|
} while (xas_nomem(&xas, GFP_KERNEL));
|
||||||
|
|
||||||
|
for (j = i << order; j < (i + 1) << order; j++) {
|
||||||
|
xas_set_order(&xas, j, 0);
|
||||||
|
rcu_read_lock();
|
||||||
|
xas_load(&xas);
|
||||||
|
XA_BUG_ON(xa, xas_get_order(&xas) != order);
|
||||||
|
rcu_read_unlock();
|
||||||
|
}
|
||||||
|
|
||||||
|
xas_lock(&xas);
|
||||||
|
xas_set_order(&xas, i << order, order);
|
||||||
|
xas_store(&xas, NULL);
|
||||||
|
xas_unlock(&xas);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static noinline void check_destroy(struct xarray *xa)
|
static noinline void check_destroy(struct xarray *xa)
|
||||||
{
|
{
|
||||||
unsigned long index;
|
unsigned long index;
|
||||||
@ -1805,6 +1838,7 @@ static int xarray_checks(void)
|
|||||||
check_reserve(&xa0);
|
check_reserve(&xa0);
|
||||||
check_multi_store(&array);
|
check_multi_store(&array);
|
||||||
check_get_order(&array);
|
check_get_order(&array);
|
||||||
|
check_xas_get_order(&array);
|
||||||
check_xa_alloc();
|
check_xa_alloc();
|
||||||
check_find(&array);
|
check_find(&array);
|
||||||
check_find_entry(&array);
|
check_find_entry(&array);
|
||||||
|
53
lib/xarray.c
53
lib/xarray.c
@ -1751,6 +1751,36 @@ unlock:
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(xa_store_range);
|
EXPORT_SYMBOL(xa_store_range);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* xas_get_order() - Get the order of an entry.
|
||||||
|
* @xas: XArray operation state.
|
||||||
|
*
|
||||||
|
* Called after xas_load, the xas should not be in an error state.
|
||||||
|
*
|
||||||
|
* Return: A number between 0 and 63 indicating the order of the entry.
|
||||||
|
*/
|
||||||
|
int xas_get_order(struct xa_state *xas)
|
||||||
|
{
|
||||||
|
int order = 0;
|
||||||
|
|
||||||
|
if (!xas->xa_node)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (;;) {
|
||||||
|
unsigned int slot = xas->xa_offset + (1 << order);
|
||||||
|
|
||||||
|
if (slot >= XA_CHUNK_SIZE)
|
||||||
|
break;
|
||||||
|
if (!xa_is_sibling(xa_entry(xas->xa, xas->xa_node, slot)))
|
||||||
|
break;
|
||||||
|
order++;
|
||||||
|
}
|
||||||
|
|
||||||
|
order += xas->xa_node->shift;
|
||||||
|
return order;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(xas_get_order);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* xa_get_order() - Get the order of an entry.
|
* xa_get_order() - Get the order of an entry.
|
||||||
* @xa: XArray.
|
* @xa: XArray.
|
||||||
@ -1761,30 +1791,13 @@ EXPORT_SYMBOL(xa_store_range);
|
|||||||
int xa_get_order(struct xarray *xa, unsigned long index)
|
int xa_get_order(struct xarray *xa, unsigned long index)
|
||||||
{
|
{
|
||||||
XA_STATE(xas, xa, index);
|
XA_STATE(xas, xa, index);
|
||||||
void *entry;
|
|
||||||
int order = 0;
|
int order = 0;
|
||||||
|
void *entry;
|
||||||
|
|
||||||
rcu_read_lock();
|
rcu_read_lock();
|
||||||
entry = xas_load(&xas);
|
entry = xas_load(&xas);
|
||||||
|
if (entry)
|
||||||
if (!entry)
|
order = xas_get_order(&xas);
|
||||||
goto unlock;
|
|
||||||
|
|
||||||
if (!xas.xa_node)
|
|
||||||
goto unlock;
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
unsigned int slot = xas.xa_offset + (1 << order);
|
|
||||||
|
|
||||||
if (slot >= XA_CHUNK_SIZE)
|
|
||||||
break;
|
|
||||||
if (!xa_is_sibling(xas.xa_node->slots[slot]))
|
|
||||||
break;
|
|
||||||
order++;
|
|
||||||
}
|
|
||||||
|
|
||||||
order += xas.xa_node->shift;
|
|
||||||
unlock:
|
|
||||||
rcu_read_unlock();
|
rcu_read_unlock();
|
||||||
|
|
||||||
return order;
|
return order;
|
||||||
|
Loading…
Reference in New Issue
Block a user