From: Andrew Morton <akpm@linux-foundation.org>
To: "Liam R. Howlett (Oracle)" <liam@infradead.org>
Cc: linux-mm@kvack.org, linux-kernel@vger.kernel.org,
maple-tree@lists.infradead.org
Subject: Re: [PATCH v3 00/19] maple_tree: lock checking and clean ups
Date: Fri, 21 Aug 2026 15:42:20 -0700 [thread overview]
Message-ID: <20260821154220.dfba955a79df3449c6e7dd76@linux-foundation.org> (raw)
In-Reply-To: <20260821192627.4085470-1-liam@infradead.org>
On Fri, 21 Aug 2026 15:26:08 -0400 "Liam R. Howlett (Oracle)" <liam@infradead.org> wrote:
> In this series:
> 1. Try to detect lock issues
> A number of syzbot reports are incorrectly pointing to the mm exit as
> a source of the locking error. The first three patches attempt to
> help users detect errors in their locking - but they still have to use
> LOCKDEP. I guess it's still down to hope and prayers.
>
> 2. Documentation fixes
> The documentation was lacking clarity, there are updates to try and
> help the users, especially around the erase() cases.
>
> 3. Two benign issues
> The cyclic allocator may have a race, although no in-kernel user can
> hit it.
> The erase functions may cause allocation issues if used with the
> incorrect locking type, but none are present in-tree.
>
> 4. The erase gfp uses
> mas_erase() and mtree_erase() do not take a gfp argument. To improve
> reliability of the erase, the first attempt to allocate will be
> GFP_NOWAIT, followed by a retry (if necessary of GFP_KERNEL |
> GFP_NOFAIL. This will ensure the data is gone. I've updated the
> documentation to make it more clear as well. mas_store() is not
> addressed in the same way, but may need to be updated at a later date,
> but that may require changing callers so it is out of scope here.
>
> Beyond these goals there are some test fixes, some general speed-up
> patches targeting extra work and cycles, and dropping dead code.
Thanks, I updated mm.git's mm-unstable branch to this version.
I added a -fix for [13/19], per your discussion with Jason:
--- a/Documentation/core-api/maple_tree.rst~maple_tree-document-erase-and-allocations-better-fix
+++ a/Documentation/core-api/maple_tree.rst
@@ -75,7 +75,8 @@ given index. You can use mtree_erase()
knowing one value within that range, or mtree_store() call with an entry of
NULL may be used to partially erase a range or many ranges at once. Note that
mtree_erase() may use GFP_KERNEL | __GFP_NOFAIL for allocations and cannot
-fail, but may need to sleep - do not use mtree_erase() from a blocking context.
+fail. mtree_erase() can sleep, so it must not be called from an atomic
+context.
If you want to only store a new entry to a range (or index) if that range is
currently ``NULL``, you can use mtree_insert_range() or mtree_insert() which
_
Sashiko said a few things which I think are new since v2.
https://sashiko.dev/#/patchset/20260821192627.4085470-1-liam@infradead.org
> Changes since v2:
> - Added a mas_nomem_nofail() function for mas_erase() - Thanks Jason,
> Vlastimil, and Pedro.
> - Dropped the WARN_ON() that was triggered by syzbot and questioned by
> Andrew - Thanks Andrew (and the syzbot)
Here's how v3 altered mm.git:
Documentation/core-api/maple_tree.rst | 9 ++-
include/linux/maple_tree.h | 2
lib/maple_tree.c | 65 ++++++++++++++++--------
3 files changed, 53 insertions(+), 23 deletions(-)
--- a/Documentation/core-api/maple_tree.rst~b
+++ a/Documentation/core-api/maple_tree.rst
@@ -74,7 +74,9 @@ but takes a range. mtree_load() is used
given index. You can use mtree_erase() to erase an entire range by only
knowing one value within that range, or mtree_store() call with an entry of
NULL may be used to partially erase a range or many ranges at once. Note that
-mtree_erase() may use GFP_KERNEL on allocations.
+mtree_erase() may use GFP_KERNEL | __GFP_NOFAIL for allocations and cannot
+fail. mtree_erase() can sleep, so it must not be called from an atomic
+context.
If you want to only store a new entry to a range (or index) if that range is
currently ``NULL``, you can use mtree_insert_range() or mtree_insert() which
@@ -174,8 +176,9 @@ You can use mas_erase() to erase an enti
last of the maple state to the desired range to erase. This will erase
the first range that is found in that range, set the maple state index
and last as the range that was erased and return the entry that existed
-at that location. Note that mas_erase() may allocate with the GFP_KERNEL flag.
-If this is not okay, consider using mas_store_gfp() and pass it a ``NULL``,
+at that location. Note that mas_erase() may allocate with the GFP_KERNEL
+__GFP_NOFAIL and cannot fail, but may sleep. If this is not okay, consider
+using mas_store_gfp() and pass it a ``NULL``,
after setting up the correct range by walking to the entry.
You can walk each entry within a range by using mas_for_each(). If you want
--- a/include/linux/maple_tree.h~b
+++ a/include/linux/maple_tree.h
@@ -570,6 +570,8 @@ int mas_alloc_cyclic(struct ma_state *ma
unsigned long *next, gfp_t gfp);
bool mas_nomem(struct ma_state *mas, gfp_t gfp);
+bool mas_nomem_nofail(struct ma_state *mas, unsigned long index,
+ unsigned long last);
void mas_pause(struct ma_state *mas);
void maple_tree_init(void);
void mas_destroy(struct ma_state *mas);
--- a/lib/maple_tree.c~b
+++ a/lib/maple_tree.c
@@ -5669,9 +5669,10 @@ EXPORT_SYMBOL_GPL(mas_find_range_rev);
* Searches for @mas->index, sets @mas->index and @mas->last to the range and
* erases that range.
*
- * Note that erase requires allocations and will use GFP_KERNEL to do so if
- * necessary. If the allocation fails, the internal lock will be dropped to
- * retry.
+ * Note that erase requires allocations and will use GFP_KERNEL | __GFP_NOFAIL
+ * to do so if necessary. If the allocation fails, the internal lock will be
+ * dropped to retry. An externally locked tree must be protected by a lock that
+ * allows blocking for this API.
*
* Return: the entry that was erased or %NULL, @mas->index and @mas->last are updated.
*/
@@ -5683,8 +5684,8 @@ void *mas_erase(struct ma_state *mas)
/*
* In low memory situations, the allocation is retried with the gfp flag
- * GFP_KERNEL. The internal spinlock is dropped in mas_nomem(), however
- * the external lock is not dropped.
+ * GFP_KERNEL | __GFP_NOFAIL. The internal spinlock is dropped in
+ * mas_nomem_nofail(), however the external lock is not dropped.
*/
if (mt_external_lock(mas->tree))
might_alloc(GFP_KERNEL);
@@ -5698,16 +5699,8 @@ write_retry:
/* 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)) {
- /* in case the range of entry changed when unlocked */
- mas->index = mas->last = index;
+ if (mas_nomem_nofail(mas, index, index))
goto write_retry;
- }
-
- if (mas_is_err(mas)) {
- entry = NULL;
- goto out;
- }
mas_wr_store_entry(&wr_mas);
out:
@@ -5746,16 +5739,48 @@ bool mas_nomem(struct ma_state *mas, gfp
* Return false on zero forward progress. Partial allocations are kept
* 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.
+ * external lock with a non-blocking gfp in a low memory situation.
*/
- if (WARN_ON_ONCE(!mas->sheaf && !mas->alloc))
+ if (!mas->sheaf && !mas->alloc)
return false;
mas_reset(mas);
return true;
}
+/**
+ * mas_nomem_nofail() - Retry allocations with __GFP_NOFAIL, if the maple state
+ * has stored the -ENOMEM error.
+ * @mas: The maple state
+ * @index: The start of the range for the @mas reset
+ * @last: The end of the range for the @mas reset
+ *
+ * Return: false if @mas isn't in an -ENOMEM state. True if the allocation
+ * happens, the state is reset. The internal lock will be dropped and external
+ * locks must allow blocking.
+ */
+bool mas_nomem_nofail(struct ma_state *mas, unsigned long index,
+ unsigned long last)
+ __must_hold(mas->tree->ma_lock)
+{
+ gfp_t gfp;
+
+ if (likely(mas->node != MA_ERROR(-ENOMEM)))
+ return false;
+
+ gfp = GFP_KERNEL | __GFP_NOFAIL;
+ if (!mt_external_lock(mas->tree)) {
+ mtree_unlock(mas->tree);
+ mas_alloc_nodes(mas, gfp);
+ mtree_lock(mas->tree);
+ } else {
+ mas_alloc_nodes(mas, gfp);
+ }
+
+ mas_set_range(mas, index, last);
+ return true;
+}
+
void __init maple_tree_init(void)
{
struct kmem_cache_args args = {
@@ -6042,9 +6067,9 @@ EXPORT_SYMBOL(mtree_alloc_rrange);
* Erasing is the same as a walk to an entry then a store of a NULL to that
* ENTIRE range. In fact, it is implemented as such using the advanced API.
*
- * Note that erase requires allocations and will use GFP_KERNEL to do so if
- * necessary. If the allocation fails, the internal lock will be dropped to
- * retry.
+ * Note that erase requires allocations and will use GFP_KERNEL | __GFP_NOFAIL
+ * to do so if necessary. If the allocation fails, the internal lock will be
+ * dropped to retry.
*
* Return: The entry stored at the @index or %NULL
*/
_
prev parent reply other threads:[~2026-08-21 22:42 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-21 19:26 [PATCH v3 00/19] maple_tree: lock checking and clean ups Liam R. Howlett (Oracle)
2026-08-21 19:26 ` [PATCH v3 01/19] maple_tree: Add rcu locking check when LOCKDEP is enabled Liam R. Howlett (Oracle)
2026-08-21 19:26 ` [PATCH v3 02/19] locking/lockdep: Add sequence counter to held_lock Liam R. Howlett (Oracle)
2026-08-21 19:26 ` [PATCH v3 03/19] maple_tree: Add write lock checking with lockdep sequence numbers Liam R. Howlett (Oracle)
2026-08-21 19:26 ` [PATCH v3 04/19] maple_tree: Documentation fix Liam R. Howlett (Oracle)
2026-08-21 19:26 ` [PATCH v3 05/19] maple_tree: Drop dead code from mas_extend_spanning_null() Liam R. Howlett (Oracle)
2026-08-21 19:26 ` [PATCH v3 06/19] maple_tree: Drop MAPLE_ALLOC_SLOTS Liam R. Howlett (Oracle)
2026-08-21 19:26 ` [PATCH v3 07/19] maple_tree: Clarify comments on mas_nomem() Liam R. Howlett (Oracle)
2026-08-21 19:26 ` [PATCH v3 08/19] maple_tree: Use prefetched value in mas_wr_store_type() Liam R. Howlett (Oracle)
2026-08-21 19:26 ` [PATCH v3 09/19] maple_tree: Optimise mas_wr_node_store() when not in rcu mode Liam R. Howlett (Oracle)
2026-08-21 19:26 ` [PATCH v3 10/19] maple_tree: micro optimisation of mas_wr_store_type() Liam R. Howlett (Oracle)
2026-08-21 19:26 ` [PATCH v3 11/19] maple_tree: Add bulk parent set helper Liam R. Howlett (Oracle)
2026-08-21 19:26 ` [PATCH v3 12/19] maple_tree: Catch race in mas_alloc_cyclic() Liam R. Howlett (Oracle)
2026-08-21 19:26 ` [PATCH v3 13/19] maple_tree: Document that erase may use GFP_KERNEL for allocations Liam R. Howlett (Oracle)
2026-08-21 19:33 ` Rik van Riel
2026-08-21 19:26 ` [PATCH v3 14/19] maple_tree: Avoid mas_erase() and mtree_erase() failures Liam R. Howlett (Oracle)
2026-08-21 19:26 ` [PATCH v3 15/19] maple_tree: Document erase and allocations better Liam R. Howlett (Oracle)
2026-08-21 19:34 ` Rik van Riel
2026-08-21 20:37 ` Liam R. Howlett (Oracle)
2026-08-21 21:55 ` Jason Gunthorpe
2026-08-21 19:26 ` [PATCH v3 16/19] maple_tree: Change two GFP flags in tests Liam R. Howlett (Oracle)
2026-08-21 19:26 ` [PATCH v3 17/19] maple_tree: Fix argument name in header Liam R. Howlett (Oracle)
2026-08-21 19:26 ` [PATCH v3 18/19] maple_tree: Avoid extra gap calculation Liam R. Howlett (Oracle)
2026-08-21 19:26 ` [PATCH v3 19/19] maple_tree: Add helper mas_make_walkable() Liam R. Howlett (Oracle)
2026-08-21 19:40 ` [PATCH v3 00/19] maple_tree: lock checking and clean ups Liam R. Howlett (Oracle)
2026-08-21 22:42 ` Andrew Morton [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260821154220.dfba955a79df3449c6e7dd76@linux-foundation.org \
--to=akpm@linux-foundation.org \
--cc=liam@infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-mm@kvack.org \
--cc=maple-tree@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox