From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-wr0-x241.google.com (mail-wr0-x241.google.com [IPv6:2a00:1450:400c:c0c::241]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by lists.ozlabs.org (Postfix) with ESMTPS id 3vhscB1MlMzDqXy for ; Tue, 14 Mar 2017 09:14:50 +1100 (AEDT) Received: by mail-wr0-x241.google.com with SMTP id l37so21726068wrc.3 for ; Mon, 13 Mar 2017 15:14:50 -0700 (PDT) From: Till Smejkal To: Richard Henderson , Ivan Kokshaysky , Matt Turner , Vineet Gupta , Russell King , Catalin Marinas , Will Deacon , Steven Miao , Richard Kuo , Tony Luck , Fenghua Yu , James Hogan , Ralf Baechle , "James E.J. Bottomley" , Helge Deller , Benjamin Herrenschmidt , Paul Mackerras , Michael Ellerman , Martin Schwidefsky , Heiko Carstens , Yoshinori Sato , Rich Felker , "David S. Miller" , Chris Metcalf , Thomas Gleixner , Ingo Molnar , "H. Peter Anvin" , x86@kernel.org, Andy Lutomirski , Chris Zankel , Max Filippov , Arnd Bergmann , Greg Kroah-Hartman , Laurent Pinchart , Mauro Carvalho Chehab , Pawel Osciak , Marek Szyprowski , Kyungmin Park , David Woodhouse , Brian Norris , Boris Brezillon , Marek Vasut , Richard Weinberger , Cyrille Pitchen , Felipe Balbi , Alexander Viro , Benjamin LaHaise , Nadia Yvette Chambers , Jeff Layton , "J. Bruce Fields" , Peter Zijlstra , Hugh Dickins , Arnaldo Carvalho de Melo , Alexander Shishkin , Jaroslav Kysela , Takashi Iwai Cc: linux-kernel@vger.kernel.org, linux-alpha@vger.kernel.org, linux-snps-arc@lists.infradead.org, linux-arm-kernel@lists.infradead.org, adi-buildroot-devel@lists.sourceforge.net, linux-hexagon@vger.kernel.org, linux-ia64@vger.kernel.org, linux-metag@vger.kernel.org, linux-mips@linux-mips.org, linux-parisc@vger.kernel.org, linuxppc-dev@lists.ozlabs.org, linux-s390@vger.kernel.org, linux-sh@vger.kernel.org, sparclinux@vger.kernel.org, linux-xtensa@linux-xtensa.org, linux-media@vger.kernel.org, linux-mtd@lists.infradead.org, linux-usb@vger.kernel.org, linux-fsdevel@vger.kernel.org, linux-aio@kvack.org, linux-mm@kvack.org, linux-api@vger.kernel.org, linux-arch@vger.kernel.org, alsa-devel@alsa-project.org Subject: [RFC PATCH 07/13] kernel/fork: Split and export 'mm_alloc' and 'mm_init' Date: Mon, 13 Mar 2017 15:14:09 -0700 Message-Id: <20170313221415.9375-8-till.smejkal@gmail.com> In-Reply-To: <20170313221415.9375-1-till.smejkal@gmail.com> References: <20170313221415.9375-1-till.smejkal@gmail.com> List-Id: Linux on PowerPC Developers Mail List List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , The only way until now to create a new memory map was via the exported function 'mm_alloc'. Unfortunately, this function not only allocates a new memory map, but also completely initializes it. However, with the introduction of first class virtual address spaces, some initialization steps done in 'mm_alloc' are not applicable to the memory maps needed for this feature and hence would lead to errors in the kernel code. Instead of introducing a new function that can allocate and initialize memory maps for first class virtual address spaces and potentially duplicate some code, I decided to split the mm_alloc function as well as the 'mm_init' function that it uses. Now there are four functions exported instead of only one. The new 'mm_alloc' function only allocates a new mm_struct and zeros it out. If one want to have the old behavior of mm_alloc one can use the newly introduced function 'mm_alloc_and_setup' which not only allocates a new mm_struct but also fully initializes it. The old 'mm_init' function which fully initialized a mm_struct was split up into two separate functions. The first one - 'mm_setup' - does all the initialization of the mm_struct that is not related to the mm_struct belonging to a particular task. This part of the initialization is done in the 'mm_set_task' function. This way it is possible to create memory maps that don't have any task-specific information as needed by the first class virtual address space feature. Both functions, 'mm_setup' and 'mm_set_task' are also exported, so that they can be used in all files in the source tree. Signed-off-by: Till Smejkal --- arch/arm/mach-rpc/ecard.c | 2 +- fs/exec.c | 2 +- include/linux/sched.h | 7 +++++- kernel/fork.c | 64 +++++++++++++++++++++++++++++++++++++---------- 4 files changed, 59 insertions(+), 16 deletions(-) diff --git a/arch/arm/mach-rpc/ecard.c b/arch/arm/mach-rpc/ecard.c index dc67a7fb3831..15845e8abd7e 100644 --- a/arch/arm/mach-rpc/ecard.c +++ b/arch/arm/mach-rpc/ecard.c @@ -245,7 +245,7 @@ static void ecard_init_pgtables(struct mm_struct *mm) static int ecard_init_mm(void) { - struct mm_struct * mm = mm_alloc(); + struct mm_struct *mm = mm_alloc_and_setup(); struct mm_struct *active_mm = current->active_mm; if (!mm) diff --git a/fs/exec.c b/fs/exec.c index e57946610733..68d7908a1e5a 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -380,7 +380,7 @@ static int bprm_mm_init(struct linux_binprm *bprm) int err; struct mm_struct *mm = NULL; - bprm->mm = mm = mm_alloc(); + bprm->mm = mm = mm_alloc_and_setup(); err = -ENOMEM; if (!mm) goto err; diff --git a/include/linux/sched.h b/include/linux/sched.h index 42b9b93a50ac..7955adc00397 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -2922,7 +2922,12 @@ static inline unsigned long sigsp(unsigned long sp, struct ksignal *ksig) /* * Routines for handling mm_structs */ -extern struct mm_struct * mm_alloc(void); +extern struct mm_struct *mm_setup(struct mm_struct *mm); +extern struct mm_struct *mm_set_task(struct mm_struct *mm, + struct task_struct *p, + struct user_namespace *user_ns); +extern struct mm_struct *mm_alloc(void); +extern struct mm_struct *mm_alloc_and_setup(void); /* mmdrop drops the mm and the page tables */ extern void __mmdrop(struct mm_struct *); diff --git a/kernel/fork.c b/kernel/fork.c index 11c5c8ab827c..9209f6d5d7c0 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -747,8 +747,10 @@ static void mm_init_owner(struct mm_struct *mm, struct task_struct *p) #endif } -static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p, - struct user_namespace *user_ns) +/** + * Initialize all the task-unrelated fields of a mm_struct. + **/ +struct mm_struct *mm_setup(struct mm_struct *mm) { mm->mmap = NULL; mm->mm_rb = RB_ROOT; @@ -767,24 +769,37 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p, spin_lock_init(&mm->page_table_lock); mm_init_cpumask(mm); mm_init_aio(mm); - mm_init_owner(mm, p); mmu_notifier_mm_init(mm); clear_tlb_flush_pending(mm); #if defined(CONFIG_TRANSPARENT_HUGEPAGE) && !USE_SPLIT_PMD_PTLOCKS mm->pmd_huge_pte = NULL; #endif + mm->flags = default_dump_filter; + mm->def_flags = 0; + + if (mm_alloc_pgd(mm)) + goto fail_nopgd; + + return mm; + +fail_nopgd: + free_mm(mm); + return NULL; +} + +/** + * Initialize all the task-related fields of a mm_struct. + **/ +struct mm_struct *mm_set_task(struct mm_struct *mm, struct task_struct *p, + struct user_namespace *user_ns) +{ if (current->mm) { mm->flags = current->mm->flags & MMF_INIT_MASK; mm->def_flags = current->mm->def_flags & VM_INIT_DEF_MASK; - } else { - mm->flags = default_dump_filter; - mm->def_flags = 0; } - if (mm_alloc_pgd(mm)) - goto fail_nopgd; - + mm_init_owner(mm, p); if (init_new_context(p, mm)) goto fail_nocontext; @@ -793,11 +808,21 @@ static struct mm_struct *mm_init(struct mm_struct *mm, struct task_struct *p, fail_nocontext: mm_free_pgd(mm); -fail_nopgd: free_mm(mm); return NULL; } +static struct mm_struct *mm_setup_all(struct mm_struct *mm, + struct task_struct *p, + struct user_namespace *user_ns) +{ + mm = mm_setup(mm); + if (!mm) + return NULL; + + return mm_set_task(mm, p, user_ns); +} + static void check_mm(struct mm_struct *mm) { int i; @@ -822,10 +847,22 @@ static void check_mm(struct mm_struct *mm) #endif } +struct mm_struct *mm_alloc(void) +{ + struct mm_struct *mm; + + mm = allocate_mm(); + if (!mm) + return NULL; + + memset(mm, 0, sizeof(*mm)); + return mm; +} + /* * Allocate and initialize an mm_struct. */ -struct mm_struct *mm_alloc(void) +struct mm_struct *mm_alloc_and_setup(void) { struct mm_struct *mm; @@ -834,9 +871,10 @@ struct mm_struct *mm_alloc(void) return NULL; memset(mm, 0, sizeof(*mm)); - return mm_init(mm, current, current_user_ns()); + return mm_setup_all(mm, current, current_user_ns()); } + /* * Called when the last reference to the mm * is dropped: either by a lazy thread or by @@ -1131,7 +1169,7 @@ static struct mm_struct *dup_mm(struct task_struct *tsk) memcpy(mm, oldmm, sizeof(*mm)); - if (!mm_init(mm, tsk, mm->user_ns)) + if (!mm_setup_all(mm, tsk, mm->user_ns)) goto fail_nomem; err = dup_mmap(mm, oldmm); -- 2.12.0