Re: [PATCH v2 14/19] maple_tree: WARN_ON_ONCE when allocations fail

"Liam R. Howlett (Oracle)" <[email protected]>
Newsgroups gmane.linux.kernel,gmane.linux.kernel.mm
Message-ID <tryturkc7cl6wckhogh37wj2z5irldp43t735mqocdfc2mfgzg@jehcfg5eiesh>
On 26/07/22 12:38PM, Liam R. Howlett (Oracle) wrote:
> On 26/06/30 04:02PM, Andrew Morton wrote:
> > On Tue, 30 Jun 2026 15:08:38 -0400 "Liam R. Howlett (Oracle)" <[email protected]> wrote:
> > 
> > > Allocations should never fail in the circumstances that are expected to
> > > occur.  Add checks in the code to ensure the circumstances are correctly
> > > set up by the user and warn if they are not.
> > > 
> > > Also add a warning on failure to allocate, which should never happen.
> > > 
> > > ...
> > >
> > > --- a/lib/maple_tree.c
> > > +++ b/lib/maple_tree.c
> > > @@ -5720,6 +5720,10 @@ bool mas_nomem(struct ma_state *mas, gfp_t gfp)
> > >  	if (likely(mas->node != MA_ERROR(-ENOMEM)))
> > >  		return false;
> > >  
> > > +	/* Allocations can fail, don't do this. */
> > > +	WARN_ON_ONCE(!gfpflags_allow_blocking(gfp) &&
> > > +		     mt_external_lock(mas->tree));
> > > +
> > >  	if (gfpflags_allow_blocking(gfp) && !mt_external_lock(mas->tree)) {
> > >  		mtree_unlock(mas->tree);
> > >  		mas_alloc_nodes(mas, gfp);
> > > @@ -5730,9 +5734,12 @@ bool mas_nomem(struct ma_state *mas, gfp_t gfp)
> > >  
> > >  	/*
> > >  	 * Return false on zero forward progress.  Partial allocations are kept
> > > -	 * so the retry path will attempt to get the rest.
> > > +	 * so the retry path will attempt to get the rest.  The failure should
> > > +	 * not happen as we try our best to reclaim.  The user would need an
> > > +	 * external lock with a non-blocking gfp in a low memory situation -
> > > +	 * which would have triggered the first warning in this function.
> > >  	 */
> > > -	if (!mas->sheaf && !mas->alloc)
> > > +	if (WARN_ON_ONCE(!mas->sheaf && !mas->alloc))
> > >  		return false;
> > >  
> > 
> > Can either of these warnings duplicate the effect of !__GFP_NOWARN?
> 
> From what I understand, __GFP_NOWARN is about suppressing warnings on
> failures because you handle them at a higher level, but in this case I
> am trying to detect incorrect use of the interface.
> 
> That is, if you want to handle the failures yourself then you should use
> mas_preallocate() that is designed to give status on the allocations.
> The following call to mas_store_prealloc() will not need to allocate or
> check for nomem.

There is another issue that was discovered by syzbot on this particular
point.

After discussion [1] on the syzbot thread and off-list with Vlastimil
and Pedro, I have opted to avoid failures by using __GFP_NOFAIL for the
retry in the erase and mas_store() functions, which don't report the
failures well enough (or at all).

I'm sending the code out here to apply on top of this commit to add the
extra gfp flag on retry.

Jason has requested a restructuring that I'd like to handle later due to
the late cycle we are in at this point.

Thanks,
Liam
0001-maple_tree-Remove-warning-from-mas_nomem.patch (text/x-diff, 2.3 KB)
From 7943966dfd4eb8470d79da1fef2d81cf4cf59983 Mon Sep 17 00:00:00 2001
From: "Liam R. Howlett (Oracle)" <[email protected]>
Date: Thu, 6 Aug 2026 10:23:00 -0400
Subject: [PATCH] maple_tree: Remove warning from mas_nomem()

It is possible to trigger the warning in mas_nomem in certain call paths
using valid gfp flags.  Drop the warning and handle the failures
differently.

Instead, have mtree_erase() and mas_erase() use __GFP_NOFAIL.

During the discussion, mas_store() was also flagged as a potential path
that may fail due to implied gfp flags.  Changing those flags to retry
with __GFP_NOFAIL is a viable solution there.  At the same time, adding
a might_sleep() check to catch incorrect uses is prudent.

Signed-off-by: Liam R. Howlett (Oracle) <[email protected]>
---
 lib/maple_tree.c | 10 ++++++----
 1 file changed, 6 insertions(+), 4 deletions(-)

diff --git a/lib/maple_tree.c b/lib/maple_tree.c
index 0954d431bf981..4fb7a209dcb2d 100644
--- a/lib/maple_tree.c
+++ b/lib/maple_tree.c
@@ -5577,6 +5577,9 @@ void *mas_store(struct ma_state *mas, void *entry)
 	MA_WR_STATE(wr_mas, mas, entry);
 
 	mas_may_init_lock_check(mas);
+	if (mt_external_lock(mas->tree))
+		might_alloc(GFP_KERNEL);
+
 	trace_ma_write(TP_FCT, mas, 0, entry);
 #ifdef CONFIG_DEBUG_MAPLE_TREE
 	if (MAS_WARN_ON(mas, mas->index > mas->last))
@@ -5609,8 +5612,7 @@ void *mas_store(struct ma_state *mas, void *entry)
 		goto store;
 
 	mas_alloc_nodes(mas, GFP_NOWAIT);
-	if (mas_is_err(mas))
-		return NULL;
+	mas_nomem(mas, GFP_KERNEL | __GFP_NOFAIL);
 
 store:
 	mas_wr_store_entry(&wr_mas);
@@ -6351,7 +6353,7 @@ void *mas_erase(struct ma_state *mas)
 	/* Must reset to ensure spanning writes of last slot are detected */
 	mas_reset(mas);
 	mas_wr_preallocate(&wr_mas, NULL);
-	if (mas_nomem(mas, GFP_KERNEL)) {
+	if (mas_nomem(mas, GFP_KERNEL | __GFP_NOFAIL)) {
 		/* in case the range of entry changed when unlocked */
 		mas->index = mas->last = index;
 		goto write_retry;
@@ -6402,7 +6404,7 @@ bool mas_nomem(struct ma_state *mas, gfp_t gfp)
 	 * external lock with a non-blocking gfp in a low memory situation -
 	 * which would have triggered the first warning in this function.
 	 */
-	if (WARN_ON_ONCE(!mas->sheaf && !mas->alloc))
+	if (!mas->sheaf && !mas->alloc)
 		return false;
 
 	mas_reset(mas);
-- 
2.47.3
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.