git: e284a6234ffb - stable/13 - linuxkpi: reduce number of stray mm_struct allocations

Konstantin Belousov kib at FreeBSD.org
Mon Apr 26 08:13:38 UTC 2021


The branch stable/13 has been updated by kib:

URL: https://cgit.FreeBSD.org/src/commit/?id=e284a6234ffb946d083e7239512c27855019f2c9

commit e284a6234ffb946d083e7239512c27855019f2c9
Author:     Konstantin Belousov <konstantinb at nvidia.com>
AuthorDate: 2021-03-11 06:48:22 +0000
Commit:     Konstantin Belousov <kib at FreeBSD.org>
CommitDate: 2021-04-26 07:10:13 +0000

    linuxkpi: reduce number of stray mm_struct allocations
    
    (cherry picked from commit fad437ba612a7c19f5cf1633e2d0d1c44d4dd478)
---
 sys/compat/linuxkpi/common/src/linux_current.c | 85 +++++++++++++++-----------
 1 file changed, 50 insertions(+), 35 deletions(-)

diff --git a/sys/compat/linuxkpi/common/src/linux_current.c b/sys/compat/linuxkpi/common/src/linux_current.c
index ef51acc1952e..9bae7ee92e49 100644
--- a/sys/compat/linuxkpi/common/src/linux_current.c
+++ b/sys/compat/linuxkpi/common/src/linux_current.c
@@ -48,15 +48,35 @@ static eventhandler_tag linuxkpi_thread_dtor_tag;
 static uma_zone_t linux_current_zone;
 static uma_zone_t linux_mm_zone;
 
+/* check if another thread already has a mm_struct */
+static struct mm_struct *
+find_other_mm(struct proc *p)
+{
+	struct thread *td;
+	struct task_struct *ts;
+	struct mm_struct *mm;
+
+	PROC_LOCK_ASSERT(p, MA_OWNED);
+	FOREACH_THREAD_IN_PROC(p, td) {
+		ts = td->td_lkpi_task;
+		if (ts == NULL)
+			continue;
+		mm = ts->mm;
+		if (mm == NULL)
+			continue;
+		/* try to share other mm_struct */
+		if (atomic_inc_not_zero(&mm->mm_users))
+			return (mm);
+	}
+	return (NULL);
+}
+
 int
 linux_alloc_current(struct thread *td, int flags)
 {
 	struct proc *proc;
-	struct thread *td_other;
 	struct task_struct *ts;
-	struct task_struct *ts_other;
-	struct mm_struct *mm;
-	struct mm_struct *mm_other;
+	struct mm_struct *mm, *mm_other;
 
 	MPASS(td->td_lkpi_task == NULL);
 
@@ -71,14 +91,7 @@ linux_alloc_current(struct thread *td, int flags)
 			panic("linux_alloc_current: failed to allocate task");
 		return (ENOMEM);
 	}
-
-	mm = uma_zalloc(linux_mm_zone, flags | M_ZERO);
-	if (mm == NULL) {
-		if ((flags & (M_WAITOK | M_NOWAIT)) == M_WAITOK)
-			panic("linux_alloc_current: failed to allocate mm");
-		uma_zfree(linux_current_zone, mm);
-		return (ENOMEM);
-	}
+	mm = NULL;
 
 	/* setup new task structure */
 	atomic_set(&ts->kthread_flags, 0);
@@ -93,35 +106,37 @@ linux_alloc_current(struct thread *td, int flags)
 
 	proc = td->td_proc;
 
-	/* check if another thread already has a mm_struct */
 	PROC_LOCK(proc);
-	FOREACH_THREAD_IN_PROC(proc, td_other) {
-		ts_other = td_other->td_lkpi_task;
-		if (ts_other == NULL)
-			continue;
+	mm_other = find_other_mm(proc);
 
-		mm_other = ts_other->mm;
-		if (mm_other == NULL)
-			continue;
+	/* use allocated mm_struct as a fallback */
+	if (mm_other == NULL) {
+		PROC_UNLOCK(proc);
+		mm = uma_zalloc(linux_mm_zone, flags | M_ZERO);
+		if (mm == NULL) {
+			if ((flags & (M_WAITOK | M_NOWAIT)) == M_WAITOK)
+				panic(
+			    "linux_alloc_current: failed to allocate mm");
+			uma_zfree(linux_current_zone, mm);
+			return (ENOMEM);
+		}
 
-		/* try to share other mm_struct */
-		if (atomic_inc_not_zero(&mm_other->mm_users)) {
+		PROC_LOCK(proc);
+		mm_other = find_other_mm(proc);
+		if (mm_other == NULL) {
+			/* setup new mm_struct */
+			init_rwsem(&mm->mmap_sem);
+			atomic_set(&mm->mm_count, 1);
+			atomic_set(&mm->mm_users, 1);
 			/* set mm_struct pointer */
+			ts->mm = mm;
+			/* clear pointer to not free memory */
+			mm = NULL;
+		} else {
 			ts->mm = mm_other;
-			break;
 		}
-	}
-
-	/* use allocated mm_struct as a fallback */
-	if (ts->mm == NULL) {
-		/* setup new mm_struct */
-		init_rwsem(&mm->mmap_sem);
-		atomic_set(&mm->mm_count, 1);
-		atomic_set(&mm->mm_users, 1);
-		/* set mm_struct pointer */
-		ts->mm = mm;
-		/* clear pointer to not free memory */
-		mm = NULL;
+	} else {
+		ts->mm = mm_other;
 	}
 
 	/* store pointer to task struct */


More information about the dev-commits-src-all mailing list