ascend inclusion category: Feature bugzilla: https://gitee.com/openeuler/kernel/issues/I7YF5R
---------------------------------------------
The fork() will create the new mm for new process, the mm should not take any information from the parent process, so need to clean it.
The exit() will mmput the mm and free the memory, if the mm is alrready be used for sp_group, need to clean the group first.
Signed-off-by: Wang Wensheng wangwensheng4@huawei.com --- include/linux/share_pool.h | 49 +++++++++++------------------- kernel/fork.c | 3 ++ mm/share_pool.c | 61 +++++++++++++++++++++++++++++++++++++- 3 files changed, 81 insertions(+), 32 deletions(-)
diff --git a/include/linux/share_pool.h b/include/linux/share_pool.h index 816230ef43c2..b0711eea4b73 100644 --- a/include/linux/share_pool.h +++ b/include/linux/share_pool.h @@ -124,21 +124,26 @@ extern bool mg_is_sharepool_addr(unsigned long addr);
extern int mg_sp_id_of_current(void);
-extern void sp_area_drop(struct vm_area_struct *vma); -extern void sp_mm_clean(struct mm_struct *mm); -vm_fault_t sharepool_no_page(struct mm_struct *mm, - struct vm_area_struct *vma, - struct address_space *mapping, pgoff_t idx, - unsigned long address, pte_t *ptep, unsigned int flags); -extern bool sp_check_addr(unsigned long addr); -extern bool sp_check_mmap_addr(unsigned long addr, unsigned long flags); -extern int sp_node_id(struct vm_area_struct *vma); +extern void __sp_area_drop(struct vm_area_struct *vma); +extern void __sp_mm_clean(struct mm_struct *mm);
static inline bool sp_is_enabled(void) { return static_branch_likely(&share_pool_enabled_key); }
+static inline void sp_mm_clean(struct mm_struct *mm) +{ + if (sp_is_enabled()) + __sp_mm_clean(mm); +} + +static inline void sp_area_drop(struct vm_area_struct *vma) +{ + if (sp_is_enabled()) + __sp_area_drop(vma); +} + static inline void sp_area_work_around(struct vm_unmapped_area_info *info) { if (sp_is_enabled()) @@ -160,10 +165,6 @@ static inline int mg_sp_group_add_task(int tgid, unsigned long prot, int spg_id) return -EPERM; }
-static inline void sp_mm_clean(struct mm_struct *mm) -{ -} - static inline int mg_sp_group_id_by_pid(int tgid, int *spg_ids, int *num) { return -EPERM; @@ -200,6 +201,10 @@ static inline int mg_sp_id_of_current(void) return -EPERM; }
+static inline void sp_mm_clean(struct mm_struct *mm) +{ +} + static inline void sp_init_mm(struct mm_struct *mm) { } @@ -255,24 +260,6 @@ static inline bool is_vm_huge_special(struct vm_area_struct *vma) return false; }
-static inline bool sp_check_addr(unsigned long addr) -{ - return false; -} - -static inline bool sp_check_mmap_addr(unsigned long addr, unsigned long flags) -{ - return false; -} - -static inline vm_fault_t sharepool_no_page(struct mm_struct *mm, - struct vm_area_struct *vma, - struct address_space *mapping, pgoff_t idx, - unsigned long address, pte_t *ptep, unsigned int flags) -{ - return VM_FAULT_SIGBUS; -} - static inline int sp_node_id(struct vm_area_struct *vma) { return numa_node_id(); diff --git a/kernel/fork.c b/kernel/fork.c index 7e11bdaef257..75acc20ca585 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -99,6 +99,7 @@ #include <linux/stackprotector.h> #include <linux/user_events.h> #include <linux/iommu.h> +#include <linux/share_pool.h>
#ifdef CONFIG_GMEM #include <linux/vm_object.h> @@ -1327,6 +1328,7 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p, if (percpu_counter_init(&mm->rss_stat[i], 0, GFP_KERNEL_ACCOUNT)) goto fail_pcpu;
+ sp_init_mm(mm); mm->user_ns = get_user_ns(user_ns); lru_gen_init_mm(mm); return mm; @@ -1368,6 +1370,7 @@ static inline void __mmput(struct mm_struct *mm) ksm_exit(mm); khugepaged_exit(mm); /* must run before exit_mmap */ exit_mmap(mm); + sp_mm_clean(mm); mm_put_huge_zero_page(mm); set_mm_exe_file(mm, NULL); if (!list_empty(&mm->mmlist)) { diff --git a/mm/share_pool.c b/mm/share_pool.c index 05e514118786..1ca5b867147d 100644 --- a/mm/share_pool.c +++ b/mm/share_pool.c @@ -1744,7 +1744,7 @@ static void sp_area_drop_func(struct work_struct *work) sp_group_put(spg); }
-void sp_area_drop(struct vm_area_struct *vma) +void __sp_area_drop(struct vm_area_struct *vma) { struct sp_area *spa = vma->spa;
@@ -3335,6 +3335,65 @@ static void __init proc_sharepool_init(void)
/*** End of tatistical and maintenance functions ***/
+void __sp_mm_clean(struct mm_struct *mm) +{ + struct sp_meminfo *meminfo; + long alloc_size, k2u_size; + /* lockless visit */ + struct sp_group_master *master = mm->sp_group_master; + struct sp_group_node *spg_node, *tmp; + struct sp_group *spg; + + if (!master) + return; + + /* + * There are two basic scenarios when a process in the share pool is + * exiting but its share pool memory usage is not 0. + * 1. Process A called sp_alloc(), but it terminates without calling + * sp_free(). Then its share pool memory usage is a positive number. + * 2. Process A never called sp_alloc(), and process B in the same spg + * called sp_alloc() to get an addr u. Then A gets u somehow and + * called sp_free(u). Now A's share pool memory usage is a negative + * number. Notice B's memory usage will be a positive number. + * + * We decide to print an info when seeing both of the scenarios. + * + * A process not in an sp group doesn't need to print because there + * wont't be any memory which is not freed. + */ + meminfo = &master->meminfo; + alloc_size = meminfo_alloc_sum(meminfo); + k2u_size = atomic64_read(&meminfo->k2u_size); + if (alloc_size != 0 || k2u_size != 0) + pr_info("process %s(%d) exits. It applied %ld aligned KB, k2u shared %ld aligned KB\n", + master->comm, master->tgid, + byte2kb(alloc_size), byte2kb(k2u_size)); + + down_write(&sp_global_sem); + list_for_each_entry_safe(spg_node, tmp, &master->group_head, group_node) { + spg = spg_node->spg; + + down_write(&spg->rw_lock); + + list_del(&spg_node->proc_node); + spg->proc_num--; + list_del(&spg_node->group_node); + master->group_num--; + + up_write(&spg->rw_lock); + + mmdrop(mm); + sp_group_put_locked(spg); + kfree(spg_node); + } + up_write(&sp_global_sem); + + sp_del_group_master(master); + + kfree(master); +} + DEFINE_STATIC_KEY_FALSE(share_pool_enabled_key);
static int __init enable_share_pool(char *s)