* [PATCH v1 00/16] mm: cleanups around unmapping / zapping
@ 2026-02-27 20:08 David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 01/16] mm/madvise: drop range checks in madvise_free_single_vma() David Hildenbrand (Arm)
` (15 more replies)
0 siblings, 16 replies; 17+ messages in thread
From: David Hildenbrand (Arm) @ 2026-02-27 20:08 UTC (permalink / raw)
To: linux-kernel
Cc: linux-mm @ kvack . org, David Hildenbrand (Arm),
Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Jann Horn,
Pedro Falcato, David Rientjes, Shakeel Butt,
Matthew Wilcox (Oracle),
Alice Ryhl, Madhavan Srinivasan, Michael Ellerman,
Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
Alexander Gordeev, Gerald Schaefer, Heiko Carstens,
Vasily Gorbik, Jarkko Sakkinen, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Greg Kroah-Hartman, Arve Hjønnevåg,
Todd Kjos, Christian Brauner, Carlos Llamas, Ian Abbott,
H Hartley Sweeten, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, David Airlie, Simona Vetter, Jason Gunthorpe,
Leon Romanovsky, Dimitri Sivanich, Arnd Bergmann,
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Peter Zijlstra, Arnaldo Carvalho de Melo, Namhyung Kim,
Andy Lutomirski, Vincenzo Frascino, Eric Dumazet, Neal Cardwell,
David S. Miller, David Ahern, Jakub Kicinski, Paolo Abeni,
Miguel Ojeda, linuxppc-dev, kvm, linux-s390, linux-sgx,
intel-gfx, dri-devel, linux-rdma, bpf, linux-perf-users,
linux-fsdevel, netdev, rust-for-linux, x86
A bunch of cleanups around unmapping and zapping. Mostly simplifications,
code movements, documentation and renaming of zapping functions.
With this series, we'll have the following high-level zap/unmap functions
(excluding high-level folio zapping):
* unmap_vmas() for actual unmapping (vmas will go away)
* zap_vma(): zap all page table entries in a vma
* zap_vma_for_reaping(): zap_vma() that must not block
* zap_vma_range(): zap a range of page table entries
* zap_vma_range_batched(): zap_vma_range() with more options and batching
* zap_special_vma_range(): limited zap_vma_range() for modules
* __zap_vma_range(): internal helper
Patch #1 is not about unmapping/zapping, but I stumbled over it while
verifying MADV_DONTNEED range handling.
Patch #16 is related to [1], but makes sense even independent of that.
[1] https://lore.kernel.org/r/aYSKyr7StGpGKNqW@google.com
The CC list is already long enough. As these are simple changes to
drivers/arch code, I'm only CCing maintainers of all changes but only
reviewers of the MM bits.
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Lorenzo Stoakes <lorenzo.stoakes@oracle.com>
Cc: "Liam R. Howlett" <Liam.Howlett@oracle.com>
Cc: Vlastimil Babka <vbabka@kernel.org>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Suren Baghdasaryan <surenb@google.com>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Jann Horn <jannh@google.com>
Cc: Pedro Falcato <pfalcato@suse.de>
Cc: David Rientjes <rientjes@google.com>
Cc: Shakeel Butt <shakeel.butt@linux.dev>
Cc: "Matthew Wilcox (Oracle)" <willy@infradead.org>
Cc: Alice Ryhl <aliceryhl@google.com>
Cc: Madhavan Srinivasan <maddy@linux.ibm.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: Christian Borntraeger <borntraeger@linux.ibm.com>
Cc: Janosch Frank <frankja@linux.ibm.com>
Cc: Claudio Imbrenda <imbrenda@linux.ibm.com>
Cc: Alexander Gordeev <agordeev@linux.ibm.com>
Cc: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
Cc: Heiko Carstens <hca@linux.ibm.com>
Cc: Vasily Gorbik <gor@linux.ibm.com>
Cc: Jarkko Sakkinen <jarkko@kernel.org>
Cc: Thomas Gleixner <tglx@kernel.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: "Arve Hjønnevåg" <arve@android.com>
Cc: Todd Kjos <tkjos@android.com>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Carlos Llamas <cmllamas@google.com>
Cc: Alice Ryhl <aliceryhl@google.com>
Cc: Ian Abbott <abbotti@mev.co.uk>
Cc: H Hartley Sweeten <hsweeten@visionengravers.com>
Cc: Jani Nikula <jani.nikula@linux.intel.com>
Cc: Joonas Lahtinen <joonas.lahtinen@linux.intel.com>
Cc: Rodrigo Vivi <rodrigo.vivi@intel.com>
Cc: Tvrtko Ursulin <tursulin@ursulin.net>
Cc: David Airlie <airlied@gmail.com>
Cc: Simona Vetter <simona@ffwll.ch>
Cc: Jason Gunthorpe <jgg@ziepe.ca>
Cc: Leon Romanovsky <leon@kernel.org>
Cc: Dimitri Sivanich <dimitri.sivanich@hpe.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Andrii Nakryiko <andrii@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Vincenzo Frascino <vincenzo.frascino@arm.com>
Cc: Eric Dumazet <edumazet@google.com>
Cc: Neal Cardwell <ncardwell@google.com>
Cc: "David S. Miller" <davem@davemloft.net>
Cc: David Ahern <dsahern@kernel.org>
Cc: Jakub Kicinski <kuba@kernel.org>
Cc: Paolo Abeni <pabeni@redhat.com>
Cc: Miguel Ojeda <ojeda@kernel.org>
Cc: linuxppc-dev@lists.ozlabs.org
Cc: kvm@vger.kernel.org
Cc: linux-s390@vger.kernel.org
Cc: linux-sgx@vger.kernel.org
Cc: intel-gfx@lists.freedesktop.org
Cc: dri-devel@lists.freedesktop.org
Cc: linux-rdma@vger.kernel.org
Cc: bpf@vger.kernel.org
Cc: linux-perf-users@vger.kernel.org
Cc: linux-fsdevel@vger.kernel.org
Cc: netdev@vger.kernel.org
Cc: rust-for-linux@vger.kernel.org
Cc: x86@kernel.org
David Hildenbrand (Arm) (16):
mm/madvise: drop range checks in madvise_free_single_vma()
mm/memory: remove "zap_details" parameter from zap_page_range_single()
mm/memory: inline unmap_mapping_range_vma() into
unmap_mapping_range_tree()
mm/memory: simplify calculation in unmap_mapping_range_tree()
mm/oom_kill: use MMU_NOTIFY_CLEAR in __oom_reap_task_mm()
mm/oom_kill: factor out zapping of VMA into zap_vma_for_reaping()
mm/memory: rename unmap_single_vma() to __zap_vma_range()
mm/memory: move adjusting of address range to unmap_vmas()
mm/memory: convert details->even_cows into details->skip_cows
mm/memory: use __zap_vma_range() in zap_vma_for_reaping()
mm/memory: inline unmap_page_range() into __zap_vma_range()
mm: rename zap_vma_pages() to zap_vma()
mm: rename zap_page_range_single_batched() to zap_vma_range_batched()
mm: rename zap_page_range_single() to zap_vma_range()
mm: rename zap_vma_ptes() to zap_special_vma_range()
mm/memory: support VM_MIXEDMAP in zap_special_vma_range()
arch/powerpc/platforms/book3s/vas-api.c | 2 +-
arch/powerpc/platforms/pseries/vas.c | 2 +-
arch/s390/mm/gmap_helpers.c | 2 +-
arch/x86/kernel/cpu/sgx/encl.c | 2 +-
drivers/android/binder/page_range.rs | 4 +-
drivers/android/binder_alloc.c | 2 +-
drivers/comedi/comedi_fops.c | 2 +-
drivers/gpu/drm/i915/i915_mm.c | 4 +-
drivers/infiniband/core/uverbs_main.c | 6 +-
drivers/misc/sgi-gru/grumain.c | 2 +-
include/linux/mm.h | 23 ++-
kernel/bpf/arena.c | 3 +-
kernel/events/core.c | 2 +-
lib/vdso/datastore.c | 2 +-
mm/internal.h | 7 +-
mm/interval_tree.c | 5 -
mm/madvise.c | 24 +--
mm/memory.c | 217 ++++++++++++------------
mm/oom_kill.c | 15 +-
mm/page-writeback.c | 2 +-
net/ipv4/tcp.c | 7 +-
rust/kernel/mm/virt.rs | 4 +-
22 files changed, 162 insertions(+), 177 deletions(-)
base-commit: df9c51269a5e2a6fbca2884a756a4011a5e78748
--
2.43.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v1 01/16] mm/madvise: drop range checks in madvise_free_single_vma()
2026-02-27 20:08 [PATCH v1 00/16] mm: cleanups around unmapping / zapping David Hildenbrand (Arm)
@ 2026-02-27 20:08 ` David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 02/16] mm/memory: remove "zap_details" parameter from zap_page_range_single() David Hildenbrand (Arm)
` (14 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: David Hildenbrand (Arm) @ 2026-02-27 20:08 UTC (permalink / raw)
To: linux-kernel
Cc: linux-mm @ kvack . org, David Hildenbrand (Arm),
Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Jann Horn,
Pedro Falcato, David Rientjes, Shakeel Butt,
Matthew Wilcox (Oracle),
Alice Ryhl, Madhavan Srinivasan, Michael Ellerman,
Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
Alexander Gordeev, Gerald Schaefer, Heiko Carstens,
Vasily Gorbik, Jarkko Sakkinen, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Greg Kroah-Hartman, Arve Hjønnevåg,
Todd Kjos, Christian Brauner, Carlos Llamas, Ian Abbott,
H Hartley Sweeten, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, David Airlie, Simona Vetter, Jason Gunthorpe,
Leon Romanovsky, Dimitri Sivanich, Arnd Bergmann,
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Peter Zijlstra, Arnaldo Carvalho de Melo, Namhyung Kim,
Andy Lutomirski, Vincenzo Frascino, Eric Dumazet, Neal Cardwell,
David S. Miller, David Ahern, Jakub Kicinski, Paolo Abeni,
Miguel Ojeda, linuxppc-dev, kvm, linux-s390, linux-sgx,
intel-gfx, dri-devel, linux-rdma, bpf, linux-perf-users,
linux-fsdevel, netdev, rust-for-linux, x86
madvise_vma_behavior()-> madvise_dontneed_free()->madvise_free_single_vma()
is only called from madvise_walk_vmas()
(a) After try_vma_read_lock() confirmed that the whole range falls into
a single VMA (see is_vma_lock_sufficient()).
(b) After adjusting the range to the VMA in the loop afterwards.
madvise_dontneed_free() might drop the MM lock when handling
userfaultfd, but it properly looks up the VMA again to adjust the range.
So in madvise_free_single_vma(), the given range should always fall into
a single VMA and should also span at least one page.
Let's drop the error checks.
The code now matches what we do in madvise_dontneed_single_vma(), where
we call zap_vma_range_batched() that documents: "The range must fit into
one VMA.". Although that function still adjusts that range, we'll change
that soon.
Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
mm/madvise.c | 13 ++++---------
1 file changed, 4 insertions(+), 9 deletions(-)
diff --git a/mm/madvise.c b/mm/madvise.c
index c0370d9b4e23..efc04334a000 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -799,9 +799,10 @@ static int madvise_free_single_vma(struct madvise_behavior *madv_behavior)
{
struct mm_struct *mm = madv_behavior->mm;
struct vm_area_struct *vma = madv_behavior->vma;
- unsigned long start_addr = madv_behavior->range.start;
- unsigned long end_addr = madv_behavior->range.end;
- struct mmu_notifier_range range;
+ struct mmu_notifier_range range = {
+ .start = madv_behavior->range.start,
+ .end = madv_behavior->range.end,
+ };
struct mmu_gather *tlb = madv_behavior->tlb;
struct mm_walk_ops walk_ops = {
.pmd_entry = madvise_free_pte_range,
@@ -811,12 +812,6 @@ static int madvise_free_single_vma(struct madvise_behavior *madv_behavior)
if (!vma_is_anonymous(vma))
return -EINVAL;
- range.start = max(vma->vm_start, start_addr);
- if (range.start >= vma->vm_end)
- return -EINVAL;
- range.end = min(vma->vm_end, end_addr);
- if (range.end <= vma->vm_start)
- return -EINVAL;
mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, mm,
range.start, range.end);
--
2.43.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v1 02/16] mm/memory: remove "zap_details" parameter from zap_page_range_single()
2026-02-27 20:08 [PATCH v1 00/16] mm: cleanups around unmapping / zapping David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 01/16] mm/madvise: drop range checks in madvise_free_single_vma() David Hildenbrand (Arm)
@ 2026-02-27 20:08 ` David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 03/16] mm/memory: inline unmap_mapping_range_vma() into unmap_mapping_range_tree() David Hildenbrand (Arm)
` (13 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: David Hildenbrand (Arm) @ 2026-02-27 20:08 UTC (permalink / raw)
To: linux-kernel
Cc: linux-mm @ kvack . org, David Hildenbrand (Arm),
Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Jann Horn,
Pedro Falcato, David Rientjes, Shakeel Butt,
Matthew Wilcox (Oracle),
Alice Ryhl, Madhavan Srinivasan, Michael Ellerman,
Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
Alexander Gordeev, Gerald Schaefer, Heiko Carstens,
Vasily Gorbik, Jarkko Sakkinen, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Greg Kroah-Hartman, Arve Hjønnevåg,
Todd Kjos, Christian Brauner, Carlos Llamas, Ian Abbott,
H Hartley Sweeten, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, David Airlie, Simona Vetter, Jason Gunthorpe,
Leon Romanovsky, Dimitri Sivanich, Arnd Bergmann,
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Peter Zijlstra, Arnaldo Carvalho de Melo, Namhyung Kim,
Andy Lutomirski, Vincenzo Frascino, Eric Dumazet, Neal Cardwell,
David S. Miller, David Ahern, Jakub Kicinski, Paolo Abeni,
Miguel Ojeda, linuxppc-dev, kvm, linux-s390, linux-sgx,
intel-gfx, dri-devel, linux-rdma, bpf, linux-perf-users,
linux-fsdevel, netdev, rust-for-linux, x86
Nobody except memory.c should really set that parameter to non-NULL. So
let's just drop it and make unmap_mapping_range_vma() use
zap_page_range_single_batched() instead.
Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
arch/s390/mm/gmap_helpers.c | 2 +-
drivers/android/binder_alloc.c | 2 +-
include/linux/mm.h | 5 ++---
kernel/bpf/arena.c | 3 +--
kernel/events/core.c | 2 +-
mm/madvise.c | 3 +--
mm/memory.c | 16 ++++++++++------
net/ipv4/tcp.c | 5 ++---
rust/kernel/mm/virt.rs | 2 +-
9 files changed, 20 insertions(+), 20 deletions(-)
diff --git a/arch/s390/mm/gmap_helpers.c b/arch/s390/mm/gmap_helpers.c
index dea83e3103e5..ae2d59a19313 100644
--- a/arch/s390/mm/gmap_helpers.c
+++ b/arch/s390/mm/gmap_helpers.c
@@ -89,7 +89,7 @@ void gmap_helper_discard(struct mm_struct *mm, unsigned long vmaddr, unsigned lo
if (!vma)
return;
if (!is_vm_hugetlb_page(vma))
- zap_page_range_single(vma, vmaddr, min(end, vma->vm_end) - vmaddr, NULL);
+ zap_page_range_single(vma, vmaddr, min(end, vma->vm_end) - vmaddr);
vmaddr = vma->vm_end;
}
}
diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c
index 241f16a9b63d..dd2046bd5cde 100644
--- a/drivers/android/binder_alloc.c
+++ b/drivers/android/binder_alloc.c
@@ -1185,7 +1185,7 @@ enum lru_status binder_alloc_free_page(struct list_head *item,
if (vma) {
trace_binder_unmap_user_start(alloc, index);
- zap_page_range_single(vma, page_addr, PAGE_SIZE, NULL);
+ zap_page_range_single(vma, page_addr, PAGE_SIZE);
trace_binder_unmap_user_end(alloc, index);
}
diff --git a/include/linux/mm.h b/include/linux/mm.h
index ecff8268089b..a8138ff7d1fa 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2835,11 +2835,10 @@ struct page *vm_normal_page_pud(struct vm_area_struct *vma, unsigned long addr,
void zap_vma_ptes(struct vm_area_struct *vma, unsigned long address,
unsigned long size);
void zap_page_range_single(struct vm_area_struct *vma, unsigned long address,
- unsigned long size, struct zap_details *details);
+ unsigned long size);
static inline void zap_vma_pages(struct vm_area_struct *vma)
{
- zap_page_range_single(vma, vma->vm_start,
- vma->vm_end - vma->vm_start, NULL);
+ zap_page_range_single(vma, vma->vm_start, vma->vm_end - vma->vm_start);
}
struct mmu_notifier_range;
diff --git a/kernel/bpf/arena.c b/kernel/bpf/arena.c
index 144f30e740e8..c34510d83b1f 100644
--- a/kernel/bpf/arena.c
+++ b/kernel/bpf/arena.c
@@ -656,8 +656,7 @@ static void zap_pages(struct bpf_arena *arena, long uaddr, long page_cnt)
guard(mutex)(&arena->lock);
/* iterate link list under lock */
list_for_each_entry(vml, &arena->vma_list, head)
- zap_page_range_single(vml->vma, uaddr,
- PAGE_SIZE * page_cnt, NULL);
+ zap_page_range_single(vml->vma, uaddr, PAGE_SIZE * page_cnt);
}
static void arena_free_pages(struct bpf_arena *arena, long uaddr, long page_cnt, bool sleepable)
diff --git a/kernel/events/core.c b/kernel/events/core.c
index ac70d68217b6..c94c56c94104 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -7215,7 +7215,7 @@ static int map_range(struct perf_buffer *rb, struct vm_area_struct *vma)
#ifdef CONFIG_MMU
/* Clear any partial mappings on error. */
if (err)
- zap_page_range_single(vma, vma->vm_start, nr_pages * PAGE_SIZE, NULL);
+ zap_page_range_single(vma, vma->vm_start, nr_pages * PAGE_SIZE);
#endif
return err;
diff --git a/mm/madvise.c b/mm/madvise.c
index efc04334a000..557a360f7919 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -1193,8 +1193,7 @@ static long madvise_guard_install(struct madvise_behavior *madv_behavior)
* OK some of the range have non-guard pages mapped, zap
* them. This leaves existing guard pages in place.
*/
- zap_page_range_single(vma, range->start,
- range->end - range->start, NULL);
+ zap_page_range_single(vma, range->start, range->end - range->start);
}
/*
diff --git a/mm/memory.c b/mm/memory.c
index 9385842c3503..19f5f9a60995 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2203,17 +2203,16 @@ void zap_page_range_single_batched(struct mmu_gather *tlb,
* @vma: vm_area_struct holding the applicable pages
* @address: starting address of pages to zap
* @size: number of bytes to zap
- * @details: details of shared cache invalidation
*
* The range must fit into one VMA.
*/
void zap_page_range_single(struct vm_area_struct *vma, unsigned long address,
- unsigned long size, struct zap_details *details)
+ unsigned long size)
{
struct mmu_gather tlb;
tlb_gather_mmu(&tlb, vma->vm_mm);
- zap_page_range_single_batched(&tlb, vma, address, size, details);
+ zap_page_range_single_batched(&tlb, vma, address, size, NULL);
tlb_finish_mmu(&tlb);
}
@@ -2235,7 +2234,7 @@ void zap_vma_ptes(struct vm_area_struct *vma, unsigned long address,
!(vma->vm_flags & VM_PFNMAP))
return;
- zap_page_range_single(vma, address, size, NULL);
+ zap_page_range_single(vma, address, size);
}
EXPORT_SYMBOL_GPL(zap_vma_ptes);
@@ -3003,7 +3002,7 @@ static int remap_pfn_range_notrack(struct vm_area_struct *vma, unsigned long add
* maintain page reference counts, and callers may free
* pages due to the error. So zap it early.
*/
- zap_page_range_single(vma, addr, size, NULL);
+ zap_page_range_single(vma, addr, size);
return error;
}
@@ -4226,7 +4225,12 @@ static void unmap_mapping_range_vma(struct vm_area_struct *vma,
unsigned long start_addr, unsigned long end_addr,
struct zap_details *details)
{
- zap_page_range_single(vma, start_addr, end_addr - start_addr, details);
+ struct mmu_gather tlb;
+
+ tlb_gather_mmu(&tlb, vma->vm_mm);
+ zap_page_range_single_batched(&tlb, vma, start_addr,
+ end_addr - start_addr, details);
+ tlb_finish_mmu(&tlb);
}
static inline void unmap_mapping_range_tree(struct rb_root_cached *root,
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index f84d9a45cc9d..befcde27dee7 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2104,7 +2104,7 @@ static int tcp_zerocopy_vm_insert_batch_error(struct vm_area_struct *vma,
maybe_zap_len = total_bytes_to_map - /* All bytes to map */
*length + /* Mapped or pending */
(pages_remaining * PAGE_SIZE); /* Failed map. */
- zap_page_range_single(vma, *address, maybe_zap_len, NULL);
+ zap_page_range_single(vma, *address, maybe_zap_len);
err = 0;
}
@@ -2269,8 +2269,7 @@ static int tcp_zerocopy_receive(struct sock *sk,
total_bytes_to_map = avail_len & ~(PAGE_SIZE - 1);
if (total_bytes_to_map) {
if (!(zc->flags & TCP_RECEIVE_ZEROCOPY_FLAG_TLB_CLEAN_HINT))
- zap_page_range_single(vma, address, total_bytes_to_map,
- NULL);
+ zap_page_range_single(vma, address, total_bytes_to_map);
zc->length = total_bytes_to_map;
zc->recv_skip_hint = 0;
} else {
diff --git a/rust/kernel/mm/virt.rs b/rust/kernel/mm/virt.rs
index da21d65ccd20..b8e59e4420f3 100644
--- a/rust/kernel/mm/virt.rs
+++ b/rust/kernel/mm/virt.rs
@@ -124,7 +124,7 @@ pub fn zap_page_range_single(&self, address: usize, size: usize) {
// sufficient for this method call. This method has no requirements on the vma flags. The
// address range is checked to be within the vma.
unsafe {
- bindings::zap_page_range_single(self.as_ptr(), address, size, core::ptr::null_mut())
+ bindings::zap_page_range_single(self.as_ptr(), address, size)
};
}
--
2.43.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v1 03/16] mm/memory: inline unmap_mapping_range_vma() into unmap_mapping_range_tree()
2026-02-27 20:08 [PATCH v1 00/16] mm: cleanups around unmapping / zapping David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 01/16] mm/madvise: drop range checks in madvise_free_single_vma() David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 02/16] mm/memory: remove "zap_details" parameter from zap_page_range_single() David Hildenbrand (Arm)
@ 2026-02-27 20:08 ` David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 04/16] mm/memory: simplify calculation in unmap_mapping_range_tree() David Hildenbrand (Arm)
` (12 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: David Hildenbrand (Arm) @ 2026-02-27 20:08 UTC (permalink / raw)
To: linux-kernel
Cc: linux-mm @ kvack . org, David Hildenbrand (Arm),
Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Jann Horn,
Pedro Falcato, David Rientjes, Shakeel Butt,
Matthew Wilcox (Oracle),
Alice Ryhl, Madhavan Srinivasan, Michael Ellerman,
Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
Alexander Gordeev, Gerald Schaefer, Heiko Carstens,
Vasily Gorbik, Jarkko Sakkinen, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Greg Kroah-Hartman, Arve Hjønnevåg,
Todd Kjos, Christian Brauner, Carlos Llamas, Ian Abbott,
H Hartley Sweeten, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, David Airlie, Simona Vetter, Jason Gunthorpe,
Leon Romanovsky, Dimitri Sivanich, Arnd Bergmann,
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Peter Zijlstra, Arnaldo Carvalho de Melo, Namhyung Kim,
Andy Lutomirski, Vincenzo Frascino, Eric Dumazet, Neal Cardwell,
David S. Miller, David Ahern, Jakub Kicinski, Paolo Abeni,
Miguel Ojeda, linuxppc-dev, kvm, linux-s390, linux-sgx,
intel-gfx, dri-devel, linux-rdma, bpf, linux-perf-users,
linux-fsdevel, netdev, rust-for-linux, x86
Let's remove the number of unmap-related functions that cause confusion
by inlining unmap_mapping_range_vma() into its single caller. The end
result looks pretty readable.
Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
mm/memory.c | 23 +++++++----------------
1 file changed, 7 insertions(+), 16 deletions(-)
diff --git a/mm/memory.c b/mm/memory.c
index 19f5f9a60995..5c47309331f5 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -4221,18 +4221,6 @@ static vm_fault_t do_wp_page(struct vm_fault *vmf)
return wp_page_copy(vmf);
}
-static void unmap_mapping_range_vma(struct vm_area_struct *vma,
- unsigned long start_addr, unsigned long end_addr,
- struct zap_details *details)
-{
- struct mmu_gather tlb;
-
- tlb_gather_mmu(&tlb, vma->vm_mm);
- zap_page_range_single_batched(&tlb, vma, start_addr,
- end_addr - start_addr, details);
- tlb_finish_mmu(&tlb);
-}
-
static inline void unmap_mapping_range_tree(struct rb_root_cached *root,
pgoff_t first_index,
pgoff_t last_index,
@@ -4240,17 +4228,20 @@ static inline void unmap_mapping_range_tree(struct rb_root_cached *root,
{
struct vm_area_struct *vma;
pgoff_t vba, vea, zba, zea;
+ unsigned long start, size;
+ struct mmu_gather tlb;
vma_interval_tree_foreach(vma, root, first_index, last_index) {
vba = vma->vm_pgoff;
vea = vba + vma_pages(vma) - 1;
zba = max(first_index, vba);
zea = min(last_index, vea);
+ start = ((zba - vba) << PAGE_SHIFT) + vma->vm_start;
+ size = (zea - zba + 1) << PAGE_SHIFT;
- unmap_mapping_range_vma(vma,
- ((zba - vba) << PAGE_SHIFT) + vma->vm_start,
- ((zea - vba + 1) << PAGE_SHIFT) + vma->vm_start,
- details);
+ tlb_gather_mmu(&tlb, vma->vm_mm);
+ zap_page_range_single_batched(&tlb, vma, start, size, details);
+ tlb_finish_mmu(&tlb);
}
}
--
2.43.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v1 04/16] mm/memory: simplify calculation in unmap_mapping_range_tree()
2026-02-27 20:08 [PATCH v1 00/16] mm: cleanups around unmapping / zapping David Hildenbrand (Arm)
` (2 preceding siblings ...)
2026-02-27 20:08 ` [PATCH v1 03/16] mm/memory: inline unmap_mapping_range_vma() into unmap_mapping_range_tree() David Hildenbrand (Arm)
@ 2026-02-27 20:08 ` David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 05/16] mm/oom_kill: use MMU_NOTIFY_CLEAR in __oom_reap_task_mm() David Hildenbrand (Arm)
` (11 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: David Hildenbrand (Arm) @ 2026-02-27 20:08 UTC (permalink / raw)
To: linux-kernel
Cc: linux-mm @ kvack . org, David Hildenbrand (Arm),
Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Jann Horn,
Pedro Falcato, David Rientjes, Shakeel Butt,
Matthew Wilcox (Oracle),
Alice Ryhl, Madhavan Srinivasan, Michael Ellerman,
Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
Alexander Gordeev, Gerald Schaefer, Heiko Carstens,
Vasily Gorbik, Jarkko Sakkinen, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Greg Kroah-Hartman, Arve Hjønnevåg,
Todd Kjos, Christian Brauner, Carlos Llamas, Ian Abbott,
H Hartley Sweeten, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, David Airlie, Simona Vetter, Jason Gunthorpe,
Leon Romanovsky, Dimitri Sivanich, Arnd Bergmann,
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Peter Zijlstra, Arnaldo Carvalho de Melo, Namhyung Kim,
Andy Lutomirski, Vincenzo Frascino, Eric Dumazet, Neal Cardwell,
David S. Miller, David Ahern, Jakub Kicinski, Paolo Abeni,
Miguel Ojeda, linuxppc-dev, kvm, linux-s390, linux-sgx,
intel-gfx, dri-devel, linux-rdma, bpf, linux-perf-users,
linux-fsdevel, netdev, rust-for-linux, x86
Let's simplify the calculation a bit further to make it easier to get,
reusing vma_last_pgoff() which we move from interval_tree.c to mm.h.
Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
include/linux/mm.h | 5 +++++
mm/interval_tree.c | 5 -----
mm/memory.c | 12 +++++-------
3 files changed, 10 insertions(+), 12 deletions(-)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index a8138ff7d1fa..d3ef586ee1c0 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -4000,6 +4000,11 @@ static inline unsigned long vma_pages(const struct vm_area_struct *vma)
return (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
}
+static inline unsigned long vma_last_pgoff(struct vm_area_struct *vma)
+{
+ return vma->vm_pgoff + vma_pages(vma) - 1;
+}
+
static inline unsigned long vma_desc_size(const struct vm_area_desc *desc)
{
return desc->end - desc->start;
diff --git a/mm/interval_tree.c b/mm/interval_tree.c
index 32e390c42c53..32bcfbfcf15f 100644
--- a/mm/interval_tree.c
+++ b/mm/interval_tree.c
@@ -15,11 +15,6 @@ static inline unsigned long vma_start_pgoff(struct vm_area_struct *v)
return v->vm_pgoff;
}
-static inline unsigned long vma_last_pgoff(struct vm_area_struct *v)
-{
- return v->vm_pgoff + vma_pages(v) - 1;
-}
-
INTERVAL_TREE_DEFINE(struct vm_area_struct, shared.rb,
unsigned long, shared.rb_subtree_last,
vma_start_pgoff, vma_last_pgoff, /* empty */, vma_interval_tree)
diff --git a/mm/memory.c b/mm/memory.c
index 5c47309331f5..e4154f03feac 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -4227,17 +4227,15 @@ static inline void unmap_mapping_range_tree(struct rb_root_cached *root,
struct zap_details *details)
{
struct vm_area_struct *vma;
- pgoff_t vba, vea, zba, zea;
unsigned long start, size;
struct mmu_gather tlb;
vma_interval_tree_foreach(vma, root, first_index, last_index) {
- vba = vma->vm_pgoff;
- vea = vba + vma_pages(vma) - 1;
- zba = max(first_index, vba);
- zea = min(last_index, vea);
- start = ((zba - vba) << PAGE_SHIFT) + vma->vm_start;
- size = (zea - zba + 1) << PAGE_SHIFT;
+ const pgoff_t start_idx = max(first_index, vma->vm_pgoff);
+ const pgoff_t end_idx = min(last_index, vma_last_pgoff(vma)) + 1;
+
+ start = vma->vm_start + ((start_idx - vma->vm_pgoff) << PAGE_SHIFT);
+ size = (end_idx - start_idx) << PAGE_SHIFT;
tlb_gather_mmu(&tlb, vma->vm_mm);
zap_page_range_single_batched(&tlb, vma, start, size, details);
--
2.43.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v1 05/16] mm/oom_kill: use MMU_NOTIFY_CLEAR in __oom_reap_task_mm()
2026-02-27 20:08 [PATCH v1 00/16] mm: cleanups around unmapping / zapping David Hildenbrand (Arm)
` (3 preceding siblings ...)
2026-02-27 20:08 ` [PATCH v1 04/16] mm/memory: simplify calculation in unmap_mapping_range_tree() David Hildenbrand (Arm)
@ 2026-02-27 20:08 ` David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 06/16] mm/oom_kill: factor out zapping of VMA into zap_vma_for_reaping() David Hildenbrand (Arm)
` (10 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: David Hildenbrand (Arm) @ 2026-02-27 20:08 UTC (permalink / raw)
To: linux-kernel
Cc: linux-mm @ kvack . org, David Hildenbrand (Arm),
Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Jann Horn,
Pedro Falcato, David Rientjes, Shakeel Butt,
Matthew Wilcox (Oracle),
Alice Ryhl, Madhavan Srinivasan, Michael Ellerman,
Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
Alexander Gordeev, Gerald Schaefer, Heiko Carstens,
Vasily Gorbik, Jarkko Sakkinen, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Greg Kroah-Hartman, Arve Hjønnevåg,
Todd Kjos, Christian Brauner, Carlos Llamas, Ian Abbott,
H Hartley Sweeten, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, David Airlie, Simona Vetter, Jason Gunthorpe,
Leon Romanovsky, Dimitri Sivanich, Arnd Bergmann,
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Peter Zijlstra, Arnaldo Carvalho de Melo, Namhyung Kim,
Andy Lutomirski, Vincenzo Frascino, Eric Dumazet, Neal Cardwell,
David S. Miller, David Ahern, Jakub Kicinski, Paolo Abeni,
Miguel Ojeda, linuxppc-dev, kvm, linux-s390, linux-sgx,
intel-gfx, dri-devel, linux-rdma, bpf, linux-perf-users,
linux-fsdevel, netdev, rust-for-linux, x86
In commit 7269f999934b ("mm/mmu_notifier: use correct mmu_notifier events
for each invalidation") we converted all MMU_NOTIFY_UNMAP to
MMU_NOTIFY_CLEAR, except the ones that actually perform munmap() or
mremap() as documented.
__oom_reap_task_mm() behaves much more like MADV_DONTNEED. So use
MMU_NOTIFY_CLEAR as well.
This is a preparation for further changes.
Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
mm/oom_kill.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 5c6c95c169ee..0ba56fcd10d5 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -551,7 +551,7 @@ static bool __oom_reap_task_mm(struct mm_struct *mm)
struct mmu_notifier_range range;
struct mmu_gather tlb;
- mmu_notifier_range_init(&range, MMU_NOTIFY_UNMAP, 0,
+ mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0,
mm, vma->vm_start,
vma->vm_end);
tlb_gather_mmu(&tlb, mm);
--
2.43.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v1 06/16] mm/oom_kill: factor out zapping of VMA into zap_vma_for_reaping()
2026-02-27 20:08 [PATCH v1 00/16] mm: cleanups around unmapping / zapping David Hildenbrand (Arm)
` (4 preceding siblings ...)
2026-02-27 20:08 ` [PATCH v1 05/16] mm/oom_kill: use MMU_NOTIFY_CLEAR in __oom_reap_task_mm() David Hildenbrand (Arm)
@ 2026-02-27 20:08 ` David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 07/16] mm/memory: rename unmap_single_vma() to __zap_vma_range() David Hildenbrand (Arm)
` (9 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: David Hildenbrand (Arm) @ 2026-02-27 20:08 UTC (permalink / raw)
To: linux-kernel
Cc: linux-mm @ kvack . org, David Hildenbrand (Arm),
Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Jann Horn,
Pedro Falcato, David Rientjes, Shakeel Butt,
Matthew Wilcox (Oracle),
Alice Ryhl, Madhavan Srinivasan, Michael Ellerman,
Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
Alexander Gordeev, Gerald Schaefer, Heiko Carstens,
Vasily Gorbik, Jarkko Sakkinen, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Greg Kroah-Hartman, Arve Hjønnevåg,
Todd Kjos, Christian Brauner, Carlos Llamas, Ian Abbott,
H Hartley Sweeten, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, David Airlie, Simona Vetter, Jason Gunthorpe,
Leon Romanovsky, Dimitri Sivanich, Arnd Bergmann,
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Peter Zijlstra, Arnaldo Carvalho de Melo, Namhyung Kim,
Andy Lutomirski, Vincenzo Frascino, Eric Dumazet, Neal Cardwell,
David S. Miller, David Ahern, Jakub Kicinski, Paolo Abeni,
Miguel Ojeda, linuxppc-dev, kvm, linux-s390, linux-sgx,
intel-gfx, dri-devel, linux-rdma, bpf, linux-perf-users,
linux-fsdevel, netdev, rust-for-linux, x86
Let's factor it out so we can turn unmap_page_range() into a static
function instead, and so oom reaping has a clean interface to call.
Note that hugetlb is not supported, because it would require a bunch of
hugetlb-specific further actions (see zap_page_range_single_batched()).
Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
mm/internal.h | 5 +----
mm/memory.c | 36 ++++++++++++++++++++++++++++++++----
mm/oom_kill.c | 15 +--------------
3 files changed, 34 insertions(+), 22 deletions(-)
diff --git a/mm/internal.h b/mm/internal.h
index 39ab37bb0e1d..df9190f7db0e 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -536,13 +536,10 @@ static inline void sync_with_folio_pmd_zap(struct mm_struct *mm, pmd_t *pmdp)
}
struct zap_details;
-void unmap_page_range(struct mmu_gather *tlb,
- struct vm_area_struct *vma,
- unsigned long addr, unsigned long end,
- struct zap_details *details);
void zap_page_range_single_batched(struct mmu_gather *tlb,
struct vm_area_struct *vma, unsigned long addr,
unsigned long size, struct zap_details *details);
+int zap_vma_for_reaping(struct vm_area_struct *vma);
int folio_unmap_invalidate(struct address_space *mapping, struct folio *folio,
gfp_t gfp);
diff --git a/mm/memory.c b/mm/memory.c
index e4154f03feac..621f38ae1425 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2054,10 +2054,9 @@ static inline unsigned long zap_p4d_range(struct mmu_gather *tlb,
return addr;
}
-void unmap_page_range(struct mmu_gather *tlb,
- struct vm_area_struct *vma,
- unsigned long addr, unsigned long end,
- struct zap_details *details)
+static void unmap_page_range(struct mmu_gather *tlb, struct vm_area_struct *vma,
+ unsigned long addr, unsigned long end,
+ struct zap_details *details)
{
pgd_t *pgd;
unsigned long next;
@@ -2115,6 +2114,35 @@ static void unmap_single_vma(struct mmu_gather *tlb,
}
}
+/**
+ * zap_vma_for_reaping - zap all page table entries in the vma without blocking
+ * @vma: The vma to zap.
+ *
+ * Zap all page table entries in the vma without blocking for use by the oom
+ * killer. Hugetlb vmas are not supported.
+ *
+ * Returns: 0 on success, -EBUSY if we would have to block.
+ */
+int zap_vma_for_reaping(struct vm_area_struct *vma)
+{
+ struct mmu_notifier_range range;
+ struct mmu_gather tlb;
+
+ VM_WARN_ON_ONCE(is_vm_hugetlb_page(vma));
+
+ mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, vma->vm_mm,
+ vma->vm_start, vma->vm_end);
+ tlb_gather_mmu(&tlb, vma->vm_mm);
+ if (mmu_notifier_invalidate_range_start_nonblock(&range)) {
+ tlb_finish_mmu(&tlb);
+ return -EBUSY;
+ }
+ unmap_page_range(&tlb, vma, range.start, range.end, NULL);
+ mmu_notifier_invalidate_range_end(&range);
+ tlb_finish_mmu(&tlb);
+ return 0;
+}
+
/**
* unmap_vmas - unmap a range of memory covered by a list of vma's
* @tlb: address of the caller's struct mmu_gather
diff --git a/mm/oom_kill.c b/mm/oom_kill.c
index 0ba56fcd10d5..54b7a8fe5136 100644
--- a/mm/oom_kill.c
+++ b/mm/oom_kill.c
@@ -548,21 +548,8 @@ static bool __oom_reap_task_mm(struct mm_struct *mm)
* count elevated without a good reason.
*/
if (vma_is_anonymous(vma) || !(vma->vm_flags & VM_SHARED)) {
- struct mmu_notifier_range range;
- struct mmu_gather tlb;
-
- mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0,
- mm, vma->vm_start,
- vma->vm_end);
- tlb_gather_mmu(&tlb, mm);
- if (mmu_notifier_invalidate_range_start_nonblock(&range)) {
- tlb_finish_mmu(&tlb);
+ if (zap_vma_for_reaping(vma))
ret = false;
- continue;
- }
- unmap_page_range(&tlb, vma, range.start, range.end, NULL);
- mmu_notifier_invalidate_range_end(&range);
- tlb_finish_mmu(&tlb);
}
}
--
2.43.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v1 07/16] mm/memory: rename unmap_single_vma() to __zap_vma_range()
2026-02-27 20:08 [PATCH v1 00/16] mm: cleanups around unmapping / zapping David Hildenbrand (Arm)
` (5 preceding siblings ...)
2026-02-27 20:08 ` [PATCH v1 06/16] mm/oom_kill: factor out zapping of VMA into zap_vma_for_reaping() David Hildenbrand (Arm)
@ 2026-02-27 20:08 ` David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 08/16] mm/memory: move adjusting of address range to unmap_vmas() David Hildenbrand (Arm)
` (8 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: David Hildenbrand (Arm) @ 2026-02-27 20:08 UTC (permalink / raw)
To: linux-kernel
Cc: linux-mm @ kvack . org, David Hildenbrand (Arm),
Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Jann Horn,
Pedro Falcato, David Rientjes, Shakeel Butt,
Matthew Wilcox (Oracle),
Alice Ryhl, Madhavan Srinivasan, Michael Ellerman,
Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
Alexander Gordeev, Gerald Schaefer, Heiko Carstens,
Vasily Gorbik, Jarkko Sakkinen, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Greg Kroah-Hartman, Arve Hjønnevåg,
Todd Kjos, Christian Brauner, Carlos Llamas, Ian Abbott,
H Hartley Sweeten, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, David Airlie, Simona Vetter, Jason Gunthorpe,
Leon Romanovsky, Dimitri Sivanich, Arnd Bergmann,
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Peter Zijlstra, Arnaldo Carvalho de Melo, Namhyung Kim,
Andy Lutomirski, Vincenzo Frascino, Eric Dumazet, Neal Cardwell,
David S. Miller, David Ahern, Jakub Kicinski, Paolo Abeni,
Miguel Ojeda, linuxppc-dev, kvm, linux-s390, linux-sgx,
intel-gfx, dri-devel, linux-rdma, bpf, linux-perf-users,
linux-fsdevel, netdev, rust-for-linux, x86
Let's rename it to better fit our new naming scheme.
Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
mm/memory.c | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/mm/memory.c b/mm/memory.c
index 621f38ae1425..f0aaec57a66b 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2074,7 +2074,7 @@ static void unmap_page_range(struct mmu_gather *tlb, struct vm_area_struct *vma,
}
-static void unmap_single_vma(struct mmu_gather *tlb,
+static void __zap_vma_range(struct mmu_gather *tlb,
struct vm_area_struct *vma, unsigned long start_addr,
unsigned long end_addr, struct zap_details *details)
{
@@ -2177,7 +2177,7 @@ void unmap_vmas(struct mmu_gather *tlb, struct unmap_desc *unmap)
unsigned long start = unmap->vma_start;
unsigned long end = unmap->vma_end;
hugetlb_zap_begin(vma, &start, &end);
- unmap_single_vma(tlb, vma, start, end, &details);
+ __zap_vma_range(tlb, vma, start, end, &details);
hugetlb_zap_end(vma, &details);
vma = mas_find(unmap->mas, unmap->tree_end - 1);
} while (vma);
@@ -2213,7 +2213,7 @@ void zap_page_range_single_batched(struct mmu_gather *tlb,
* unmap 'address-end' not 'range.start-range.end' as range
* could have been expanded for hugetlb pmd sharing.
*/
- unmap_single_vma(tlb, vma, address, end, details);
+ __zap_vma_range(tlb, vma, address, end, details);
mmu_notifier_invalidate_range_end(&range);
if (is_vm_hugetlb_page(vma)) {
/*
--
2.43.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v1 08/16] mm/memory: move adjusting of address range to unmap_vmas()
2026-02-27 20:08 [PATCH v1 00/16] mm: cleanups around unmapping / zapping David Hildenbrand (Arm)
` (6 preceding siblings ...)
2026-02-27 20:08 ` [PATCH v1 07/16] mm/memory: rename unmap_single_vma() to __zap_vma_range() David Hildenbrand (Arm)
@ 2026-02-27 20:08 ` David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 09/16] mm/memory: convert details->even_cows into details->skip_cows David Hildenbrand (Arm)
` (7 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: David Hildenbrand (Arm) @ 2026-02-27 20:08 UTC (permalink / raw)
To: linux-kernel
Cc: linux-mm @ kvack . org, David Hildenbrand (Arm),
Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Jann Horn,
Pedro Falcato, David Rientjes, Shakeel Butt,
Matthew Wilcox (Oracle),
Alice Ryhl, Madhavan Srinivasan, Michael Ellerman,
Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
Alexander Gordeev, Gerald Schaefer, Heiko Carstens,
Vasily Gorbik, Jarkko Sakkinen, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Greg Kroah-Hartman, Arve Hjønnevåg,
Todd Kjos, Christian Brauner, Carlos Llamas, Ian Abbott,
H Hartley Sweeten, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, David Airlie, Simona Vetter, Jason Gunthorpe,
Leon Romanovsky, Dimitri Sivanich, Arnd Bergmann,
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Peter Zijlstra, Arnaldo Carvalho de Melo, Namhyung Kim,
Andy Lutomirski, Vincenzo Frascino, Eric Dumazet, Neal Cardwell,
David S. Miller, David Ahern, Jakub Kicinski, Paolo Abeni,
Miguel Ojeda, linuxppc-dev, kvm, linux-s390, linux-sgx,
intel-gfx, dri-devel, linux-rdma, bpf, linux-perf-users,
linux-fsdevel, netdev, rust-for-linux, x86
__zap_vma_range() has two callers, whereby
zap_page_range_single_batched() documents that the range must fit into
the VMA range.
So move adjusting the range to unmap_vmas() where it is actually
required and add a safety check in __zap_vma_range() instead. In
unmap_vmas(), we'd never expect to have empty ranges (otherwise, why
have the vma in there in the first place).
__zap_vma_range() will no longer be called with start == end, so
cleanup the function a bit. While at it, simplify the overly long
comment to its core message.
We will no longer call uprobe_munmap() for start == end, which actually
seems to be the right thing to do.
Note that hugetlb_zap_begin()->...->adjust_range_if_pmd_sharing_possible()
cannot result in the range exceeding the vma range.
Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
mm/memory.c | 58 +++++++++++++++++++++--------------------------------
1 file changed, 23 insertions(+), 35 deletions(-)
diff --git a/mm/memory.c b/mm/memory.c
index f0aaec57a66b..fdcd2abf29c2 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2073,44 +2073,28 @@ static void unmap_page_range(struct mmu_gather *tlb, struct vm_area_struct *vma,
tlb_end_vma(tlb, vma);
}
-
-static void __zap_vma_range(struct mmu_gather *tlb,
- struct vm_area_struct *vma, unsigned long start_addr,
- unsigned long end_addr, struct zap_details *details)
+static void __zap_vma_range(struct mmu_gather *tlb, struct vm_area_struct *vma,
+ unsigned long start, unsigned long end,
+ struct zap_details *details)
{
- unsigned long start = max(vma->vm_start, start_addr);
- unsigned long end;
-
- if (start >= vma->vm_end)
- return;
- end = min(vma->vm_end, end_addr);
- if (end <= vma->vm_start)
- return;
+ VM_WARN_ON_ONCE(start >= end || !range_in_vma(vma, start, end));
if (vma->vm_file)
uprobe_munmap(vma, start, end);
- if (start != end) {
- if (unlikely(is_vm_hugetlb_page(vma))) {
- /*
- * It is undesirable to test vma->vm_file as it
- * should be non-null for valid hugetlb area.
- * However, vm_file will be NULL in the error
- * cleanup path of mmap_region. When
- * hugetlbfs ->mmap method fails,
- * mmap_region() nullifies vma->vm_file
- * before calling this function to clean up.
- * Since no pte has actually been setup, it is
- * safe to do nothing in this case.
- */
- if (vma->vm_file) {
- zap_flags_t zap_flags = details ?
- details->zap_flags : 0;
- __unmap_hugepage_range(tlb, vma, start, end,
- NULL, zap_flags);
- }
- } else
- unmap_page_range(tlb, vma, start, end, details);
+ if (unlikely(is_vm_hugetlb_page(vma))) {
+ zap_flags_t zap_flags = details ? details->zap_flags : 0;
+
+ /*
+ * vm_file will be NULL when we fail early while instantiating
+ * a new mapping. In this case, no pages were mapped yet and
+ * there is nothing to do.
+ */
+ if (!vma->vm_file)
+ return;
+ __unmap_hugepage_range(tlb, vma, start, end, NULL, zap_flags);
+ } else {
+ unmap_page_range(tlb, vma, start, end, details);
}
}
@@ -2174,8 +2158,9 @@ void unmap_vmas(struct mmu_gather *tlb, struct unmap_desc *unmap)
unmap->vma_start, unmap->vma_end);
mmu_notifier_invalidate_range_start(&range);
do {
- unsigned long start = unmap->vma_start;
- unsigned long end = unmap->vma_end;
+ unsigned long start = max(vma->vm_start, unmap->vma_start);
+ unsigned long end = min(vma->vm_end, unmap->vma_end);
+
hugetlb_zap_begin(vma, &start, &end);
__zap_vma_range(tlb, vma, start, end, &details);
hugetlb_zap_end(vma, &details);
@@ -2204,6 +2189,9 @@ void zap_page_range_single_batched(struct mmu_gather *tlb,
VM_WARN_ON_ONCE(!tlb || tlb->mm != vma->vm_mm);
+ if (unlikely(!size))
+ return;
+
mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, vma->vm_mm,
address, end);
hugetlb_zap_begin(vma, &range.start, &range.end);
--
2.43.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v1 09/16] mm/memory: convert details->even_cows into details->skip_cows
2026-02-27 20:08 [PATCH v1 00/16] mm: cleanups around unmapping / zapping David Hildenbrand (Arm)
` (7 preceding siblings ...)
2026-02-27 20:08 ` [PATCH v1 08/16] mm/memory: move adjusting of address range to unmap_vmas() David Hildenbrand (Arm)
@ 2026-02-27 20:08 ` David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 10/16] mm/memory: use __zap_vma_range() in zap_vma_for_reaping() David Hildenbrand (Arm)
` (6 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: David Hildenbrand (Arm) @ 2026-02-27 20:08 UTC (permalink / raw)
To: linux-kernel
Cc: linux-mm @ kvack . org, David Hildenbrand (Arm),
Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Jann Horn,
Pedro Falcato, David Rientjes, Shakeel Butt,
Matthew Wilcox (Oracle),
Alice Ryhl, Madhavan Srinivasan, Michael Ellerman,
Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
Alexander Gordeev, Gerald Schaefer, Heiko Carstens,
Vasily Gorbik, Jarkko Sakkinen, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Greg Kroah-Hartman, Arve Hjønnevåg,
Todd Kjos, Christian Brauner, Carlos Llamas, Ian Abbott,
H Hartley Sweeten, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, David Airlie, Simona Vetter, Jason Gunthorpe,
Leon Romanovsky, Dimitri Sivanich, Arnd Bergmann,
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Peter Zijlstra, Arnaldo Carvalho de Melo, Namhyung Kim,
Andy Lutomirski, Vincenzo Frascino, Eric Dumazet, Neal Cardwell,
David S. Miller, David Ahern, Jakub Kicinski, Paolo Abeni,
Miguel Ojeda, linuxppc-dev, kvm, linux-s390, linux-sgx,
intel-gfx, dri-devel, linux-rdma, bpf, linux-perf-users,
linux-fsdevel, netdev, rust-for-linux, x86
The current semantics are confusing: simply because someone specifies an
empty zap_detail struct suddenly makes should_zap_cows() behave
differently. The default should be to also zap CoW'ed anonymous pages.
Really only unmap_mapping_pages() and friends want to skip zapping of
these anon folios.
So let's invert the meaning; turn the confusing "reclaim_pt" check that
overrides other properties in should_zap_cows() into a safety check.
Note that the only caller that sets reclaim_pt=true is
madvise_dontneed_single_vma(), which wants to zap any pages.
Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
include/linux/mm.h | 2 +-
mm/madvise.c | 1 -
mm/memory.c | 12 ++++++------
3 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index d3ef586ee1c0..21b67c203e62 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2798,7 +2798,7 @@ extern void pagefault_out_of_memory(void);
*/
struct zap_details {
struct folio *single_folio; /* Locked folio to be unmapped */
- bool even_cows; /* Zap COWed private pages too? */
+ bool skip_cows; /* Do not zap COWed private pages */
bool reclaim_pt; /* Need reclaim page tables? */
zap_flags_t zap_flags; /* Extra flags for zapping */
};
diff --git a/mm/madvise.c b/mm/madvise.c
index 557a360f7919..b51f216934f3 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -853,7 +853,6 @@ static long madvise_dontneed_single_vma(struct madvise_behavior *madv_behavior)
struct madvise_behavior_range *range = &madv_behavior->range;
struct zap_details details = {
.reclaim_pt = true,
- .even_cows = true,
};
zap_page_range_single_batched(
diff --git a/mm/memory.c b/mm/memory.c
index fdcd2abf29c2..7d7c24c6917c 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1554,11 +1554,13 @@ copy_page_range(struct vm_area_struct *dst_vma, struct vm_area_struct *src_vma)
static inline bool should_zap_cows(struct zap_details *details)
{
/* By default, zap all pages */
- if (!details || details->reclaim_pt)
+ if (!details)
return true;
+ VM_WARN_ON_ONCE(details->skip_cows && details->reclaim_pt);
+
/* Or, we zap COWed pages only if the caller wants to */
- return details->even_cows;
+ return !details->skip_cows;
}
/* Decides whether we should zap this folio with the folio pointer specified */
@@ -2149,8 +2151,6 @@ void unmap_vmas(struct mmu_gather *tlb, struct unmap_desc *unmap)
struct mmu_notifier_range range;
struct zap_details details = {
.zap_flags = ZAP_FLAG_DROP_MARKER | ZAP_FLAG_UNMAP,
- /* Careful - we need to zap private pages too! */
- .even_cows = true,
};
vma = unmap->first;
@@ -4282,7 +4282,7 @@ void unmap_mapping_folio(struct folio *folio)
first_index = folio->index;
last_index = folio_next_index(folio) - 1;
- details.even_cows = false;
+ details.skip_cows = true;
details.single_folio = folio;
details.zap_flags = ZAP_FLAG_DROP_MARKER;
@@ -4312,7 +4312,7 @@ void unmap_mapping_pages(struct address_space *mapping, pgoff_t start,
pgoff_t first_index = start;
pgoff_t last_index = start + nr - 1;
- details.even_cows = even_cows;
+ details.skip_cows = !even_cows;
if (last_index < first_index)
last_index = ULONG_MAX;
--
2.43.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v1 10/16] mm/memory: use __zap_vma_range() in zap_vma_for_reaping()
2026-02-27 20:08 [PATCH v1 00/16] mm: cleanups around unmapping / zapping David Hildenbrand (Arm)
` (8 preceding siblings ...)
2026-02-27 20:08 ` [PATCH v1 09/16] mm/memory: convert details->even_cows into details->skip_cows David Hildenbrand (Arm)
@ 2026-02-27 20:08 ` David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 11/16] mm/memory: inline unmap_page_range() into __zap_vma_range() David Hildenbrand (Arm)
` (5 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: David Hildenbrand (Arm) @ 2026-02-27 20:08 UTC (permalink / raw)
To: linux-kernel
Cc: linux-mm @ kvack . org, David Hildenbrand (Arm),
Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Jann Horn,
Pedro Falcato, David Rientjes, Shakeel Butt,
Matthew Wilcox (Oracle),
Alice Ryhl, Madhavan Srinivasan, Michael Ellerman,
Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
Alexander Gordeev, Gerald Schaefer, Heiko Carstens,
Vasily Gorbik, Jarkko Sakkinen, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Greg Kroah-Hartman, Arve Hjønnevåg,
Todd Kjos, Christian Brauner, Carlos Llamas, Ian Abbott,
H Hartley Sweeten, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, David Airlie, Simona Vetter, Jason Gunthorpe,
Leon Romanovsky, Dimitri Sivanich, Arnd Bergmann,
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Peter Zijlstra, Arnaldo Carvalho de Melo, Namhyung Kim,
Andy Lutomirski, Vincenzo Frascino, Eric Dumazet, Neal Cardwell,
David S. Miller, David Ahern, Jakub Kicinski, Paolo Abeni,
Miguel Ojeda, linuxppc-dev, kvm, linux-s390, linux-sgx,
intel-gfx, dri-devel, linux-rdma, bpf, linux-perf-users,
linux-fsdevel, netdev, rust-for-linux, x86
Let's call __zap_vma_range() instead of unmap_page_range() to prepare
for further cleanups.
To keep the existing behavior, whereby we do not call uprobe_munmap()
which could block, add a new "reaping" member to zap_details and use it.
Likely we should handle the possible blocking in uprobe_munmap()
differently, but for now keep it unchanged.
Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
include/linux/mm.h | 1 +
mm/memory.c | 13 +++++++++----
2 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 21b67c203e62..4710f7c7495a 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2800,6 +2800,7 @@ struct zap_details {
struct folio *single_folio; /* Locked folio to be unmapped */
bool skip_cows; /* Do not zap COWed private pages */
bool reclaim_pt; /* Need reclaim page tables? */
+ bool reaping; /* Reaping, do not block. */
zap_flags_t zap_flags; /* Extra flags for zapping */
};
diff --git a/mm/memory.c b/mm/memory.c
index 7d7c24c6917c..394b2e931974 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2079,14 +2079,18 @@ static void __zap_vma_range(struct mmu_gather *tlb, struct vm_area_struct *vma,
unsigned long start, unsigned long end,
struct zap_details *details)
{
+ const bool reaping = details && details->reaping;
+
VM_WARN_ON_ONCE(start >= end || !range_in_vma(vma, start, end));
- if (vma->vm_file)
+ /* uprobe_munmap() might sleep, so skip it when reaping. */
+ if (vma->vm_file && !reaping)
uprobe_munmap(vma, start, end);
if (unlikely(is_vm_hugetlb_page(vma))) {
zap_flags_t zap_flags = details ? details->zap_flags : 0;
+ VM_WARN_ON_ONCE(reaping);
/*
* vm_file will be NULL when we fail early while instantiating
* a new mapping. In this case, no pages were mapped yet and
@@ -2111,11 +2115,12 @@ static void __zap_vma_range(struct mmu_gather *tlb, struct vm_area_struct *vma,
*/
int zap_vma_for_reaping(struct vm_area_struct *vma)
{
+ struct zap_details details = {
+ .reaping = true,
+ };
struct mmu_notifier_range range;
struct mmu_gather tlb;
- VM_WARN_ON_ONCE(is_vm_hugetlb_page(vma));
-
mmu_notifier_range_init(&range, MMU_NOTIFY_CLEAR, 0, vma->vm_mm,
vma->vm_start, vma->vm_end);
tlb_gather_mmu(&tlb, vma->vm_mm);
@@ -2123,7 +2128,7 @@ int zap_vma_for_reaping(struct vm_area_struct *vma)
tlb_finish_mmu(&tlb);
return -EBUSY;
}
- unmap_page_range(&tlb, vma, range.start, range.end, NULL);
+ __zap_vma_range(&tlb, vma, range.start, range.end, &details);
mmu_notifier_invalidate_range_end(&range);
tlb_finish_mmu(&tlb);
return 0;
--
2.43.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v1 11/16] mm/memory: inline unmap_page_range() into __zap_vma_range()
2026-02-27 20:08 [PATCH v1 00/16] mm: cleanups around unmapping / zapping David Hildenbrand (Arm)
` (9 preceding siblings ...)
2026-02-27 20:08 ` [PATCH v1 10/16] mm/memory: use __zap_vma_range() in zap_vma_for_reaping() David Hildenbrand (Arm)
@ 2026-02-27 20:08 ` David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 12/16] mm: rename zap_vma_pages() to zap_vma() David Hildenbrand (Arm)
` (4 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: David Hildenbrand (Arm) @ 2026-02-27 20:08 UTC (permalink / raw)
To: linux-kernel
Cc: linux-mm @ kvack . org, David Hildenbrand (Arm),
Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Jann Horn,
Pedro Falcato, David Rientjes, Shakeel Butt,
Matthew Wilcox (Oracle),
Alice Ryhl, Madhavan Srinivasan, Michael Ellerman,
Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
Alexander Gordeev, Gerald Schaefer, Heiko Carstens,
Vasily Gorbik, Jarkko Sakkinen, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Greg Kroah-Hartman, Arve Hjønnevåg,
Todd Kjos, Christian Brauner, Carlos Llamas, Ian Abbott,
H Hartley Sweeten, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, David Airlie, Simona Vetter, Jason Gunthorpe,
Leon Romanovsky, Dimitri Sivanich, Arnd Bergmann,
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Peter Zijlstra, Arnaldo Carvalho de Melo, Namhyung Kim,
Andy Lutomirski, Vincenzo Frascino, Eric Dumazet, Neal Cardwell,
David S. Miller, David Ahern, Jakub Kicinski, Paolo Abeni,
Miguel Ojeda, linuxppc-dev, kvm, linux-s390, linux-sgx,
intel-gfx, dri-devel, linux-rdma, bpf, linux-perf-users,
linux-fsdevel, netdev, rust-for-linux, x86
Let's inline it into the single caller to reduce the number of confusing
unmap/zap helpers.
Get rid of the unnecessary BUG_ON().
Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
mm/memory.c | 32 ++++++++++++--------------------
1 file changed, 12 insertions(+), 20 deletions(-)
diff --git a/mm/memory.c b/mm/memory.c
index 394b2e931974..1c0bcdfc73b7 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2056,25 +2056,6 @@ static inline unsigned long zap_p4d_range(struct mmu_gather *tlb,
return addr;
}
-static void unmap_page_range(struct mmu_gather *tlb, struct vm_area_struct *vma,
- unsigned long addr, unsigned long end,
- struct zap_details *details)
-{
- pgd_t *pgd;
- unsigned long next;
-
- BUG_ON(addr >= end);
- tlb_start_vma(tlb, vma);
- pgd = pgd_offset(vma->vm_mm, addr);
- do {
- next = pgd_addr_end(addr, end);
- if (pgd_none_or_clear_bad(pgd))
- continue;
- next = zap_p4d_range(tlb, vma, pgd, addr, next, details);
- } while (pgd++, addr = next, addr != end);
- tlb_end_vma(tlb, vma);
-}
-
static void __zap_vma_range(struct mmu_gather *tlb, struct vm_area_struct *vma,
unsigned long start, unsigned long end,
struct zap_details *details)
@@ -2100,7 +2081,18 @@ static void __zap_vma_range(struct mmu_gather *tlb, struct vm_area_struct *vma,
return;
__unmap_hugepage_range(tlb, vma, start, end, NULL, zap_flags);
} else {
- unmap_page_range(tlb, vma, start, end, details);
+ unsigned long next, cur = start;
+ pgd_t *pgd;
+
+ tlb_start_vma(tlb, vma);
+ pgd = pgd_offset(vma->vm_mm, cur);
+ do {
+ next = pgd_addr_end(cur, end);
+ if (pgd_none_or_clear_bad(pgd))
+ continue;
+ next = zap_p4d_range(tlb, vma, pgd, cur, next, details);
+ } while (pgd++, cur = next, cur != end);
+ tlb_end_vma(tlb, vma);
}
}
--
2.43.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v1 12/16] mm: rename zap_vma_pages() to zap_vma()
2026-02-27 20:08 [PATCH v1 00/16] mm: cleanups around unmapping / zapping David Hildenbrand (Arm)
` (10 preceding siblings ...)
2026-02-27 20:08 ` [PATCH v1 11/16] mm/memory: inline unmap_page_range() into __zap_vma_range() David Hildenbrand (Arm)
@ 2026-02-27 20:08 ` David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 13/16] mm: rename zap_page_range_single_batched() to zap_vma_range_batched() David Hildenbrand (Arm)
` (3 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: David Hildenbrand (Arm) @ 2026-02-27 20:08 UTC (permalink / raw)
To: linux-kernel
Cc: linux-mm @ kvack . org, David Hildenbrand (Arm),
Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Jann Horn,
Pedro Falcato, David Rientjes, Shakeel Butt,
Matthew Wilcox (Oracle),
Alice Ryhl, Madhavan Srinivasan, Michael Ellerman,
Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
Alexander Gordeev, Gerald Schaefer, Heiko Carstens,
Vasily Gorbik, Jarkko Sakkinen, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Greg Kroah-Hartman, Arve Hjønnevåg,
Todd Kjos, Christian Brauner, Carlos Llamas, Ian Abbott,
H Hartley Sweeten, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, David Airlie, Simona Vetter, Jason Gunthorpe,
Leon Romanovsky, Dimitri Sivanich, Arnd Bergmann,
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Peter Zijlstra, Arnaldo Carvalho de Melo, Namhyung Kim,
Andy Lutomirski, Vincenzo Frascino, Eric Dumazet, Neal Cardwell,
David S. Miller, David Ahern, Jakub Kicinski, Paolo Abeni,
Miguel Ojeda, linuxppc-dev, kvm, linux-s390, linux-sgx,
intel-gfx, dri-devel, linux-rdma, bpf, linux-perf-users,
linux-fsdevel, netdev, rust-for-linux, x86
Let's rename it to an even simpler name. While at it, add some
simplistic kernel doc.
Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
arch/powerpc/platforms/book3s/vas-api.c | 2 +-
arch/powerpc/platforms/pseries/vas.c | 2 +-
include/linux/mm.h | 6 +++++-
lib/vdso/datastore.c | 2 +-
mm/page-writeback.c | 2 +-
5 files changed, 9 insertions(+), 5 deletions(-)
diff --git a/arch/powerpc/platforms/book3s/vas-api.c b/arch/powerpc/platforms/book3s/vas-api.c
index ea4ffa63f043..e96d79db69fe 100644
--- a/arch/powerpc/platforms/book3s/vas-api.c
+++ b/arch/powerpc/platforms/book3s/vas-api.c
@@ -414,7 +414,7 @@ static vm_fault_t vas_mmap_fault(struct vm_fault *vmf)
/*
* When the LPAR lost credits due to core removal or during
* migration, invalidate the existing mapping for the current
- * paste addresses and set windows in-active (zap_vma_pages in
+ * paste addresses and set windows in-active (zap_vma() in
* reconfig_close_windows()).
* New mapping will be done later after migration or new credits
* available. So continue to receive faults if the user space
diff --git a/arch/powerpc/platforms/pseries/vas.c b/arch/powerpc/platforms/pseries/vas.c
index ceb0a8788c0a..fa05f04364fe 100644
--- a/arch/powerpc/platforms/pseries/vas.c
+++ b/arch/powerpc/platforms/pseries/vas.c
@@ -807,7 +807,7 @@ static int reconfig_close_windows(struct vas_caps *vcap, int excess_creds,
* is done before the original mmap() and after the ioctl.
*/
if (vma)
- zap_vma_pages(vma);
+ zap_vma(vma);
mutex_unlock(&task_ref->mmap_mutex);
mmap_write_unlock(task_ref->mm);
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 4710f7c7495a..4bd1500b9630 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2837,7 +2837,11 @@ void zap_vma_ptes(struct vm_area_struct *vma, unsigned long address,
unsigned long size);
void zap_page_range_single(struct vm_area_struct *vma, unsigned long address,
unsigned long size);
-static inline void zap_vma_pages(struct vm_area_struct *vma)
+/**
+ * zap_vma - zap all page table entries in a vma
+ * @vma: The vma to zap.
+ */
+static inline void zap_vma(struct vm_area_struct *vma)
{
zap_page_range_single(vma, vma->vm_start, vma->vm_end - vma->vm_start);
}
diff --git a/lib/vdso/datastore.c b/lib/vdso/datastore.c
index a565c30c71a0..222c143aebf7 100644
--- a/lib/vdso/datastore.c
+++ b/lib/vdso/datastore.c
@@ -121,7 +121,7 @@ int vdso_join_timens(struct task_struct *task, struct time_namespace *ns)
mmap_read_lock(mm);
for_each_vma(vmi, vma) {
if (vma_is_special_mapping(vma, &vdso_vvar_mapping))
- zap_vma_pages(vma);
+ zap_vma(vma);
}
mmap_read_unlock(mm);
diff --git a/mm/page-writeback.c b/mm/page-writeback.c
index 601a5e048d12..29f7567e5a71 100644
--- a/mm/page-writeback.c
+++ b/mm/page-writeback.c
@@ -2645,7 +2645,7 @@ void folio_account_cleaned(struct folio *folio, struct bdi_writeback *wb)
* while this function is in progress, although it may have been truncated
* before this function is called. Most callers have the folio locked.
* A few have the folio blocked from truncation through other means (e.g.
- * zap_vma_pages() has it mapped and is holding the page table lock).
+ * zap_vma() has it mapped and is holding the page table lock).
* When called from mark_buffer_dirty(), the filesystem should hold a
* reference to the buffer_head that is being marked dirty, which causes
* try_to_free_buffers() to fail.
--
2.43.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v1 13/16] mm: rename zap_page_range_single_batched() to zap_vma_range_batched()
2026-02-27 20:08 [PATCH v1 00/16] mm: cleanups around unmapping / zapping David Hildenbrand (Arm)
` (11 preceding siblings ...)
2026-02-27 20:08 ` [PATCH v1 12/16] mm: rename zap_vma_pages() to zap_vma() David Hildenbrand (Arm)
@ 2026-02-27 20:08 ` David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 14/16] mm: rename zap_page_range_single() to zap_vma_range() David Hildenbrand (Arm)
` (2 subsequent siblings)
15 siblings, 0 replies; 17+ messages in thread
From: David Hildenbrand (Arm) @ 2026-02-27 20:08 UTC (permalink / raw)
To: linux-kernel
Cc: linux-mm @ kvack . org, David Hildenbrand (Arm),
Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Jann Horn,
Pedro Falcato, David Rientjes, Shakeel Butt,
Matthew Wilcox (Oracle),
Alice Ryhl, Madhavan Srinivasan, Michael Ellerman,
Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
Alexander Gordeev, Gerald Schaefer, Heiko Carstens,
Vasily Gorbik, Jarkko Sakkinen, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Greg Kroah-Hartman, Arve Hjønnevåg,
Todd Kjos, Christian Brauner, Carlos Llamas, Ian Abbott,
H Hartley Sweeten, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, David Airlie, Simona Vetter, Jason Gunthorpe,
Leon Romanovsky, Dimitri Sivanich, Arnd Bergmann,
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Peter Zijlstra, Arnaldo Carvalho de Melo, Namhyung Kim,
Andy Lutomirski, Vincenzo Frascino, Eric Dumazet, Neal Cardwell,
David S. Miller, David Ahern, Jakub Kicinski, Paolo Abeni,
Miguel Ojeda, linuxppc-dev, kvm, linux-s390, linux-sgx,
intel-gfx, dri-devel, linux-rdma, bpf, linux-perf-users,
linux-fsdevel, netdev, rust-for-linux, x86
Let's make the naming more consistent with our new naming scheme.
While at it, polish the kerneldoc a bit.
Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
mm/internal.h | 2 +-
mm/madvise.c | 5 ++---
mm/memory.c | 23 +++++++++++++----------
3 files changed, 16 insertions(+), 14 deletions(-)
diff --git a/mm/internal.h b/mm/internal.h
index df9190f7db0e..15a1b3f0a6d1 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -536,7 +536,7 @@ static inline void sync_with_folio_pmd_zap(struct mm_struct *mm, pmd_t *pmdp)
}
struct zap_details;
-void zap_page_range_single_batched(struct mmu_gather *tlb,
+void zap_vma_range_batched(struct mmu_gather *tlb,
struct vm_area_struct *vma, unsigned long addr,
unsigned long size, struct zap_details *details);
int zap_vma_for_reaping(struct vm_area_struct *vma);
diff --git a/mm/madvise.c b/mm/madvise.c
index b51f216934f3..fb5fcdff2b66 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -855,9 +855,8 @@ static long madvise_dontneed_single_vma(struct madvise_behavior *madv_behavior)
.reclaim_pt = true,
};
- zap_page_range_single_batched(
- madv_behavior->tlb, madv_behavior->vma, range->start,
- range->end - range->start, &details);
+ zap_vma_range_batched(madv_behavior->tlb, madv_behavior->vma,
+ range->start, range->end - range->start, &details);
return 0;
}
diff --git a/mm/memory.c b/mm/memory.c
index 1c0bcdfc73b7..e611e9af4e85 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2167,17 +2167,20 @@ void unmap_vmas(struct mmu_gather *tlb, struct unmap_desc *unmap)
}
/**
- * zap_page_range_single_batched - remove user pages in a given range
+ * zap_vma_range_batched - zap page table entries in a vma range
* @tlb: pointer to the caller's struct mmu_gather
- * @vma: vm_area_struct holding the applicable pages
- * @address: starting address of pages to remove
- * @size: number of bytes to remove
- * @details: details of shared cache invalidation
+ * @vma: the vma covering the range to zap
+ * @address: starting address of the range to zap
+ * @size: number of bytes to zap
+ * @details: details specifying zapping behavior
+ *
+ * @tlb must not be NULL. The provided address range must be fully
+ * contained within @vma. If @vma is for hugetlb, @tlb is flushed and
+ * re-initialized by this function.
*
- * @tlb shouldn't be NULL. The range must fit into one VMA. If @vma is for
- * hugetlb, @tlb is flushed and re-initialized by this function.
+ * If @details is NULL, this function will zap all page table entries.
*/
-void zap_page_range_single_batched(struct mmu_gather *tlb,
+void zap_vma_range_batched(struct mmu_gather *tlb,
struct vm_area_struct *vma, unsigned long address,
unsigned long size, struct zap_details *details)
{
@@ -2225,7 +2228,7 @@ void zap_page_range_single(struct vm_area_struct *vma, unsigned long address,
struct mmu_gather tlb;
tlb_gather_mmu(&tlb, vma->vm_mm);
- zap_page_range_single_batched(&tlb, vma, address, size, NULL);
+ zap_vma_range_batched(&tlb, vma, address, size, NULL);
tlb_finish_mmu(&tlb);
}
@@ -4251,7 +4254,7 @@ static inline void unmap_mapping_range_tree(struct rb_root_cached *root,
size = (end_idx - start_idx) << PAGE_SHIFT;
tlb_gather_mmu(&tlb, vma->vm_mm);
- zap_page_range_single_batched(&tlb, vma, start, size, details);
+ zap_vma_range_batched(&tlb, vma, start, size, details);
tlb_finish_mmu(&tlb);
}
}
--
2.43.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v1 14/16] mm: rename zap_page_range_single() to zap_vma_range()
2026-02-27 20:08 [PATCH v1 00/16] mm: cleanups around unmapping / zapping David Hildenbrand (Arm)
` (12 preceding siblings ...)
2026-02-27 20:08 ` [PATCH v1 13/16] mm: rename zap_page_range_single_batched() to zap_vma_range_batched() David Hildenbrand (Arm)
@ 2026-02-27 20:08 ` David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 15/16] mm: rename zap_vma_ptes() to zap_special_vma_range() David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 16/16] mm/memory: support VM_MIXEDMAP in zap_special_vma_range() David Hildenbrand (Arm)
15 siblings, 0 replies; 17+ messages in thread
From: David Hildenbrand (Arm) @ 2026-02-27 20:08 UTC (permalink / raw)
To: linux-kernel
Cc: linux-mm @ kvack . org, David Hildenbrand (Arm),
Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Jann Horn,
Pedro Falcato, David Rientjes, Shakeel Butt,
Matthew Wilcox (Oracle),
Alice Ryhl, Madhavan Srinivasan, Michael Ellerman,
Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
Alexander Gordeev, Gerald Schaefer, Heiko Carstens,
Vasily Gorbik, Jarkko Sakkinen, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Greg Kroah-Hartman, Arve Hjønnevåg,
Todd Kjos, Christian Brauner, Carlos Llamas, Ian Abbott,
H Hartley Sweeten, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, David Airlie, Simona Vetter, Jason Gunthorpe,
Leon Romanovsky, Dimitri Sivanich, Arnd Bergmann,
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Peter Zijlstra, Arnaldo Carvalho de Melo, Namhyung Kim,
Andy Lutomirski, Vincenzo Frascino, Eric Dumazet, Neal Cardwell,
David S. Miller, David Ahern, Jakub Kicinski, Paolo Abeni,
Miguel Ojeda, linuxppc-dev, kvm, linux-s390, linux-sgx,
intel-gfx, dri-devel, linux-rdma, bpf, linux-perf-users,
linux-fsdevel, netdev, rust-for-linux, x86
Let's rename it to make it better match our new naming scheme.
While at it, polish the kerneldoc.
Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
arch/s390/mm/gmap_helpers.c | 2 +-
drivers/android/binder/page_range.rs | 4 ++--
drivers/android/binder_alloc.c | 2 +-
include/linux/mm.h | 4 ++--
kernel/bpf/arena.c | 2 +-
kernel/events/core.c | 2 +-
mm/madvise.c | 4 ++--
mm/memory.c | 14 +++++++-------
net/ipv4/tcp.c | 6 +++---
rust/kernel/mm/virt.rs | 4 ++--
10 files changed, 22 insertions(+), 22 deletions(-)
diff --git a/arch/s390/mm/gmap_helpers.c b/arch/s390/mm/gmap_helpers.c
index ae2d59a19313..f8789ffcc05c 100644
--- a/arch/s390/mm/gmap_helpers.c
+++ b/arch/s390/mm/gmap_helpers.c
@@ -89,7 +89,7 @@ void gmap_helper_discard(struct mm_struct *mm, unsigned long vmaddr, unsigned lo
if (!vma)
return;
if (!is_vm_hugetlb_page(vma))
- zap_page_range_single(vma, vmaddr, min(end, vma->vm_end) - vmaddr);
+ zap_vma_range(vma, vmaddr, min(end, vma->vm_end) - vmaddr);
vmaddr = vma->vm_end;
}
}
diff --git a/drivers/android/binder/page_range.rs b/drivers/android/binder/page_range.rs
index fdd97112ef5c..2fddd4ed8d4c 100644
--- a/drivers/android/binder/page_range.rs
+++ b/drivers/android/binder/page_range.rs
@@ -130,7 +130,7 @@ pub(crate) struct ShrinkablePageRange {
pid: Pid,
/// The mm for the relevant process.
mm: ARef<Mm>,
- /// Used to synchronize calls to `vm_insert_page` and `zap_page_range_single`.
+ /// Used to synchronize calls to `vm_insert_page` and `zap_vma_range`.
#[pin]
mm_lock: Mutex<()>,
/// Spinlock protecting changes to pages.
@@ -719,7 +719,7 @@ fn drop(self: Pin<&mut Self>) {
if let Some(vma) = mmap_read.vma_lookup(vma_addr) {
let user_page_addr = vma_addr + (page_index << PAGE_SHIFT);
- vma.zap_page_range_single(user_page_addr, PAGE_SIZE);
+ vma.zap_vma_range(user_page_addr, PAGE_SIZE);
}
drop(mmap_read);
diff --git a/drivers/android/binder_alloc.c b/drivers/android/binder_alloc.c
index dd2046bd5cde..e4488ad86a65 100644
--- a/drivers/android/binder_alloc.c
+++ b/drivers/android/binder_alloc.c
@@ -1185,7 +1185,7 @@ enum lru_status binder_alloc_free_page(struct list_head *item,
if (vma) {
trace_binder_unmap_user_start(alloc, index);
- zap_page_range_single(vma, page_addr, PAGE_SIZE);
+ zap_vma_range(vma, page_addr, PAGE_SIZE);
trace_binder_unmap_user_end(alloc, index);
}
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 4bd1500b9630..833bedd3f739 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2835,7 +2835,7 @@ struct page *vm_normal_page_pud(struct vm_area_struct *vma, unsigned long addr,
void zap_vma_ptes(struct vm_area_struct *vma, unsigned long address,
unsigned long size);
-void zap_page_range_single(struct vm_area_struct *vma, unsigned long address,
+void zap_vma_range(struct vm_area_struct *vma, unsigned long address,
unsigned long size);
/**
* zap_vma - zap all page table entries in a vma
@@ -2843,7 +2843,7 @@ void zap_page_range_single(struct vm_area_struct *vma, unsigned long address,
*/
static inline void zap_vma(struct vm_area_struct *vma)
{
- zap_page_range_single(vma, vma->vm_start, vma->vm_end - vma->vm_start);
+ zap_vma_range(vma, vma->vm_start, vma->vm_end - vma->vm_start);
}
struct mmu_notifier_range;
diff --git a/kernel/bpf/arena.c b/kernel/bpf/arena.c
index c34510d83b1f..37843c6a4764 100644
--- a/kernel/bpf/arena.c
+++ b/kernel/bpf/arena.c
@@ -656,7 +656,7 @@ static void zap_pages(struct bpf_arena *arena, long uaddr, long page_cnt)
guard(mutex)(&arena->lock);
/* iterate link list under lock */
list_for_each_entry(vml, &arena->vma_list, head)
- zap_page_range_single(vml->vma, uaddr, PAGE_SIZE * page_cnt);
+ zap_vma_range(vml->vma, uaddr, PAGE_SIZE * page_cnt);
}
static void arena_free_pages(struct bpf_arena *arena, long uaddr, long page_cnt, bool sleepable)
diff --git a/kernel/events/core.c b/kernel/events/core.c
index c94c56c94104..5ee02817c3bc 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -7215,7 +7215,7 @@ static int map_range(struct perf_buffer *rb, struct vm_area_struct *vma)
#ifdef CONFIG_MMU
/* Clear any partial mappings on error. */
if (err)
- zap_page_range_single(vma, vma->vm_start, nr_pages * PAGE_SIZE);
+ zap_vma_range(vma, vma->vm_start, nr_pages * PAGE_SIZE);
#endif
return err;
diff --git a/mm/madvise.c b/mm/madvise.c
index fb5fcdff2b66..6e66f56ff1a6 100644
--- a/mm/madvise.c
+++ b/mm/madvise.c
@@ -832,7 +832,7 @@ static int madvise_free_single_vma(struct madvise_behavior *madv_behavior)
* Application no longer needs these pages. If the pages are dirty,
* it's OK to just throw them away. The app will be more careful about
* data it wants to keep. Be sure to free swap resources too. The
- * zap_page_range_single call sets things up for shrink_active_list to actually
+ * zap_vma_range call sets things up for shrink_active_list to actually
* free these pages later if no one else has touched them in the meantime,
* although we could add these pages to a global reuse list for
* shrink_active_list to pick up before reclaiming other pages.
@@ -1191,7 +1191,7 @@ static long madvise_guard_install(struct madvise_behavior *madv_behavior)
* OK some of the range have non-guard pages mapped, zap
* them. This leaves existing guard pages in place.
*/
- zap_page_range_single(vma, range->start, range->end - range->start);
+ zap_vma_range(vma, range->start, range->end - range->start);
}
/*
diff --git a/mm/memory.c b/mm/memory.c
index e611e9af4e85..dd737b6d28c0 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2215,14 +2215,14 @@ void zap_vma_range_batched(struct mmu_gather *tlb,
}
/**
- * zap_page_range_single - remove user pages in a given range
- * @vma: vm_area_struct holding the applicable pages
- * @address: starting address of pages to zap
+ * zap_vma_range - zap all page table entries in a vma range
+ * @vma: the vma covering the range to zap
+ * @address: starting address of the range to zap
* @size: number of bytes to zap
*
- * The range must fit into one VMA.
+ * The provided address range must be fully contained within @vma.
*/
-void zap_page_range_single(struct vm_area_struct *vma, unsigned long address,
+void zap_vma_range(struct vm_area_struct *vma, unsigned long address,
unsigned long size)
{
struct mmu_gather tlb;
@@ -2250,7 +2250,7 @@ void zap_vma_ptes(struct vm_area_struct *vma, unsigned long address,
!(vma->vm_flags & VM_PFNMAP))
return;
- zap_page_range_single(vma, address, size);
+ zap_vma_range(vma, address, size);
}
EXPORT_SYMBOL_GPL(zap_vma_ptes);
@@ -3018,7 +3018,7 @@ static int remap_pfn_range_notrack(struct vm_area_struct *vma, unsigned long add
* maintain page reference counts, and callers may free
* pages due to the error. So zap it early.
*/
- zap_page_range_single(vma, addr, size);
+ zap_vma_range(vma, addr, size);
return error;
}
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index befcde27dee7..cb4477ef1529 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -2104,7 +2104,7 @@ static int tcp_zerocopy_vm_insert_batch_error(struct vm_area_struct *vma,
maybe_zap_len = total_bytes_to_map - /* All bytes to map */
*length + /* Mapped or pending */
(pages_remaining * PAGE_SIZE); /* Failed map. */
- zap_page_range_single(vma, *address, maybe_zap_len);
+ zap_vma_range(vma, *address, maybe_zap_len);
err = 0;
}
@@ -2112,7 +2112,7 @@ static int tcp_zerocopy_vm_insert_batch_error(struct vm_area_struct *vma,
unsigned long leftover_pages = pages_remaining;
int bytes_mapped;
- /* We called zap_page_range_single, try to reinsert. */
+ /* We called zap_vma_range, try to reinsert. */
err = vm_insert_pages(vma, *address,
pending_pages,
&pages_remaining);
@@ -2269,7 +2269,7 @@ static int tcp_zerocopy_receive(struct sock *sk,
total_bytes_to_map = avail_len & ~(PAGE_SIZE - 1);
if (total_bytes_to_map) {
if (!(zc->flags & TCP_RECEIVE_ZEROCOPY_FLAG_TLB_CLEAN_HINT))
- zap_page_range_single(vma, address, total_bytes_to_map);
+ zap_vma_range(vma, address, total_bytes_to_map);
zc->length = total_bytes_to_map;
zc->recv_skip_hint = 0;
} else {
diff --git a/rust/kernel/mm/virt.rs b/rust/kernel/mm/virt.rs
index b8e59e4420f3..04b3cc925d67 100644
--- a/rust/kernel/mm/virt.rs
+++ b/rust/kernel/mm/virt.rs
@@ -113,7 +113,7 @@ pub fn end(&self) -> usize {
/// kernel goes further in freeing unused page tables, but for the purposes of this operation
/// we must only assume that the leaf level is cleared.
#[inline]
- pub fn zap_page_range_single(&self, address: usize, size: usize) {
+ pub fn zap_vma_range(&self, address: usize, size: usize) {
let (end, did_overflow) = address.overflowing_add(size);
if did_overflow || address < self.start() || self.end() < end {
// TODO: call WARN_ONCE once Rust version of it is added
@@ -124,7 +124,7 @@ pub fn zap_page_range_single(&self, address: usize, size: usize) {
// sufficient for this method call. This method has no requirements on the vma flags. The
// address range is checked to be within the vma.
unsafe {
- bindings::zap_page_range_single(self.as_ptr(), address, size)
+ bindings::zap_vma_range(self.as_ptr(), address, size)
};
}
--
2.43.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v1 15/16] mm: rename zap_vma_ptes() to zap_special_vma_range()
2026-02-27 20:08 [PATCH v1 00/16] mm: cleanups around unmapping / zapping David Hildenbrand (Arm)
` (13 preceding siblings ...)
2026-02-27 20:08 ` [PATCH v1 14/16] mm: rename zap_page_range_single() to zap_vma_range() David Hildenbrand (Arm)
@ 2026-02-27 20:08 ` David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 16/16] mm/memory: support VM_MIXEDMAP in zap_special_vma_range() David Hildenbrand (Arm)
15 siblings, 0 replies; 17+ messages in thread
From: David Hildenbrand (Arm) @ 2026-02-27 20:08 UTC (permalink / raw)
To: linux-kernel
Cc: linux-mm @ kvack . org, David Hildenbrand (Arm),
Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Jann Horn,
Pedro Falcato, David Rientjes, Shakeel Butt,
Matthew Wilcox (Oracle),
Alice Ryhl, Madhavan Srinivasan, Michael Ellerman,
Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
Alexander Gordeev, Gerald Schaefer, Heiko Carstens,
Vasily Gorbik, Jarkko Sakkinen, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Greg Kroah-Hartman, Arve Hjønnevåg,
Todd Kjos, Christian Brauner, Carlos Llamas, Ian Abbott,
H Hartley Sweeten, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, David Airlie, Simona Vetter, Jason Gunthorpe,
Leon Romanovsky, Dimitri Sivanich, Arnd Bergmann,
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Peter Zijlstra, Arnaldo Carvalho de Melo, Namhyung Kim,
Andy Lutomirski, Vincenzo Frascino, Eric Dumazet, Neal Cardwell,
David S. Miller, David Ahern, Jakub Kicinski, Paolo Abeni,
Miguel Ojeda, linuxppc-dev, kvm, linux-s390, linux-sgx,
intel-gfx, dri-devel, linux-rdma, bpf, linux-perf-users,
linux-fsdevel, netdev, rust-for-linux, x86
zap_vma_ptes() is the only zapping function we export to modules.
It's essentially a wrapper around zap_vma_range(), however, with some
safety checks:
* That the passed range fits fully into the VMA
* That it's only used for VM_PFNMAP
We might want to support VM_MIXEDMAP soon as well, so use the
more-generic term "special vma", although "special" is a bit overloaded.
Maybe we'll later just support any VM_SPECIAL flag.
While at it, improve the kerneldoc.
Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
arch/x86/kernel/cpu/sgx/encl.c | 2 +-
drivers/comedi/comedi_fops.c | 2 +-
drivers/gpu/drm/i915/i915_mm.c | 4 ++--
drivers/infiniband/core/uverbs_main.c | 6 +++---
drivers/misc/sgi-gru/grumain.c | 2 +-
include/linux/mm.h | 2 +-
mm/memory.c | 16 +++++++---------
7 files changed, 16 insertions(+), 18 deletions(-)
diff --git a/arch/x86/kernel/cpu/sgx/encl.c b/arch/x86/kernel/cpu/sgx/encl.c
index ac60ebde5d9b..3f0222d10f6e 100644
--- a/arch/x86/kernel/cpu/sgx/encl.c
+++ b/arch/x86/kernel/cpu/sgx/encl.c
@@ -1220,7 +1220,7 @@ void sgx_zap_enclave_ptes(struct sgx_encl *encl, unsigned long addr)
ret = sgx_encl_find(encl_mm->mm, addr, &vma);
if (!ret && encl == vma->vm_private_data)
- zap_vma_ptes(vma, addr, PAGE_SIZE);
+ zap_special_vma_range(vma, addr, PAGE_SIZE);
mmap_read_unlock(encl_mm->mm);
diff --git a/drivers/comedi/comedi_fops.c b/drivers/comedi/comedi_fops.c
index 48a8a607a84c..b91e0b5ac394 100644
--- a/drivers/comedi/comedi_fops.c
+++ b/drivers/comedi/comedi_fops.c
@@ -2588,7 +2588,7 @@ static int comedi_mmap(struct file *file, struct vm_area_struct *vma)
* remap_pfn_range() because we call remap_pfn_range() in a loop.
*/
if (retval)
- zap_vma_ptes(vma, vma->vm_start, size);
+ zap_special_vma_range(vma, vma->vm_start, size);
#endif
if (retval == 0) {
diff --git a/drivers/gpu/drm/i915/i915_mm.c b/drivers/gpu/drm/i915/i915_mm.c
index c33bd3d83069..fd89e7c7d8d6 100644
--- a/drivers/gpu/drm/i915/i915_mm.c
+++ b/drivers/gpu/drm/i915/i915_mm.c
@@ -108,7 +108,7 @@ int remap_io_mapping(struct vm_area_struct *vma,
err = apply_to_page_range(r.mm, addr, size, remap_pfn, &r);
if (unlikely(err)) {
- zap_vma_ptes(vma, addr, (r.pfn - pfn) << PAGE_SHIFT);
+ zap_special_vma_range(vma, addr, (r.pfn - pfn) << PAGE_SHIFT);
return err;
}
@@ -156,7 +156,7 @@ int remap_io_sg(struct vm_area_struct *vma,
err = apply_to_page_range(r.mm, addr, size, remap_sg, &r);
if (unlikely(err)) {
- zap_vma_ptes(vma, addr, r.pfn << PAGE_SHIFT);
+ zap_special_vma_range(vma, addr, r.pfn << PAGE_SHIFT);
return err;
}
diff --git a/drivers/infiniband/core/uverbs_main.c b/drivers/infiniband/core/uverbs_main.c
index 7b68967a6301..f5837da47299 100644
--- a/drivers/infiniband/core/uverbs_main.c
+++ b/drivers/infiniband/core/uverbs_main.c
@@ -756,7 +756,7 @@ static void rdma_umap_open(struct vm_area_struct *vma)
* point, so zap it.
*/
vma->vm_private_data = NULL;
- zap_vma_ptes(vma, vma->vm_start, vma->vm_end - vma->vm_start);
+ zap_special_vma_range(vma, vma->vm_start, vma->vm_end - vma->vm_start);
}
static void rdma_umap_close(struct vm_area_struct *vma)
@@ -782,7 +782,7 @@ static void rdma_umap_close(struct vm_area_struct *vma)
}
/*
- * Once the zap_vma_ptes has been called touches to the VMA will come here and
+ * Once the zap_special_vma_range has been called touches to the VMA will come here and
* we return a dummy writable zero page for all the pfns.
*/
static vm_fault_t rdma_umap_fault(struct vm_fault *vmf)
@@ -878,7 +878,7 @@ void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile)
continue;
list_del_init(&priv->list);
- zap_vma_ptes(vma, vma->vm_start,
+ zap_special_vma_range(vma, vma->vm_start,
vma->vm_end - vma->vm_start);
if (priv->entry) {
diff --git a/drivers/misc/sgi-gru/grumain.c b/drivers/misc/sgi-gru/grumain.c
index 8d749f345246..278b76cbd281 100644
--- a/drivers/misc/sgi-gru/grumain.c
+++ b/drivers/misc/sgi-gru/grumain.c
@@ -542,7 +542,7 @@ void gru_unload_context(struct gru_thread_state *gts, int savestate)
int ctxnum = gts->ts_ctxnum;
if (!is_kernel_context(gts))
- zap_vma_ptes(gts->ts_vma, UGRUADDR(gts), GRU_GSEG_PAGESIZE);
+ zap_special_vma_range(gts->ts_vma, UGRUADDR(gts), GRU_GSEG_PAGESIZE);
cch = get_cch(gru->gs_gru_base_vaddr, ctxnum);
gru_dbg(grudev, "gts %p, cbrmap 0x%lx, dsrmap 0x%lx\n",
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 833bedd3f739..07f6819db02d 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -2833,7 +2833,7 @@ struct page *vm_normal_page_pmd(struct vm_area_struct *vma, unsigned long addr,
struct page *vm_normal_page_pud(struct vm_area_struct *vma, unsigned long addr,
pud_t pud);
-void zap_vma_ptes(struct vm_area_struct *vma, unsigned long address,
+void zap_special_vma_range(struct vm_area_struct *vma, unsigned long address,
unsigned long size);
void zap_vma_range(struct vm_area_struct *vma, unsigned long address,
unsigned long size);
diff --git a/mm/memory.c b/mm/memory.c
index dd737b6d28c0..f3b7b7e16138 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2233,17 +2233,15 @@ void zap_vma_range(struct vm_area_struct *vma, unsigned long address,
}
/**
- * zap_vma_ptes - remove ptes mapping the vma
- * @vma: vm_area_struct holding ptes to be zapped
- * @address: starting address of pages to zap
+ * zap_special_vma_range - zap all page table entries in a special vma range
+ * @vma: the vma covering the range to zap
+ * @address: starting address of the range to zap
* @size: number of bytes to zap
*
- * This function only unmaps ptes assigned to VM_PFNMAP vmas.
- *
- * The entire address range must be fully contained within the vma.
- *
+ * This function does nothing when the provided address range is not fully
+ * contained in @vma, or when the @vma is not VM_PFNMAP.
*/
-void zap_vma_ptes(struct vm_area_struct *vma, unsigned long address,
+void zap_special_vma_range(struct vm_area_struct *vma, unsigned long address,
unsigned long size)
{
if (!range_in_vma(vma, address, address + size) ||
@@ -2252,7 +2250,7 @@ void zap_vma_ptes(struct vm_area_struct *vma, unsigned long address,
zap_vma_range(vma, address, size);
}
-EXPORT_SYMBOL_GPL(zap_vma_ptes);
+EXPORT_SYMBOL_GPL(zap_special_vma_range);
static pmd_t *walk_to_pmd(struct mm_struct *mm, unsigned long addr)
{
--
2.43.0
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH v1 16/16] mm/memory: support VM_MIXEDMAP in zap_special_vma_range()
2026-02-27 20:08 [PATCH v1 00/16] mm: cleanups around unmapping / zapping David Hildenbrand (Arm)
` (14 preceding siblings ...)
2026-02-27 20:08 ` [PATCH v1 15/16] mm: rename zap_vma_ptes() to zap_special_vma_range() David Hildenbrand (Arm)
@ 2026-02-27 20:08 ` David Hildenbrand (Arm)
15 siblings, 0 replies; 17+ messages in thread
From: David Hildenbrand (Arm) @ 2026-02-27 20:08 UTC (permalink / raw)
To: linux-kernel
Cc: linux-mm @ kvack . org, David Hildenbrand (Arm),
Andrew Morton, Lorenzo Stoakes, Liam R. Howlett, Vlastimil Babka,
Mike Rapoport, Suren Baghdasaryan, Michal Hocko, Jann Horn,
Pedro Falcato, David Rientjes, Shakeel Butt,
Matthew Wilcox (Oracle),
Alice Ryhl, Madhavan Srinivasan, Michael Ellerman,
Christian Borntraeger, Janosch Frank, Claudio Imbrenda,
Alexander Gordeev, Gerald Schaefer, Heiko Carstens,
Vasily Gorbik, Jarkko Sakkinen, Thomas Gleixner, Ingo Molnar,
Borislav Petkov, Greg Kroah-Hartman, Arve Hjønnevåg,
Todd Kjos, Christian Brauner, Carlos Llamas, Ian Abbott,
H Hartley Sweeten, Jani Nikula, Joonas Lahtinen, Rodrigo Vivi,
Tvrtko Ursulin, David Airlie, Simona Vetter, Jason Gunthorpe,
Leon Romanovsky, Dimitri Sivanich, Arnd Bergmann,
Alexei Starovoitov, Daniel Borkmann, Andrii Nakryiko,
Peter Zijlstra, Arnaldo Carvalho de Melo, Namhyung Kim,
Andy Lutomirski, Vincenzo Frascino, Eric Dumazet, Neal Cardwell,
David S. Miller, David Ahern, Jakub Kicinski, Paolo Abeni,
Miguel Ojeda, linuxppc-dev, kvm, linux-s390, linux-sgx,
intel-gfx, dri-devel, linux-rdma, bpf, linux-perf-users,
linux-fsdevel, netdev, rust-for-linux, x86
There is demand for also zapping page table entries by drivers in
VM_MIXEDMAP VMAs[1].
Nothing really speaks against supporting VM_MIXEDMAP for driver use. We
just don't want arbitrary drivers to zap in ordinary (non-special) VMAs.
[1] https://lore.kernel.org/r/aYSKyr7StGpGKNqW@google.com
Signed-off-by: David Hildenbrand (Arm) <david@kernel.org>
---
mm/memory.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/mm/memory.c b/mm/memory.c
index f3b7b7e16138..3fe30dc2f179 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -2239,13 +2239,13 @@ void zap_vma_range(struct vm_area_struct *vma, unsigned long address,
* @size: number of bytes to zap
*
* This function does nothing when the provided address range is not fully
- * contained in @vma, or when the @vma is not VM_PFNMAP.
+ * contained in @vma, or when the @vma is not VM_PFNMAP or VM_MIXEDMAP.
*/
void zap_special_vma_range(struct vm_area_struct *vma, unsigned long address,
unsigned long size)
{
if (!range_in_vma(vma, address, address + size) ||
- !(vma->vm_flags & VM_PFNMAP))
+ !(vma->vm_flags & (VM_PFNMAP | VM_MIXEDMAP)))
return;
zap_vma_range(vma, address, size);
--
2.43.0
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2026-02-27 20:13 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-02-27 20:08 [PATCH v1 00/16] mm: cleanups around unmapping / zapping David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 01/16] mm/madvise: drop range checks in madvise_free_single_vma() David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 02/16] mm/memory: remove "zap_details" parameter from zap_page_range_single() David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 03/16] mm/memory: inline unmap_mapping_range_vma() into unmap_mapping_range_tree() David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 04/16] mm/memory: simplify calculation in unmap_mapping_range_tree() David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 05/16] mm/oom_kill: use MMU_NOTIFY_CLEAR in __oom_reap_task_mm() David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 06/16] mm/oom_kill: factor out zapping of VMA into zap_vma_for_reaping() David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 07/16] mm/memory: rename unmap_single_vma() to __zap_vma_range() David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 08/16] mm/memory: move adjusting of address range to unmap_vmas() David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 09/16] mm/memory: convert details->even_cows into details->skip_cows David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 10/16] mm/memory: use __zap_vma_range() in zap_vma_for_reaping() David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 11/16] mm/memory: inline unmap_page_range() into __zap_vma_range() David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 12/16] mm: rename zap_vma_pages() to zap_vma() David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 13/16] mm: rename zap_page_range_single_batched() to zap_vma_range_batched() David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 14/16] mm: rename zap_page_range_single() to zap_vma_range() David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 15/16] mm: rename zap_vma_ptes() to zap_special_vma_range() David Hildenbrand (Arm)
2026-02-27 20:08 ` [PATCH v1 16/16] mm/memory: support VM_MIXEDMAP in zap_special_vma_range() David Hildenbrand (Arm)
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox