* [PATCH] XArray: Set the marks correctly when splitting an entry
@ 2024-05-01 15:31 Matthew Wilcox (Oracle)
2024-05-01 16:20 ` Luis Chamberlain
0 siblings, 1 reply; 2+ messages in thread
From: Matthew Wilcox (Oracle) @ 2024-05-01 15:31 UTC (permalink / raw)
To: Andrew Morton
Cc: Matthew Wilcox (Oracle),
Zi Yan, linux-mm, linux-fsdevel, Luis Chamberlain
If we created a new node to replace an entry which had search marks set,
we were setting the search mark on every entry in that node. That works
fine when we're splitting to order 0, but when splitting to a larger
order, we must not set the search marks on the sibling entries.
Reported-by: Luis Chamberlain <mcgrof@kernel.org>
Link: https://lore.kernel.org/r/ZjFGCOYk3FK_zVy3@bombadil.infradead.org
Fixes: c010d47f107f ("mm: thp: split huge page to any lower order pages")
Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
---
lib/test_xarray.c | 14 +++++++++++++-
lib/xarray.c | 23 +++++++++++++++++++----
2 files changed, 32 insertions(+), 5 deletions(-)
diff --git a/lib/test_xarray.c b/lib/test_xarray.c
index 0aea6a85099d..ab9cc42a0d74 100644
--- a/lib/test_xarray.c
+++ b/lib/test_xarray.c
@@ -1788,9 +1788,11 @@ static void check_split_1(struct xarray *xa, unsigned long index,
unsigned int order, unsigned int new_order)
{
XA_STATE_ORDER(xas, xa, index, new_order);
- unsigned int i;
+ unsigned int i, found;
+ void *entry;
xa_store_order(xa, index, order, xa, GFP_KERNEL);
+ xa_set_mark(xa, index, XA_MARK_1);
xas_split_alloc(&xas, xa, order, GFP_KERNEL);
xas_lock(&xas);
@@ -1807,6 +1809,16 @@ static void check_split_1(struct xarray *xa, unsigned long index,
xa_set_mark(xa, index, XA_MARK_0);
XA_BUG_ON(xa, !xa_get_mark(xa, index, XA_MARK_0));
+ xas_set_order(&xas, index, 0);
+ found = 0;
+ rcu_read_lock();
+ xas_for_each_marked(&xas, entry, ULONG_MAX, XA_MARK_1) {
+ found++;
+ XA_BUG_ON(xa, xa_is_internal(entry));
+ }
+ rcu_read_unlock();
+ XA_BUG_ON(xa, found != 1 << (order - new_order));
+
xa_destroy(xa);
}
diff --git a/lib/xarray.c b/lib/xarray.c
index 1c87d871cacf..32d4bac8c94c 100644
--- a/lib/xarray.c
+++ b/lib/xarray.c
@@ -970,8 +970,22 @@ static unsigned int node_get_marks(struct xa_node *node, unsigned int offset)
return marks;
}
+static inline void node_mark_slots(struct xa_node *node, unsigned int sibs,
+ xa_mark_t mark)
+{
+ int i;
+
+ if (sibs == 0)
+ node_mark_all(node, mark);
+ else {
+ for (i = 0; i < XA_CHUNK_SIZE; i += sibs + 1)
+ node_set_mark(node, i, mark);
+ }
+}
+
static void node_set_marks(struct xa_node *node, unsigned int offset,
- struct xa_node *child, unsigned int marks)
+ struct xa_node *child, unsigned int sibs,
+ unsigned int marks)
{
xa_mark_t mark = XA_MARK_0;
@@ -979,7 +993,7 @@ static void node_set_marks(struct xa_node *node, unsigned int offset,
if (marks & (1 << (__force unsigned int)mark)) {
node_set_mark(node, offset, mark);
if (child)
- node_mark_all(child, mark);
+ node_mark_slots(child, sibs, mark);
}
if (mark == XA_MARK_MAX)
break;
@@ -1078,7 +1092,8 @@ void xas_split(struct xa_state *xas, void *entry, unsigned int order)
child->nr_values = xa_is_value(entry) ?
XA_CHUNK_SIZE : 0;
RCU_INIT_POINTER(child->parent, node);
- node_set_marks(node, offset, child, marks);
+ node_set_marks(node, offset, child, xas->xa_sibs,
+ marks);
rcu_assign_pointer(node->slots[offset],
xa_mk_node(child));
if (xa_is_value(curr))
@@ -1087,7 +1102,7 @@ void xas_split(struct xa_state *xas, void *entry, unsigned int order)
} else {
unsigned int canon = offset - xas->xa_sibs;
- node_set_marks(node, canon, NULL, marks);
+ node_set_marks(node, canon, NULL, 0, marks);
rcu_assign_pointer(node->slots[canon], entry);
while (offset > canon)
rcu_assign_pointer(node->slots[offset--],
--
2.43.0
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [PATCH] XArray: Set the marks correctly when splitting an entry
2024-05-01 15:31 [PATCH] XArray: Set the marks correctly when splitting an entry Matthew Wilcox (Oracle)
@ 2024-05-01 16:20 ` Luis Chamberlain
0 siblings, 0 replies; 2+ messages in thread
From: Luis Chamberlain @ 2024-05-01 16:20 UTC (permalink / raw)
To: Matthew Wilcox (Oracle); +Cc: Andrew Morton, Zi Yan, linux-mm, linux-fsdevel
On Wed, May 01, 2024 at 04:31:18PM +0100, Matthew Wilcox (Oracle) wrote:
> If we created a new node to replace an entry which had search marks set,
> we were setting the search mark on every entry in that node. That works
> fine when we're splitting to order 0, but when splitting to a larger
> order, we must not set the search marks on the sibling entries.
>
> Reported-by: Luis Chamberlain <mcgrof@kernel.org>
> Link: https://lore.kernel.org/r/ZjFGCOYk3FK_zVy3@bombadil.infradead.org
> Fixes: c010d47f107f ("mm: thp: split huge page to any lower order pages")
> Signed-off-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Thanks!
Tested-by: Luis Chamberlain <mcgrof@kernel.org>
Luis
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2024-05-01 16:21 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-05-01 15:31 [PATCH] XArray: Set the marks correctly when splitting an entry Matthew Wilcox (Oracle)
2024-05-01 16:20 ` Luis Chamberlain
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox