* [PATCH] mm: filemap: tighten dropbehind completion context check
@ 2026-08-20 14:29 Wenjie Qi
2026-08-20 14:34 ` Matthew Wilcox
` (2 more replies)
0 siblings, 3 replies; 19+ messages in thread
From: Wenjie Qi @ 2026-08-20 14:29 UTC (permalink / raw)
To: akpm
Cc: willy, jack, linux-fsdevel, linux-mm, linux-kernel, baohua, Wenjie Qi
folio_end_dropbehind() uses in_task() to keep folio invalidation out of
interrupt context. Task context alone is not sufficient: preemption can
still be disabled, or the task can be in a preemptible RCU read-side
critical section, while filemap_end_dropbehind() may reach
folio_unmap_invalidate() and sleep.
Use the established conservative three-part atomic-context test: reject
preemptible RCU read-side sections, reject configurations without
PREEMPT_COUNT, and otherwise require a preemptible context. Unsafe
completions retain the existing best-effort behavior and skip invalidation.
Signed-off-by: Wenjie Qi <qiwenjie@xiaomi.com>
---
mm/filemap.c | 19 ++++++++++++++-----
1 file changed, 14 insertions(+), 5 deletions(-)
diff --git a/mm/filemap.c b/mm/filemap.c
index 6afec6368..0616057e6 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -45,6 +45,7 @@
#include <linux/migrate.h>
#include <linux/pipe_fs_i.h>
#include <linux/splice.h>
+#include <linux/rcupdate.h>
#include <linux/rcupdate_wait.h>
#include <linux/sched/mm.h>
#include <linux/sysctl.h>
@@ -1620,6 +1621,15 @@ static void filemap_end_dropbehind(struct folio *folio)
folio_unmap_invalidate(mapping, folio, 0);
}
+static bool folio_dropbehind_in_atomic(void)
+{
+ if (IS_ENABLED(CONFIG_PREEMPTION) && rcu_preempt_depth())
+ return true;
+ if (!IS_ENABLED(CONFIG_PREEMPT_COUNT))
+ return true;
+ return !preemptible();
+}
+
/*
* If folio was marked as dropbehind, then pages should be dropped when writeback
* completes. Do that now. If we fail, it's likely because of a big folio -
@@ -1631,13 +1641,12 @@ void folio_end_dropbehind(struct folio *folio)
return;
/*
- * Hitting !in_task() should not happen off RWF_DONTCACHE writeback,
- * but can happen if normal writeback just happens to find dirty folios
- * that were created as part of uncached writeback, and that writeback
- * would otherwise not need non-IRQ handling. Just skip the
+ * Hitting an atomic context should not happen from RWF_DONTCACHE
+ * writeback, but can happen if normal writeback just happens to find
+ * dirty folios created as part of uncached writeback. Just skip the
* invalidation in that case.
*/
- if (in_task() && folio_trylock(folio)) {
+ if (!folio_dropbehind_in_atomic() && folio_trylock(folio)) {
filemap_end_dropbehind(folio);
folio_unlock(folio);
}
--
2.43.0
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH] mm: filemap: tighten dropbehind completion context check
2026-08-20 14:29 [PATCH] mm: filemap: tighten dropbehind completion context check Wenjie Qi
@ 2026-08-20 14:34 ` Matthew Wilcox
2026-08-21 1:23 ` Wenjie Qi
2026-08-29 1:10 ` Andrew Morton
2026-08-29 12:30 ` [PATCH v2] mm: filemap: retain mapped dropbehind folios Wenjie Qi
2 siblings, 1 reply; 19+ messages in thread
From: Matthew Wilcox @ 2026-08-20 14:34 UTC (permalink / raw)
To: Wenjie Qi
Cc: akpm, jack, linux-fsdevel, linux-mm, linux-kernel, baohua, Wenjie Qi
On Thu, Aug 20, 2026 at 10:29:56PM +0800, Wenjie Qi wrote:
> folio_end_dropbehind() uses in_task() to keep folio invalidation out of
> interrupt context. Task context alone is not sufficient: preemption can
> still be disabled, or the task can be in a preemptible RCU read-side
> critical section, while filemap_end_dropbehind() may reach
> folio_unmap_invalidate() and sleep.
>
> Use the established conservative three-part atomic-context test: reject
> preemptible RCU read-side sections, reject configurations without
> PREEMPT_COUNT, and otherwise require a preemptible context. Unsafe
> completions retain the existing best-effort behavior and skip invalidation.
Have you seen this happen in practice, or is this based on code
examination?
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH] mm: filemap: tighten dropbehind completion context check
2026-08-20 14:34 ` Matthew Wilcox
@ 2026-08-21 1:23 ` Wenjie Qi
2026-08-21 3:30 ` Matthew Wilcox
0 siblings, 1 reply; 19+ messages in thread
From: Wenjie Qi @ 2026-08-21 1:23 UTC (permalink / raw)
To: Matthew Wilcox
Cc: akpm, jack, linux-fsdevel, linux-mm, linux-kernel, baohua, Wenjie Qi
This is based on code examination; I have not reproduced it in
folio_end_dropbehind().
There is an analogous EROFS report where bio completion ran under an RCU
read-side critical section and hit a sleeping-function warning even though
in_atomic() and preempt_count were both zero:
https://lore.kernel.org/r/20230621220848.3379029-1-dhavale@google.com
That is not a reproducer for this path, but it shows why task context alone
does not establish that sleeping is safe. Here, folio_unmap_invalidate() can
reach unmap_mapping_folio(), which takes mapping->i_mmap_rwsem through
i_mmap_lock_read(). I noticed the mismatch while comparing this path with
the stricter bio_in_atomic() check used by the block dropbehind work.
On Thu, Aug 20, 2026 at 10:34 PM Matthew Wilcox <willy@infradead.org> wrote:
>
> On Thu, Aug 20, 2026 at 10:29:56PM +0800, Wenjie Qi wrote:
> > folio_end_dropbehind() uses in_task() to keep folio invalidation out of
> > interrupt context. Task context alone is not sufficient: preemption can
> > still be disabled, or the task can be in a preemptible RCU read-side
> > critical section, while filemap_end_dropbehind() may reach
> > folio_unmap_invalidate() and sleep.
> >
> > Use the established conservative three-part atomic-context test: reject
> > preemptible RCU read-side sections, reject configurations without
> > PREEMPT_COUNT, and otherwise require a preemptible context. Unsafe
> > completions retain the existing best-effort behavior and skip invalidation.
>
> Have you seen this happen in practice, or is this based on code
> examination?
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH] mm: filemap: tighten dropbehind completion context check
2026-08-21 1:23 ` Wenjie Qi
@ 2026-08-21 3:30 ` Matthew Wilcox
2026-08-24 13:34 ` Wenjie Qi
0 siblings, 1 reply; 19+ messages in thread
From: Matthew Wilcox @ 2026-08-21 3:30 UTC (permalink / raw)
To: Wenjie Qi
Cc: akpm, jack, linux-fsdevel, linux-mm, linux-kernel, baohua, Wenjie Qi
On Fri, Aug 21, 2026 at 09:23:12AM +0800, Wenjie Qi wrote:
> This is based on code examination; I have not reproduced it in
> folio_end_dropbehind().
> There is an analogous EROFS report where bio completion ran under an RCU
> read-side critical section and hit a sleeping-function warning even though
> in_atomic() and preempt_count were both zero:
>
> https://lore.kernel.org/r/20230621220848.3379029-1-dhavale@google.com
>
> That is not a reproducer for this path, but it shows why task context alone
> does not establish that sleeping is safe. Here, folio_unmap_invalidate() can
> reach unmap_mapping_folio(), which takes mapping->i_mmap_rwsem through
> i_mmap_lock_read(). I noticed the mismatch while comparing this path with
> the stricter bio_in_atomic() check used by the block dropbehind work.
So your analysis is right as far as it goes. But if a folio has
been marked as dropbehind, but was then mmaped, we clearly shouldn't
be discarding it! I believe that we'll clear the dropbehind flag in
__filemap_get_folio_mpol(), called from filemap_get_folio() called from
filemap_fault().
If you can find a way to get a folio with both dropbehind & mapped set,
I'm interested in hearing how.
> On Thu, Aug 20, 2026 at 10:34 PM Matthew Wilcox <willy@infradead.org> wrote:
> >
> > On Thu, Aug 20, 2026 at 10:29:56PM +0800, Wenjie Qi wrote:
> > > folio_end_dropbehind() uses in_task() to keep folio invalidation out of
> > > interrupt context. Task context alone is not sufficient: preemption can
> > > still be disabled, or the task can be in a preemptible RCU read-side
> > > critical section, while filemap_end_dropbehind() may reach
> > > folio_unmap_invalidate() and sleep.
> > >
> > > Use the established conservative three-part atomic-context test: reject
> > > preemptible RCU read-side sections, reject configurations without
> > > PREEMPT_COUNT, and otherwise require a preemptible context. Unsafe
> > > completions retain the existing best-effort behavior and skip invalidation.
> >
> > Have you seen this happen in practice, or is this based on code
> > examination?
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH] mm: filemap: tighten dropbehind completion context check
2026-08-21 3:30 ` Matthew Wilcox
@ 2026-08-24 13:34 ` Wenjie Qi
0 siblings, 0 replies; 19+ messages in thread
From: Wenjie Qi @ 2026-08-24 13:34 UTC (permalink / raw)
To: Matthew Wilcox
Cc: akpm, jack, linux-fsdevel, linux-mm, linux-kernel, baohua, Wenjie Qi
I think fault-around provides such a path.
do_read_fault() calls do_fault_around() before ->fault. For generic file
mappings this reaches filemap_map_pages(), which walks mapping->i_pages
directly and maps ready folios without going through
__filemap_get_folio_mpol(). It does not clear dropbehind or exclude dirty
or writeback folios.
If the mapped PTE range covers vmf->address, filemap_map_pages() returns
VM_FAULT_NOPAGE, so do_read_fault() does not fall back to filemap_fault().
Both the faulting folio and speculative neighboring folios can therefore be
mapped while retaining dropbehind.
A fault-around PTE does not necessarily mean that every mapped folio was
accessed, since neighboring folios are mapped speculatively. So I do not
think folio_mapped() alone is sufficient to cancel dropbehind. Clearing it
for the folio covering vmf->address may be more precise, but that would be a
separate semantic change.
If this distinction makes sense, I can send an RFC to clear dropbehind for
the faulting folio in filemap_map_pages().
On Fri, Aug 21, 2026 at 11:30 AM Matthew Wilcox <willy@infradead.org> wrote:
>
> On Fri, Aug 21, 2026 at 09:23:12AM +0800, Wenjie Qi wrote:
> > This is based on code examination; I have not reproduced it in
> > folio_end_dropbehind().
> > There is an analogous EROFS report where bio completion ran under an RCU
> > read-side critical section and hit a sleeping-function warning even though
> > in_atomic() and preempt_count were both zero:
> >
> > https://lore.kernel.org/r/20230621220848.3379029-1-dhavale@google.com
> >
> > That is not a reproducer for this path, but it shows why task context alone
> > does not establish that sleeping is safe. Here, folio_unmap_invalidate() can
> > reach unmap_mapping_folio(), which takes mapping->i_mmap_rwsem through
> > i_mmap_lock_read(). I noticed the mismatch while comparing this path with
> > the stricter bio_in_atomic() check used by the block dropbehind work.
>
> So your analysis is right as far as it goes. But if a folio has
> been marked as dropbehind, but was then mmaped, we clearly shouldn't
> be discarding it! I believe that we'll clear the dropbehind flag in
> __filemap_get_folio_mpol(), called from filemap_get_folio() called from
> filemap_fault().
>
> If you can find a way to get a folio with both dropbehind & mapped set,
> I'm interested in hearing how.
>
> > On Thu, Aug 20, 2026 at 10:34 PM Matthew Wilcox <willy@infradead.org> wrote:
> > >
> > > On Thu, Aug 20, 2026 at 10:29:56PM +0800, Wenjie Qi wrote:
> > > > folio_end_dropbehind() uses in_task() to keep folio invalidation out of
> > > > interrupt context. Task context alone is not sufficient: preemption can
> > > > still be disabled, or the task can be in a preemptible RCU read-side
> > > > critical section, while filemap_end_dropbehind() may reach
> > > > folio_unmap_invalidate() and sleep.
> > > >
> > > > Use the established conservative three-part atomic-context test: reject
> > > > preemptible RCU read-side sections, reject configurations without
> > > > PREEMPT_COUNT, and otherwise require a preemptible context. Unsafe
> > > > completions retain the existing best-effort behavior and skip invalidation.
> > >
> > > Have you seen this happen in practice, or is this based on code
> > > examination?
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH] mm: filemap: tighten dropbehind completion context check
2026-08-20 14:29 [PATCH] mm: filemap: tighten dropbehind completion context check Wenjie Qi
2026-08-20 14:34 ` Matthew Wilcox
@ 2026-08-29 1:10 ` Andrew Morton
2026-08-29 12:13 ` Wenjie Qi
2026-08-29 12:30 ` [PATCH v2] mm: filemap: retain mapped dropbehind folios Wenjie Qi
2 siblings, 1 reply; 19+ messages in thread
From: Andrew Morton @ 2026-08-29 1:10 UTC (permalink / raw)
To: Wenjie Qi
Cc: willy, jack, linux-fsdevel, linux-mm, linux-kernel, baohua, Wenjie Qi
On Thu, 20 Aug 2026 22:29:56 +0800 Wenjie Qi <qwjhust@gmail.com> wrote:
> folio_end_dropbehind() uses in_task() to keep folio invalidation out of
> interrupt context. Task context alone is not sufficient: preemption can
> still be disabled, or the task can be in a preemptible RCU read-side
> critical section, while filemap_end_dropbehind() may reach
> folio_unmap_invalidate() and sleep.
>
> Use the established conservative three-part atomic-context test: reject
> preemptible RCU read-side sections, reject configurations without
> PREEMPT_COUNT, and otherwise require a preemptible context. Unsafe
> completions retain the existing best-effort behavior and skip invalidation.
>
> ...
>
> +static bool folio_dropbehind_in_atomic(void)
> +{
> + if (IS_ENABLED(CONFIG_PREEMPTION) && rcu_preempt_depth())
> + return true;
> + if (!IS_ENABLED(CONFIG_PREEMPT_COUNT))
> + return true;
> + return !preemptible();
> +}
Cripes.
There's nothing mm-specific about this function. If we have a use-case
for such a thing then surely the function should be kernel-wide, it
should live at the sched/rcu/etc layer and it should be elaborately
documented?
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH] mm: filemap: tighten dropbehind completion context check
2026-08-29 1:10 ` Andrew Morton
@ 2026-08-29 12:13 ` Wenjie Qi
2026-08-30 8:45 ` Barry Song
0 siblings, 1 reply; 19+ messages in thread
From: Wenjie Qi @ 2026-08-29 12:13 UTC (permalink / raw)
To: akpm; +Cc: willy, jack, linux-fsdevel, linux-mm, linux-kernel, baohua, qiwenjie
I kept the helper private to avoid an MM dependency on <linux/bio.h>.
After looking further at the mapped-folio case Matthew raised, I think the
better fix is to retain a dropbehind folio once it is mapped. A mapping
represents a competing cached user, and retaining it avoids the sleeping
unmap path, so filemap no longer needs a stricter context helper; the
existing in_task() guard remains. I will respin the patch on that basis.
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v2] mm: filemap: retain mapped dropbehind folios
2026-08-20 14:29 [PATCH] mm: filemap: tighten dropbehind completion context check Wenjie Qi
2026-08-20 14:34 ` Matthew Wilcox
2026-08-29 1:10 ` Andrew Morton
@ 2026-08-29 12:30 ` Wenjie Qi
2026-08-29 14:47 ` Matthew Wilcox
` (2 more replies)
2 siblings, 3 replies; 19+ messages in thread
From: Wenjie Qi @ 2026-08-29 12:30 UTC (permalink / raw)
To: willy, jack, akpm
Cc: linux-fsdevel, linux-mm, linux-kernel, baohua, axboe,
trond.myklebust, qiwenjie, qwjhust
From: Wenjie Qi <qiwenjie@xiaomi.com>
Fault-around can map ready dropbehind folios without going through the
normal page-cache lookup that clears dropbehind. A mapping represents a
competing cached user, so retain the folio instead of forcibly unmapping it
when writeback completes.
Unmapped dropbehind folios continue through the existing invalidation path.
Signed-off-by: Wenjie Qi <qiwenjie@xiaomi.com>
---
Changes since v1:
- Retain mapped folios instead of adding a stricter context predicate.
- Remove the private helper and RCU include.
mm/filemap.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mm/filemap.c b/mm/filemap.c
index 6afec636881f..00fd89cf6f55 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1616,7 +1616,7 @@ static void filemap_end_dropbehind(struct folio *folio)
return;
if (!folio_test_clear_dropbehind(folio))
return;
- if (mapping)
+ if (mapping && !folio_mapped(folio))
folio_unmap_invalidate(mapping, folio, 0);
}
--
2.43.0
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2] mm: filemap: retain mapped dropbehind folios
2026-08-29 12:30 ` [PATCH v2] mm: filemap: retain mapped dropbehind folios Wenjie Qi
@ 2026-08-29 14:47 ` Matthew Wilcox
2026-08-29 15:53 ` Tal Zussman
2026-08-29 17:36 ` [PATCH v3] " Wenjie Qi
2 siblings, 0 replies; 19+ messages in thread
From: Matthew Wilcox @ 2026-08-29 14:47 UTC (permalink / raw)
To: Wenjie Qi
Cc: jack, akpm, linux-fsdevel, linux-mm, linux-kernel, baohua, axboe,
trond.myklebust, qiwenjie
On Sat, Aug 29, 2026 at 08:30:47PM +0800, Wenjie Qi wrote:
> From: Wenjie Qi <qiwenjie@xiaomi.com>
>
> Fault-around can map ready dropbehind folios without going through the
> normal page-cache lookup that clears dropbehind. A mapping represents a
> competing cached user, so retain the folio instead of forcibly unmapping it
> when writeback completes.
>
> Unmapped dropbehind folios continue through the existing invalidation path.
Yes, I think this is the right approach.
Reviewed-by: Matthew Wilcox (Oracle) <willy@infradead.org>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2] mm: filemap: retain mapped dropbehind folios
2026-08-29 12:30 ` [PATCH v2] mm: filemap: retain mapped dropbehind folios Wenjie Qi
2026-08-29 14:47 ` Matthew Wilcox
@ 2026-08-29 15:53 ` Tal Zussman
2026-08-29 16:09 ` Tal Zussman
2026-08-29 17:36 ` [PATCH v3] " Wenjie Qi
2 siblings, 1 reply; 19+ messages in thread
From: Tal Zussman @ 2026-08-29 15:53 UTC (permalink / raw)
To: Wenjie Qi
Cc: willy, jack, akpm, linux-fsdevel, linux-mm, linux-kernel, baohua,
axboe, trond.myklebust, qiwenjie
On Sat, 29 Aug 2026 20:30:47 +0800, Wenjie Qi <qwjhust@gmail.com> wrote:
> Fault-around can map ready dropbehind folios without going through the
> normal page-cache lookup that clears dropbehind. A mapping represents a
> competing cached user, so retain the folio instead of forcibly unmapping it
> when writeback completes.
>
> Unmapped dropbehind folios continue through the existing invalidation path.
>
> Signed-off-by: Wenjie Qi <qiwenjie@xiaomi.com>
Overall looks good to me. It may be nice to add a sentence about the
safety aspect of this in the commit message. Maybe something like:
folio_unmap_invalidate() may sleep if the folio is mapped, so this
also ensures that folio_end_dropbehind() is safe to call from
non-preemptible task context.
Reviewed-by: Tal Zussman <tz2294@columbia.edu>
--
Tal Zussman <tz2294@columbia.edu>
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v2] mm: filemap: retain mapped dropbehind folios
2026-08-29 15:53 ` Tal Zussman
@ 2026-08-29 16:09 ` Tal Zussman
0 siblings, 0 replies; 19+ messages in thread
From: Tal Zussman @ 2026-08-29 16:09 UTC (permalink / raw)
To: Wenjie Qi
Cc: willy, jack, akpm, linux-fsdevel, linux-mm, linux-kernel, baohua,
axboe, trond.myklebust, qiwenjie
On 8/29/26 6:53 PM, Tal Zussman wrote:
> On Sat, 29 Aug 2026 20:30:47 +0800, Wenjie Qi <qwjhust@gmail.com> wrote:
>> Fault-around can map ready dropbehind folios without going through the
>> normal page-cache lookup that clears dropbehind. A mapping represents a
>> competing cached user, so retain the folio instead of forcibly unmapping it
>> when writeback completes.
>>
>> Unmapped dropbehind folios continue through the existing invalidation path.
>>
>> Signed-off-by: Wenjie Qi <qiwenjie@xiaomi.com>
>
> Overall looks good to me. It may be nice to add a sentence about the
> safety aspect of this in the commit message. Maybe something like:
>
> folio_unmap_invalidate() may sleep if the folio is mapped, so this
> also ensures that folio_end_dropbehind() is safe to call from
> non-preemptible task context.
>
> Reviewed-by: Tal Zussman <tz2294@columbia.edu>
>
And maybe:
Fixes: fb7d3bc41493 ("mm/filemap: drop streaming/uncached pages when writeback completes")
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v3] mm: filemap: retain mapped dropbehind folios
2026-08-29 12:30 ` [PATCH v2] mm: filemap: retain mapped dropbehind folios Wenjie Qi
2026-08-29 14:47 ` Matthew Wilcox
2026-08-29 15:53 ` Tal Zussman
@ 2026-08-29 17:36 ` Wenjie Qi
2026-08-29 18:16 ` Andrew Morton
2 siblings, 1 reply; 19+ messages in thread
From: Wenjie Qi @ 2026-08-29 17:36 UTC (permalink / raw)
To: willy, jack, akpm
Cc: linux-fsdevel, linux-mm, linux-kernel, baohua, axboe,
trond.myklebust, tz2294, qiwenjie, qwjhust
From: Wenjie Qi <qiwenjie@xiaomi.com>
Fault-around can map ready dropbehind folios without going through the
normal page-cache lookup that clears dropbehind. A mapping represents a
competing cached user, so retain the folio instead of forcibly unmapping it
when writeback completes.
For a mapped folio, folio_unmap_invalidate() can call
unmap_mapping_folio(), which takes i_mmap_rwsem and may sleep. Retaining
mapped folios avoids this path when folio_end_dropbehind() runs in
non-preemptible task context.
Unmapped dropbehind folios continue through the existing invalidation path.
Fixes: fb7d3bc41493 ("mm/filemap: drop streaming/uncached pages when writeback completes")
Signed-off-by: Wenjie Qi <qiwenjie@xiaomi.com>
Reviewed-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: Tal Zussman <tz2294@columbia.edu>
---
Changes since v2:
- Explain why retaining mapped folios avoids a sleepable unmap path.
- Add the Fixes and Reviewed-by trailers.
mm/filemap.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mm/filemap.c b/mm/filemap.c
index 6afec636881f..00fd89cf6f55 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1616,7 +1616,7 @@ static void filemap_end_dropbehind(struct folio *folio)
return;
if (!folio_test_clear_dropbehind(folio))
return;
- if (mapping)
+ if (mapping && !folio_mapped(folio))
folio_unmap_invalidate(mapping, folio, 0);
}
--
2.43.0
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v3] mm: filemap: retain mapped dropbehind folios
2026-08-29 17:36 ` [PATCH v3] " Wenjie Qi
@ 2026-08-29 18:16 ` Andrew Morton
2026-08-30 3:25 ` [PATCH v4] " Wenjie Qi
0 siblings, 1 reply; 19+ messages in thread
From: Andrew Morton @ 2026-08-29 18:16 UTC (permalink / raw)
To: Wenjie Qi
Cc: willy, jack, linux-fsdevel, linux-mm, linux-kernel, baohua,
axboe, trond.myklebust, tz2294, qiwenjie
On Sun, 30 Aug 2026 01:36:12 +0800 Wenjie Qi <qwjhust@gmail.com> wrote:
> From: Wenjie Qi <qiwenjie@xiaomi.com>
>
> Fault-around can map ready dropbehind folios without going through the
> normal page-cache lookup that clears dropbehind. A mapping represents a
> competing cached user, so retain the folio instead of forcibly unmapping it
> when writeback completes.
>
> For a mapped folio, folio_unmap_invalidate() can call
> unmap_mapping_folio(), which takes i_mmap_rwsem and may sleep. Retaining
> mapped folios avoids this path when folio_end_dropbehind() runs in
> non-preemptible task context.
>
> Unmapped dropbehind folios continue through the existing invalidation path.
Thanks.
When fixing a bug, please always provide a very clear description of the
userspace-visible runtime effects of that bug.
From the above it appears that the current code can trigger a
sleeping-in-atomic warning? Has this been observed in any situation?
Is there a report?
chatgpt easily prepared a reproducer for me, which I haven't run.
If I'm correct in the above, we should backport this fix with a
cc:stable tag, do you agree?
^ permalink raw reply [flat|nested] 19+ messages in thread
* [PATCH v4] mm: filemap: retain mapped dropbehind folios
2026-08-29 18:16 ` Andrew Morton
@ 2026-08-30 3:25 ` Wenjie Qi
2026-08-30 8:35 ` Barry Song
2026-08-30 11:58 ` Tal Zussman
0 siblings, 2 replies; 19+ messages in thread
From: Wenjie Qi @ 2026-08-30 3:25 UTC (permalink / raw)
To: willy, jack, akpm
Cc: linux-fsdevel, linux-mm, linux-kernel, stable, baohua, axboe,
trond.myklebust, tz2294, jaegeuk, chao, qiwenjie, qwjhust
From: Wenjie Qi <qiwenjie@xiaomi.com>
Fault-around can map ready dropbehind folios without going through the
normal page-cache lookup that clears dropbehind. A mapping represents a
competing cached user, but writeback completion can currently unmap that
folio. A later mmap access must then fault it back in.
Retain mapped folios instead. For a mapped folio,
folio_unmap_invalidate() can call unmap_mapping_folio(), which takes
i_mmap_rwsem and may sleep. Retaining the folio also avoids this path when
folio_end_dropbehind() runs in non-preemptible task context.
Unmapped dropbehind folios continue through the existing invalidation path.
Fixes: fb7d3bc41493 ("mm/filemap: drop streaming/uncached pages when writeback completes")
Cc: stable@vger.kernel.org
Signed-off-by: Wenjie Qi <qiwenjie@xiaomi.com>
Reviewed-by: Matthew Wilcox (Oracle) <willy@infradead.org>
Reviewed-by: Tal Zussman <tz2294@columbia.edu>
---
The mapped-plus-dropbehind state was reproduced in QEMU. The patched
kernel retained the mapped folio and continued to evict the unmapped
dontcache folio. I did not reproduce the sleeping-in-atomic warning and
am not aware of an existing report.
Changes since v3:
- Describe the forced-unmap/refault runtime effect.
- Record the reproduction boundary and add Cc: stable@vger.kernel.org.
mm/filemap.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mm/filemap.c b/mm/filemap.c
index 6afec636881f..00fd89cf6f55 100644
--- a/mm/filemap.c
+++ b/mm/filemap.c
@@ -1616,7 +1616,7 @@ static void filemap_end_dropbehind(struct folio *folio)
return;
if (!folio_test_clear_dropbehind(folio))
return;
- if (mapping)
+ if (mapping && !folio_mapped(folio))
folio_unmap_invalidate(mapping, folio, 0);
}
--
2.43.0
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v4] mm: filemap: retain mapped dropbehind folios
2026-08-30 3:25 ` [PATCH v4] " Wenjie Qi
@ 2026-08-30 8:35 ` Barry Song
2026-08-30 9:13 ` Wenjie Qi
2026-08-30 11:58 ` Tal Zussman
1 sibling, 1 reply; 19+ messages in thread
From: Barry Song @ 2026-08-30 8:35 UTC (permalink / raw)
To: Wenjie Qi
Cc: willy, jack, akpm, linux-fsdevel, linux-mm, linux-kernel, stable,
axboe, trond.myklebust, tz2294, jaegeuk, chao, qiwenjie
On Sun, Aug 30, 2026 at 11:25 AM Wenjie Qi <qwjhust@gmail.com> wrote:
>
> From: Wenjie Qi <qiwenjie@xiaomi.com>
>
> Fault-around can map ready dropbehind folios without going through the
> normal page-cache lookup that clears dropbehind. A mapping represents a
> competing cached user, but writeback completion can currently unmap that
> folio. A later mmap access must then fault it back in.
Andrew is asking for a visible user-facing impact. I think the current
mainline code might result in an extra fault-in and extra I/O. Maybe we
should highlight this?
On the other hand, my gut feeling is that this patch might only be
50% right, rather than 100% right.
Fault-around might just end up mapping data that will never be accessed
at all (fault-around mappings aren't really fault-mapped), while the user
has explicitly requested "dropbehind", which seems like a strong hint
that they don't need it :-)
>
> Retain mapped folios instead. For a mapped folio,
> folio_unmap_invalidate() can call unmap_mapping_folio(), which takes
> i_mmap_rwsem and may sleep. Retaining the folio also avoids this path when
> folio_end_dropbehind() runs in non-preemptible task context.
>
I'm not quite sure this can be entirely avoided. Somehow,
`folio_launder(mapping, folio)` could also be nasty. For example, NFS
can still be problematic today:
static int nfs_launder_folio(struct folio *folio)
{
struct inode *inode = folio->mapping->host;
int ret;
dfprintk(PAGECACHE, "NFS: launder_folio(%llu, %llu)\n",
inode->i_ino, folio_pos(folio));
folio_wait_private_2(folio); /* [DEPRECATED] */
ret = nfs_wb_folio(inode, folio);
trace_nfs_launder_folio_done(inode, folio_pos(folio),
folio_size(folio), ret);
return ret;
}
Best Regards
Barry
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH] mm: filemap: tighten dropbehind completion context check
2026-08-29 12:13 ` Wenjie Qi
@ 2026-08-30 8:45 ` Barry Song
0 siblings, 0 replies; 19+ messages in thread
From: Barry Song @ 2026-08-30 8:45 UTC (permalink / raw)
To: Wenjie Qi
Cc: akpm, willy, jack, linux-fsdevel, linux-mm, linux-kernel, qiwenjie
On Sat, Aug 29, 2026 at 8:13 PM Wenjie Qi <qwjhust@gmail.com> wrote:
>
> I kept the helper private to avoid an MM dependency on <linux/bio.h>.
>
> After looking further at the mapped-folio case Matthew raised, I think the
> better fix is to retain a dropbehind folio once it is mapped. A mapping
> represents a competing cached user, and retaining it avoids the sleeping
> unmap path, so filemap no longer needs a stricter context helper; the
> existing in_task() guard remains. I will respin the patch on that basis.
But we still have `bio_in_atomic()` in `include/linux/bio.h`:
/**
* bio_in_atomic - check if the current context is unsafe for bio completion
*
* Return: %true in atomic contexts (e.g. hard/soft IRQ, preempt-disabled);
* %false when a bio can be safely completed in the current context.
*/
static inline bool bio_in_atomic(void)
{
if (IS_ENABLED(CONFIG_PREEMPTION) && rcu_preempt_depth())
return true;
if (!IS_ENABLED(CONFIG_PREEMPT_COUNT))
return true;
return !preemptible();
}
Right now, it's used in three places, and I expect we'll see more users
over time.
1 1925 block/bio.c <<bio_endio>>
if (bio_flagged(bio, BIO_COMPLETE_IN_TASK) && bio_in_atomic())
2 1451 fs/erofs/zdata.c <<z_erofs_decompress_kickoff>>
if (bio_in_atomic()) {
3 403 include/linux/bio.h <<bio_complete_in_task>>
if (!bio_in_atomic())
Yet it really has nothing to do with `bio` at all; it's purely a
scheduler thing!
So I fully agree with Andrew that we should move it to `sched` and
continue the discussion there. Maybe the current `in_atomic()` helpers
aren't really good enough?
Best Regards
Barry
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v4] mm: filemap: retain mapped dropbehind folios
2026-08-30 8:35 ` Barry Song
@ 2026-08-30 9:13 ` Wenjie Qi
2026-08-30 9:31 ` Barry Song
0 siblings, 1 reply; 19+ messages in thread
From: Wenjie Qi @ 2026-08-30 9:13 UTC (permalink / raw)
To: baohua
Cc: willy, jack, akpm, linux-fsdevel, linux-mm, linux-kernel, stable,
axboe, trond.myklebust, tz2294, jaegeuk, chao, qiwenjie, qwjhust
Yes. The current path removes the folio from the page cache, so a later
mmap access can incur both another fault and I/O. I should have stated
that explicitly.
For fault-around neighbors, folio_mapped() cannot distinguish the faulting
page from a speculative neighbor. This patch takes the conservative policy
that an installed PTE represents a competing cache user and wins over the
writer's RWF_DONTCACHE hint. It can therefore retain a speculative neighbor
which is never accessed. Distinguishing those cases seems to require
fault-around to preserve the faulting folio while not mapping, or later
dropping, dropbehind neighbors. I think that should be considered as a
separate follow-up.
For folio_launder(), filemap_end_dropbehind() holds the folio lock and returns
if the folio is dirty or under writeback before calling
folio_unmap_invalidate(). folio_launder() also immediately returns for a
clean folio. I do not see how nfs_launder_folio() is reached from this
completion path unless the locked, unmapped folio can become dirty between
those checks. Is there a path I am missing?
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v4] mm: filemap: retain mapped dropbehind folios
2026-08-30 9:13 ` Wenjie Qi
@ 2026-08-30 9:31 ` Barry Song
0 siblings, 0 replies; 19+ messages in thread
From: Barry Song @ 2026-08-30 9:31 UTC (permalink / raw)
To: Wenjie Qi
Cc: willy, jack, akpm, linux-fsdevel, linux-mm, linux-kernel, stable,
axboe, trond.myklebust, tz2294, jaegeuk, chao, qiwenjie
On Sun, Aug 30, 2026 at 5:13 PM Wenjie Qi <qwjhust@gmail.com> wrote:
>
> Yes. The current path removes the folio from the page cache, so a later
> mmap access can incur both another fault and I/O. I should have stated
> that explicitly.
>
> For fault-around neighbors, folio_mapped() cannot distinguish the faulting
> page from a speculative neighbor. This patch takes the conservative policy
> that an installed PTE represents a competing cache user and wins over the
> writer's RWF_DONTCACHE hint. It can therefore retain a speculative neighbor
> which is never accessed. Distinguishing those cases seems to require
> fault-around to preserve the faulting folio while not mapping, or later
> dropping, dropbehind neighbors. I think that should be considered as a
> separate follow-up.
Yes. Maybe we can skip mapping neighbors with the dropbehind flag in
fault-around.
>
> For folio_launder(), filemap_end_dropbehind() holds the folio lock and returns
> if the folio is dirty or under writeback before calling
> folio_unmap_invalidate(). folio_launder() also immediately returns for a
> clean folio. I do not see how nfs_launder_folio() is reached from this
> completion path unless the locked, unmapped folio can become dirty between
> those checks. Is there a path I am missing?
You are probably right. I was referring to the bit wait in
nfs_launder_folio(), though I'm not quite sure whether this can
actually happen:
folio_wait_private_2(folio); /* [DEPRECATED] */
I assume we won't wait for `private_2` while the folio is clean. If so,
it should be fine.
^ permalink raw reply [flat|nested] 19+ messages in thread
* Re: [PATCH v4] mm: filemap: retain mapped dropbehind folios
2026-08-30 3:25 ` [PATCH v4] " Wenjie Qi
2026-08-30 8:35 ` Barry Song
@ 2026-08-30 11:58 ` Tal Zussman
1 sibling, 0 replies; 19+ messages in thread
From: Tal Zussman @ 2026-08-30 11:58 UTC (permalink / raw)
To: Wenjie Qi, willy, jack, akpm
Cc: linux-fsdevel, linux-mm, linux-kernel, stable, baohua, axboe,
trond.myklebust, jaegeuk, chao, qiwenjie
On 8/30/26 6:25 AM, Wenjie Qi wrote:
> From: Wenjie Qi <qiwenjie@ xiaomi. com> Fault-around can map ready dropbehind
> folios without going through the normal page-cache lookup that clears
> dropbehind. A mapping represents a competing cached user, but writeback
> completion can currently
> ZjQcmQRYFpfptBannerStart
> This Message Is From an External Sender
> This message came from outside your organization.
> ZjQcmQRYFpfptBannerEnd
>
> From: Wenjie Qi <qiwenjie@xiaomi.com>
>
> Fault-around can map ready dropbehind folios without going through the
> normal page-cache lookup that clears dropbehind. A mapping represents a
> competing cached user, but writeback completion can currently unmap that
> folio. A later mmap access must then fault it back in.
>
> Retain mapped folios instead. For a mapped folio,
> folio_unmap_invalidate() can call unmap_mapping_folio(), which takes
> i_mmap_rwsem and may sleep. Retaining the folio also avoids this path when
> folio_end_dropbehind() runs in non-preemptible task context.
>
> Unmapped dropbehind folios continue through the existing invalidation path.
>
> Fixes: fb7d3bc41493 ("mm/filemap: drop streaming/uncached pages when writeback completes")
> Cc: stable@vger.kernel.org
> Signed-off-by: Wenjie Qi <qiwenjie@xiaomi.com>
> Reviewed-by: Matthew Wilcox (Oracle) <willy@infradead.org>
> Reviewed-by: Tal Zussman <tz2294@columbia.edu>
> ---
> The mapped-plus-dropbehind state was reproduced in QEMU. The patched
> kernel retained the mapped folio and continued to evict the unmapped
> dontcache folio. I did not reproduce the sleeping-in-atomic warning and
> am not aware of an existing report.
>
I was able to trigger the sleeping-while-atomic BUG on current mainline with
some help from Claude. The reproducer itself is straightforward enough, but the
configuration was a little finicky. The atomic context comes from using
threadirqs so that virtblk_done() completes requests from the irq thread under
local_bh_disable() and the vq spinlock with irqs off, so in_task() is true but
the i_mmap_rwsem down_read() sleeps. It also needed 1 vCPU (so completion stays
in the irq thread rather than softirq) and ext4 -o dioread_lock (so end_io runs
inline instead of on a workqueue). With v4 applied the bug is gone, so:
Tested-by: Tal Zussman <tz2294@columbia.edu>
Full splat:
[ 46.745106] BUG: sleeping function called from invalid context at kernel/locking/rwsem.c:1573
[ 46.745183] in_atomic(): 1, irqs_disabled(): 1, non_block: 0, pid: 61, name: irq/40-virtio1-
[ 46.745211] preempt_count: 201, expected: 0
[ 46.745233] RCU nest depth: 0, expected: 0
[ 46.745292] locks held by irq/40-virtio1-/61: 1, last CPU#0:
[ 46.745324] #0: ff1fce9901fc2f20 (&vblk->vqs[i].lock){....}-{3:3}, at: virtblk_done+0x56/0x100
[ 46.746801] irq event stamp: 1585
[ 46.748015] hardirqs last enabled at (1583): [<ffffffff88dc7c54>] finish_task_switch.isra.0+0xd4/0x360
[ 46.748224] hardirqs last disabled at (1585): [<ffffffff88e2b16c>] irq_forced_thread_fn+0x5c/0x60
[ 46.748405] softirqs last enabled at (1578): [<ffffffff88e2b159>] irq_forced_thread_fn+0x49/0x60
[ 46.748580] softirqs last disabled at (1584): [<ffffffff88e2b12d>] irq_forced_thread_fn+0x1d/0x60
[ 46.749233] CPU: 0 UID: 0 PID: 61 Comm: irq/40-virtio1- Not tainted 7.2.0+ #5 PREEMPT(full)
[ 46.749323] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[ 46.749472] Call Trace:
[ 46.749552] <TASK>
[ 46.749653] dump_stack_lvl+0x66/0xa0
[ 46.749747] __might_resched+0x154/0x260
[ 46.749787] down_read+0x1e/0x170
[ 46.749806] unmap_mapping_folio+0x74/0xd0
[ 46.749854] folio_unmap_invalidate+0x92/0x200
[ 46.749886] folio_end_writeback+0x51/0xb0
[ 46.749906] ext4_finish_bio+0x36d/0x3a0
[ 46.749979] ext4_end_bio+0x51/0x140
[ 46.750010] blk_update_request+0x101/0x4d0
[ 46.750045] ? detach_buf_split_in_order+0x18c/0x1b0
[ 46.750098] blk_mq_end_request+0x20/0x130
[ 46.750135] virtblk_done+0x75/0x100
[ 46.750173] ? irq_thread+0xb3/0x2a0
[ 46.750190] vring_interrupt+0x8c/0xd0
[ 46.750205] irq_thread_fn+0x23/0x60
[ 46.750238] irq_forced_thread_fn+0x35/0x60
[ 46.750261] irq_thread+0x17c/0x2a0
[ 46.750274] ? __pfx_irq_forced_thread_fn+0x10/0x10
[ 46.750299] ? __pfx_irq_thread_dtor+0x10/0x10
[ 46.750333] ? __pfx_irq_thread+0x10/0x10
[ 46.750353] kthread+0xf6/0x130
[ 46.750369] ? __pfx_kthread+0x10/0x10
[ 46.750404] ret_from_fork+0x248/0x350
[ 46.750421] ? __pfx_kthread+0x10/0x10
[ 46.750442] ret_from_fork_asm+0x1a/0x30
[ 46.750585] </TASK>
[ 46.752964] =============================
[ 46.753047] [ BUG: Invalid wait context ]
[ 46.753230] 7.2.0+ #5 Tainted: G W
[ 46.753353] -----------------------------
[ 46.753438] irq/40-virtio1-/61 is trying to lock:
[ 46.753533] ff1fce99004e4990 (&mapping->i_mmap_rwsem){++++}-{4:4}, at: unmap_mapping_folio+0x74/0xd0
[ 46.753882] other info that might help us debug this:
[ 46.754000] context-{5:5}
[ 46.754062] locks held by irq/40-virtio1-/61: 1, last CPU#0:
[ 46.754171] #0: ff1fce9901fc2f20 (&vblk->vqs[i].lock){....}-{3:3}, at: virtblk_done+0x56/0x100
[ 46.754371] stack backtrace:
[ 46.754441] CPU: 0 UID: 0 PID: 61 Comm: irq/40-virtio1- Tainted: G W 7.2.0+ #5 PREEMPT(full)
[ 46.754656] Tainted: [W]=WARN
[ 46.754725] Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
[ 46.754887] Call Trace:
[ 46.754942] <TASK>
[ 46.754996] dump_stack_lvl+0x66/0xa0
[ 46.755082] __lock_acquire+0x92e/0x1a80
[ 46.755197] lock_acquire+0xcd/0x2d0
[ 46.755282] ? unmap_mapping_folio+0x74/0xd0
[ 46.755403] down_read+0x42/0x170
[ 46.755476] ? unmap_mapping_folio+0x74/0xd0
[ 46.755565] unmap_mapping_folio+0x74/0xd0
[ 46.755664] folio_unmap_invalidate+0x92/0x200
[ 46.755763] folio_end_writeback+0x51/0xb0
[ 46.755851] ext4_finish_bio+0x36d/0x3a0
[ 46.755958] ext4_end_bio+0x51/0x140
[ 46.756043] blk_update_request+0x101/0x4d0
[ 46.756135] ? detach_buf_split_in_order+0x18c/0x1b0
[ 46.756254] blk_mq_end_request+0x20/0x130
[ 46.756349] virtblk_done+0x75/0x100
[ 46.756438] ? irq_thread+0xb3/0x2a0
[ 46.756515] vring_interrupt+0x8c/0xd0
[ 46.756595] irq_thread_fn+0x23/0x60
[ 46.756678] irq_forced_thread_fn+0x35/0x60
[ 46.756768] irq_thread+0x17c/0x2a0
[ 46.756842] ? __pfx_irq_forced_thread_fn+0x10/0x10
[ 46.756945] ? __pfx_irq_thread_dtor+0x10/0x10
[ 46.757045] ? __pfx_irq_thread+0x10/0x10
[ 46.757136] kthread+0xf6/0x130
[ 46.757207] ? __pfx_kthread+0x10/0x10
[ 46.757302] ret_from_fork+0x248/0x350
[ 46.757383] ? __pfx_kthread+0x10/0x10
[ 46.757466] ret_from_fork_asm+0x1a/0x30
[ 46.757594] </TASK>
> Changes since v3:
> - Describe the forced-unmap/refault runtime effect.
> - Record the reproduction boundary and add Cc: stable@vger.kernel.org.
>
> mm/filemap.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/mm/filemap.c b/mm/filemap.c
> index 6afec636881f..00fd89cf6f55 100644
> --- a/mm/filemap.c
> +++ b/mm/filemap.c
> @@ -1616,7 +1616,7 @@ static void filemap_end_dropbehind(struct folio *folio)
> return;
> if (!folio_test_clear_dropbehind(folio))
> return;
> - if (mapping)
> + if (mapping && !folio_mapped(folio))
> folio_unmap_invalidate(mapping, folio, 0);
> }
>
> --
> 2.43.0
>
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2026-08-30 11:59 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-08-20 14:29 [PATCH] mm: filemap: tighten dropbehind completion context check Wenjie Qi
2026-08-20 14:34 ` Matthew Wilcox
2026-08-21 1:23 ` Wenjie Qi
2026-08-21 3:30 ` Matthew Wilcox
2026-08-24 13:34 ` Wenjie Qi
2026-08-29 1:10 ` Andrew Morton
2026-08-29 12:13 ` Wenjie Qi
2026-08-30 8:45 ` Barry Song
2026-08-29 12:30 ` [PATCH v2] mm: filemap: retain mapped dropbehind folios Wenjie Qi
2026-08-29 14:47 ` Matthew Wilcox
2026-08-29 15:53 ` Tal Zussman
2026-08-29 16:09 ` Tal Zussman
2026-08-29 17:36 ` [PATCH v3] " Wenjie Qi
2026-08-29 18:16 ` Andrew Morton
2026-08-30 3:25 ` [PATCH v4] " Wenjie Qi
2026-08-30 8:35 ` Barry Song
2026-08-30 9:13 ` Wenjie Qi
2026-08-30 9:31 ` Barry Song
2026-08-30 11:58 ` Tal Zussman
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®