Re: [PATCH v7 00/70] Introducing the Maple Tree
From: Liam Howlett
Date: Tue Apr 19 2022 - 11:51:21 EST
* Yu Zhao <yuzhao@xxxxxxxxxx> [220416 15:30]:
> On Sat, Apr 16, 2022 at 9:19 AM Liam Howlett <liam.howlett@xxxxxxxxxx> wrote:
> >
>
> <snipped>
>
> > How did you hit this issue? Just on boot?
>
> I was hoping this is known to you or you have something I can verify for you.
Thanks, yes. I believe that both crashes are the same root cause. The
cause is that I was not cleaning up after the kmem bulk allocation
failure on my side. Please test with this patch.
Thanks,
Liam
From 1469ecc8c9ef662066e53d4a4a00c84d94ee9dc4 Mon Sep 17 00:00:00 2001
From: "Liam R. Howlett" <Liam.Howlett@xxxxxxxxxx>
Date: Tue, 19 Apr 2022 11:47:15 -0400
Subject: [PATCH] maple_tree: Clean up after bulk allocation failure in
mas_alloc_nodes()
Signed-off-by: Liam R. Howlett <Liam.Howlett@xxxxxxxxxx>
---
lib/maple_tree.c | 22 ++++++++++++++--------
1 file changed, 14 insertions(+), 8 deletions(-)
diff --git a/lib/maple_tree.c b/lib/maple_tree.c
index 6393be9d9230..3c78e63efaec 100644
--- a/lib/maple_tree.c
+++ b/lib/maple_tree.c
@@ -1206,6 +1206,8 @@ static inline void mas_alloc_nodes(struct ma_state *mas, gfp_t gfp)
unsigned long success = allocated;
unsigned int requested = mas_alloc_req(mas);
unsigned int count;
+ void **slots = NULL;
+ unsigned int max_req = 0;
if (!requested)
return;
@@ -1214,7 +1216,7 @@ static inline void mas_alloc_nodes(struct ma_state *mas, gfp_t gfp)
if (!allocated || mas->alloc->node_count == MAPLE_ALLOC_SLOTS - 1) {
node = (struct maple_alloc *)mt_alloc_one(gfp);
if (!node)
- goto nomem;
+ goto nomem_one;
if (allocated)
node->slot[0] = mas->alloc;
@@ -1226,20 +1228,20 @@ static inline void mas_alloc_nodes(struct ma_state *mas, gfp_t gfp)
node = mas->alloc;
while (requested) {
- void **slots = (void **)&node->slot;
- unsigned int max_req = MAPLE_NODE_SLOTS - 1;
-
+ max_req = MAPLE_NODE_SLOTS - 1;
if (node->slot[0]) {
unsigned int offset = node->node_count + 1;
slots = (void **)&node->slot[offset];
max_req -= offset;
+ } else {
+ slots = (void **)&node->slot;
}
- count = mt_alloc_bulk(gfp, min(requested, max_req),
- slots);
+ max_req = min(requested, max_req);
+ count = mt_alloc_bulk(gfp, max_req, slots);
if (!count)
- goto nomem;
+ goto nomem_bulk;
node->node_count += count;
/* zero indexed. */
@@ -1253,7 +1255,11 @@ static inline void mas_alloc_nodes(struct ma_state *mas, gfp_t gfp)
}
mas->alloc->total = success;
return;
-nomem:
+
+nomem_bulk:
+ /* Clean up potential freed allocations on bulk failure */
+ memset(slots, 0, max_req * sizeof(unsigned long));
+nomem_one:
mas_set_alloc_req(mas, requested);
if (mas->alloc && !(((unsigned long)mas->alloc & 0x1)))
mas->alloc->total = success;
--
2.34.1