[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20250820010415.699353-12-anthony.yznaga@oracle.com>
Date: Tue, 19 Aug 2025 18:04:04 -0700
From: Anthony Yznaga <anthony.yznaga@...cle.com>
To: linux-mm@...ck.org
Cc: akpm@...ux-foundation.org, andreyknvl@...il.com, arnd@...db.de,
bp@...en8.de, brauner@...nel.org, bsegall@...gle.com, corbet@....net,
dave.hansen@...ux.intel.com, david@...hat.com,
dietmar.eggemann@....com, ebiederm@...ssion.com, hpa@...or.com,
jakub.wartak@...lbox.org, jannh@...gle.com, juri.lelli@...hat.com,
khalid@...nel.org, liam.howlett@...cle.com, linyongting@...edance.com,
lorenzo.stoakes@...cle.com, luto@...nel.org, markhemm@...glemail.com,
maz@...nel.org, mhiramat@...nel.org, mgorman@...e.de, mhocko@...e.com,
mingo@...hat.com, muchun.song@...ux.dev, neilb@...e.de,
osalvador@...e.de, pcc@...gle.com, peterz@...radead.org,
pfalcato@...e.de, rostedt@...dmis.org, rppt@...nel.org,
shakeel.butt@...ux.dev, surenb@...gle.com, tglx@...utronix.de,
vasily.averin@...ux.dev, vbabka@...e.cz, vincent.guittot@...aro.org,
viro@...iv.linux.org.uk, vschneid@...hat.com, willy@...radead.org,
x86@...nel.org, xhao@...ux.alibaba.com, linux-doc@...r.kernel.org,
linux-kernel@...r.kernel.org, linux-arch@...r.kernel.org
Subject: [PATCH v3 11/22] mm: add and use unmap_page_range vm_ops hook
Special handling is needed when unmapping a hugetlb vma and will
be needed when unmapping an msharefs vma once support is added for
handling faults in an mshare region.
Signed-off-by: Anthony Yznaga <anthony.yznaga@...cle.com>
---
include/linux/mm.h | 10 ++++++++++
ipc/shm.c | 17 +++++++++++++++++
mm/hugetlb.c | 25 +++++++++++++++++++++++++
mm/memory.c | 36 +++++++++++++-----------------------
4 files changed, 65 insertions(+), 23 deletions(-)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index aca853b4c5dc..96440082a633 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -43,6 +43,7 @@ struct anon_vma_chain;
struct user_struct;
struct pt_regs;
struct folio_batch;
+struct zap_details;
void arch_mm_preinit(void);
void mm_core_init(void);
@@ -681,8 +682,17 @@ struct vm_operations_struct {
struct page *(*find_normal_page)(struct vm_area_struct *vma,
unsigned long addr);
#endif /* CONFIG_FIND_NORMAL_PAGE */
+ void (*unmap_page_range)(struct mmu_gather *tlb,
+ struct vm_area_struct *vma,
+ unsigned long addr, unsigned long end,
+ struct zap_details *details);
};
+void __unmap_page_range(struct mmu_gather *tlb,
+ struct vm_area_struct *vma,
+ unsigned long addr, unsigned long end,
+ struct zap_details *details);
+
#ifdef CONFIG_NUMA_BALANCING
static inline void vma_numab_state_init(struct vm_area_struct *vma)
{
diff --git a/ipc/shm.c b/ipc/shm.c
index a9310b6dbbc3..14376b63d46a 100644
--- a/ipc/shm.c
+++ b/ipc/shm.c
@@ -588,6 +588,22 @@ static struct mempolicy *shm_get_policy(struct vm_area_struct *vma,
}
#endif
+static void shm_unmap_page_range(struct mmu_gather *tlb,
+ struct vm_area_struct *vma,
+ unsigned long addr, unsigned long end,
+ struct zap_details *details)
+{
+ struct file *file = vma->vm_file;
+ struct shm_file_data *sfd = shm_file_data(file);
+
+ if (sfd->vm_ops->unmap_page_range) {
+ sfd->vm_ops->unmap_page_range(tlb, vma, addr, end, details);
+ return;
+ }
+
+ __unmap_page_range(tlb, vma, addr, end, details);
+}
+
static int shm_mmap(struct file *file, struct vm_area_struct *vma)
{
struct shm_file_data *sfd = shm_file_data(file);
@@ -688,6 +704,7 @@ static const struct vm_operations_struct shm_vm_ops = {
.set_policy = shm_set_policy,
.get_policy = shm_get_policy,
#endif
+ .unmap_page_range = shm_unmap_page_range,
};
/**
diff --git a/mm/hugetlb.c b/mm/hugetlb.c
index 514fab5a20ef..3fc6eb8a5858 100644
--- a/mm/hugetlb.c
+++ b/mm/hugetlb.c
@@ -5461,6 +5461,30 @@ static vm_fault_t hugetlb_vm_op_fault(struct vm_fault *vmf)
return 0;
}
+static void hugetlb_vm_op_unmap_page_range(struct mmu_gather *tlb,
+ struct vm_area_struct *vma,
+ unsigned long addr, unsigned long end,
+ struct zap_details *details)
+{
+ zap_flags_t zap_flags = details ? details->zap_flags : 0;
+
+ /*
+ * 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)
+ return;
+
+ __unmap_hugepage_range(tlb, vma, addr, end, NULL, zap_flags);
+}
+
/*
* When a new function is introduced to vm_operations_struct and added
* to hugetlb_vm_ops, please consider adding the function to shm_vm_ops.
@@ -5474,6 +5498,7 @@ const struct vm_operations_struct hugetlb_vm_ops = {
.close = hugetlb_vm_op_close,
.may_split = hugetlb_vm_op_split,
.pagesize = hugetlb_vm_op_pagesize,
+ .unmap_page_range = hugetlb_vm_op_unmap_page_range,
};
static pte_t make_huge_pte(struct vm_area_struct *vma, struct folio *folio,
diff --git a/mm/memory.c b/mm/memory.c
index 002c28795d8b..dbc299aa82c2 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -1999,7 +1999,7 @@ static inline unsigned long zap_p4d_range(struct mmu_gather *tlb,
return addr;
}
-void unmap_page_range(struct mmu_gather *tlb,
+void __unmap_page_range(struct mmu_gather *tlb,
struct vm_area_struct *vma,
unsigned long addr, unsigned long end,
struct zap_details *details)
@@ -2019,6 +2019,16 @@ void unmap_page_range(struct mmu_gather *tlb,
tlb_end_vma(tlb, vma);
}
+void unmap_page_range(struct mmu_gather *tlb,
+ struct vm_area_struct *vma,
+ unsigned long addr, unsigned long end,
+ struct zap_details *details)
+{
+ if (vma->vm_ops && vma->vm_ops->unmap_page_range)
+ vma->vm_ops->unmap_page_range(tlb, vma, addr, end, details);
+ else
+ __unmap_page_range(tlb, vma, addr, end, details);
+}
static void unmap_single_vma(struct mmu_gather *tlb,
struct vm_area_struct *vma, unsigned long start_addr,
@@ -2037,28 +2047,8 @@ static void unmap_single_vma(struct mmu_gather *tlb,
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 (start != end)
+ unmap_page_range(tlb, vma, start, end, details);
}
/**
--
2.47.1
Powered by blists - more mailing lists