Address-space teardown on process exit runs synchronously in the dying
task's context: exit_mm() -> mmput() -> __mmput() -> exit_mmap() walks
page tables, updates rmap, frees the RSS and drops file refs, all on the
exiting CPU.

Add the scaffolding to later move __mmput() off-CPU for large exiting
address spaces, with no functional change in this patch:
  - new config ASYNC_MM_TEARDOWN (bool, depends on MMU, default n)
  - struct mm_struct::async_reap_node (llist_node), CONFIG-gated, with
    an explicit <linux/llist.h> include (it was only ever available
    transitively via spinlock.h)
  - mmput_exit() declaration, with a static inline fallback that is a
    plain mmput

When the config is disabled mmput_exit() compiles to mmput() with zero
delta, so nothing changes until the kthread and dispatch land.

Signed-off-by: Aditya Sharma <[email protected]>
---
 include/linux/mm_types.h |  4 ++++
 include/linux/sched/mm.h |  6 ++++++
 mm/Kconfig               | 11 +++++++++++
 3 files changed, 21 insertions(+)

diff --git a/include/linux/mm_types.h b/include/linux/mm_types.h
index 939b5ea8c..fffa285ef 100644
--- a/include/linux/mm_types.h
+++ b/include/linux/mm_types.h
@@ -7,6 +7,7 @@
 #include <linux/auxvec.h>
 #include <linux/kref.h>
 #include <linux/list.h>
+#include <linux/llist.h>
 #include <linux/spinlock.h>
 #include <linux/rbtree.h>
 #include <linux/maple_tree.h>
@@ -1367,6 +1368,9 @@ struct mm_struct {
                atomic_long_t hugetlb_usage;
 #endif
                struct work_struct async_put_work;
+#ifdef CONFIG_ASYNC_MM_TEARDOWN
+               struct llist_node async_reap_node;
+#endif /* CONFIG_ASYNC_MM_TEARDOWN */
 
 #ifdef CONFIG_IOMMU_MM_DATA
                struct iommu_mm_data *iommu_mm;
diff --git a/include/linux/sched/mm.h b/include/linux/sched/mm.h
index 10be8a54b..20aeb1d7e 100644
--- a/include/linux/sched/mm.h
+++ b/include/linux/sched/mm.h
@@ -147,6 +147,12 @@ extern void mmput(struct mm_struct *);
 void mmput_async(struct mm_struct *);
 #endif
 
+#ifdef CONFIG_ASYNC_MM_TEARDOWN
+void mmput_exit(struct mm_struct *);
+#else
+static inline void mmput_exit(struct mm_struct *mm) { mmput(mm); }
+#endif
+
 /* Grab a reference to a task's mm, if it is not already going away */
 extern struct mm_struct *get_task_mm(struct task_struct *task);
 /*
diff --git a/mm/Kconfig b/mm/Kconfig
index c52ab6afc..296b16ad4 100644
--- a/mm/Kconfig
+++ b/mm/Kconfig
@@ -1500,6 +1500,17 @@ config LAZY_MMU_MODE_KUNIT_TEST
 
          If unsure, say N.
 
+config ASYNC_MM_TEARDOWN
+       bool "Async off-CPU address space teardown on exit"
+       depends on MMU
+       default n
+       help
+         Defer the address space teardown (exit_mmap()) of large exiting 
processes
+         to a kernel thread instead of running it on the exiting CPU. The 
feature
+         is off by default.
+
+         If unsure, say N.
+
 source "mm/damon/Kconfig"
 
 endmenu
-- 
2.34.1


Reply via email to