patch-2.1.52 linux/kernel/fork.c

Next file: linux/mm/filemap.c
Previous file: linux/kernel/exit.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.1.51/linux/kernel/fork.c linux/kernel/fork.c
@@ -258,36 +258,62 @@
 	return 0;
 
 fail_nomem:
-	exit_mmap(mm);
 	flush_tlb_mm(current->mm);
 	return retval;
 }
 
+/*
+ * Allocate and initialize an mm_struct.
+ */
+struct mm_struct * mm_alloc(void)
+{
+	struct mm_struct * mm;
+
+	mm = kmem_cache_alloc(mm_cachep, SLAB_KERNEL);
+	if (mm) {
+		*mm = *current->mm;
+		init_new_context(mm);
+		mm->count = 1;
+		mm->def_flags = 0;
+		mm->mmap_sem = MUTEX;
+		mm->pgd = NULL;
+		mm->mmap = mm->mmap_cache = NULL;
+
+		/* It has not run yet, so cannot be present in anyone's
+		 * cache or tlb.
+		 */
+		mm->cpu_vm_mask = 0;
+	}
+	return mm;
+}
+
+/*
+ * Decrement the use count and release all resources for an mm.
+ */
+void mmput(struct mm_struct *mm)
+{
+	if (!--mm->count) {
+		exit_mmap(mm);
+		free_page_tables(mm);
+		kmem_cache_free(mm_cachep, mm);
+	}
+}
+
 static inline int copy_mm(unsigned long clone_flags, struct task_struct * tsk)
 {
 	struct mm_struct * mm;
 	int retval;
 
 	if (clone_flags & CLONE_VM) {
-		current->mm->count++;
+		mmget(current->mm);
 		SET_PAGE_DIR(tsk, current->mm->pgd);
 		return 0;
 	}
 
 	retval = -ENOMEM;
-	mm = kmem_cache_alloc(mm_cachep, SLAB_KERNEL);
+	mm = mm_alloc();
 	if (!mm)
 		goto fail_nomem;
-	*mm = *current->mm;
-	init_new_context(mm);
-	mm->count = 1;
-	mm->def_flags = 0;
-	mm->mmap_sem = MUTEX;
-
-	/* It has not run yet, so cannot be present in anyone's
-	 * cache or tlb.
-	 */
-	mm->cpu_vm_mask = 0;
 
 	tsk->mm = mm;
 	tsk->min_flt = tsk->maj_flt = 0;
@@ -298,14 +324,12 @@
 		goto free_mm;
 	retval = dup_mmap(mm);
 	if (retval)
-		goto free_pt;
+		goto free_mm;
 	return 0;
 
-free_pt:
-	free_page_tables(mm);
 free_mm:
 	tsk->mm = NULL;
-	kmem_cache_free(mm_cachep, mm);
+	mmput(mm);
 fail_nomem:
 	return retval;
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov