Messages in this thread Patch in this message | | | Date | Wed, 21 Jul 1999 14:42:48 -0400 (EDT) | From | Alexander Viro <> | Subject | Re: [2.3.11=pre6]: No OOPS, but mount segfaults remounting "/"? |
| |
On 21 Jul 1999, Linus Torvalds wrote:
> I'm working on a pre-8 right now, but in the meantime pre-7 is the way > to go (I bet that the problem in pre-7 is basically impossible to > trigger unless you really design for it). There may be problems we don't > even know about, so testing is good.
There are. Coredumps are b0rken - we should check for presense of other non-lazy owners instead of the total counter.
I did the counter separation. The differences (aside of the stuff we discussed yesterday): * destroy_context() went to mmput() * I don't see the need to switch to init_mm upon exit_mm() - what for? Old context will serve us equally fine and the next schedule will bury it. We should do exit_mmap(), indeed, but that's it. * -pre7 has a race in exec() for lazy threads. ->active_mm may change while we are allocating new mm and pgd. * in assorted places we should use different counters (coredumps being an example).
Patch follows:
diff -urN linux-2.3.11-pre7/arch/i386/kernel/ldt.c linux-bird.lazy-TLB/arch/i386/kernel/ldt.c --- linux-2.3.11-pre7/arch/i386/kernel/ldt.c Wed Jul 21 02:31:43 1999 +++ linux-bird.lazy-TLB/arch/i386/kernel/ldt.c Wed Jul 21 14:19:15 1999 @@ -94,7 +94,7 @@ if (!mm->segments) goto out_unlock; - if (atomic_read(&mm->count) > 1) + if (atomic_read(&mm->mm_count) > 1) printk(KERN_WARNING "LDT allocated for cloned task!\n"); /* * Possibly do an SMP cross-call to other CPUs to reload diff -urN linux-2.3.11-pre7/arch/sparc/mm/srmmu.c linux-bird.lazy-TLB/arch/sparc/mm/srmmu.c --- linux-2.3.11-pre7/arch/sparc/mm/srmmu.c Tue Jul 6 04:31:10 1999 +++ linux-bird.lazy-TLB/arch/sparc/mm/srmmu.c Wed Jul 21 12:10:41 1999 @@ -2042,7 +2042,7 @@ static void srmmu_destroy_context(struct mm_struct *mm) { - if(mm->context != NO_CONTEXT && atomic_read(&mm->count) == 1) { + if(mm->context != NO_CONTEXT) { /* XXX This could be drastically improved. * XXX We are only called from __exit_mm and it just did * XXX cache/tlb mm flush and right after this will (re-) @@ -2127,7 +2127,7 @@ static void hypersparc_destroy_context(struct mm_struct *mm) { - if(mm->context != NO_CONTEXT && atomic_read(&mm->count) == 1) { + if(mm->context != NO_CONTEXT) { ctxd_t *ctxp; /* HyperSparc is copy-back, any data for this diff -urN linux-2.3.11-pre7/arch/sparc/mm/sun4c.c linux-bird.lazy-TLB/arch/sparc/mm/sun4c.c --- linux-2.3.11-pre7/arch/sparc/mm/sun4c.c Tue Jul 6 04:31:10 1999 +++ linux-bird.lazy-TLB/arch/sparc/mm/sun4c.c Wed Jul 21 12:10:49 1999 @@ -2147,7 +2147,7 @@ { struct ctx_list *ctx_old; - if(mm->context != NO_CONTEXT && atomic_read(&mm->count) == 1) { + if(mm->context != NO_CONTEXT) { sun4c_demap_context_hw(&sun4c_context_ring[mm->context], mm->context); ctx_old = ctx_list_pool + mm->context; remove_from_ctx_list(ctx_old); @@ -2210,7 +2210,7 @@ { struct ctx_list *ctx_old; - if(mm->context != NO_CONTEXT && atomic_read(&mm->count) == 1) { + if(mm->context != NO_CONTEXT) { sun4c_demap_context_sw(&sun4c_context_ring[mm->context], mm->context); ctx_old = ctx_list_pool + mm->context; remove_from_ctx_list(ctx_old); diff -urN linux-2.3.11-pre7/fs/binfmt_aout.c linux-bird.lazy-TLB/fs/binfmt_aout.c --- linux-2.3.11-pre7/fs/binfmt_aout.c Fri Jul 2 21:20:24 1999 +++ linux-bird.lazy-TLB/fs/binfmt_aout.c Wed Jul 21 13:51:34 1999 @@ -106,7 +106,7 @@ # define START_STACK(u) (u.start_stack) #endif - if (!current->dumpable || atomic_read(¤t->mm->count) != 1) + if (!current->dumpable || atomic_read(¤t->mm->mm_users) != 1) return 0; current->dumpable = 0; diff -urN linux-2.3.11-pre7/fs/binfmt_elf.c linux-bird.lazy-TLB/fs/binfmt_elf.c --- linux-2.3.11-pre7/fs/binfmt_elf.c Tue Jul 6 04:33:47 1999 +++ linux-bird.lazy-TLB/fs/binfmt_elf.c Wed Jul 21 13:51:50 1999 @@ -1060,7 +1060,7 @@ if (!current->dumpable || limit < ELF_EXEC_PAGESIZE || - atomic_read(¤t->mm->count) != 1) + atomic_read(¤t->mm->mm_users) != 1) return 0; current->dumpable = 0; diff -urN linux-2.3.11-pre7/fs/exec.c linux-bird.lazy-TLB/fs/exec.c --- linux-2.3.11-pre7/fs/exec.c Wed Jul 21 02:31:53 1999 +++ linux-bird.lazy-TLB/fs/exec.c Wed Jul 21 14:06:52 1999 @@ -374,8 +374,11 @@ * lazy mm, so we can turn it into a real mm. */ old_mm = current->active_mm; - if (atomic_read(&old_mm->count) == 1) { - current->mm = old_mm; + if (atomic_read(&old_mm->mm_count) == 1) { + if (!current->mm) { + atomic_inc(&old_mm->mm_users); + current->mm = old_mm; + } flush_cache_mm(old_mm); mm_release(); release_segments(old_mm); @@ -395,11 +398,15 @@ if (!mm->pgd) goto fail_free; + old_mm = current->active_mm; /* we might sleep */ current->mm = mm; current->active_mm = mm; SET_PAGE_DIR(current, mm->pgd); activate_context(current); mm_release(); + if (atomic_dec_and_test(&old_mm->mm_users)) { + exit_mmap(old_mm); + } mmput(old_mm); return 0; diff -urN linux-2.3.11-pre7/fs/proc/array.c linux-bird.lazy-TLB/fs/proc/array.c --- linux-2.3.11-pre7/fs/proc/array.c Wed Jul 21 02:31:54 1999 +++ linux-bird.lazy-TLB/fs/proc/array.c Wed Jul 21 14:04:17 1999 @@ -1115,7 +1115,7 @@ goto getlen_out; /* Check whether the mmaps could change if we sleep */ - volatile_task = (p != current || atomic_read(&p->mm->count) > 1); + volatile_task = (p != current || atomic_read(&p->mm->mm_users) > 1); /* decode f_pos */ lineno = *ppos >> MAPS_LINE_SHIFT; diff -urN linux-2.3.11-pre7/include/asm-sparc64/mmu_context.h linux-bird.lazy-TLB/include/asm-sparc64/mmu_context.h --- linux-2.3.11-pre7/include/asm-sparc64/mmu_context.h Mon Jun 21 13:17:39 1999 +++ linux-bird.lazy-TLB/include/asm-sparc64/mmu_context.h Wed Jul 21 12:12:00 1999 @@ -35,8 +35,7 @@ * the final reference to the address space. */ #define destroy_context(__mm) do { \ - if ((__mm)->context != NO_CONTEXT && \ - atomic_read(&(__mm)->count) == 1) { \ + if ((__mm)->context != NO_CONTEXT ) { \ if (!(((__mm)->context ^ tlb_context_cache) & CTX_VERSION_MASK))\ clear_bit((__mm)->context & ~(CTX_VERSION_MASK), \ mmu_context_bmap); \ diff -urN linux-2.3.11-pre7/include/linux/sched.h linux-bird.lazy-TLB/include/linux/sched.h --- linux-2.3.11-pre7/include/linux/sched.h Wed Jul 21 02:31:57 1999 +++ linux-bird.lazy-TLB/include/linux/sched.h Wed Jul 21 13:46:53 1999 @@ -170,7 +170,8 @@ struct vm_area_struct * mmap_avl; /* tree of VMAs */ struct vm_area_struct * mmap_cache; /* last find_vma result */ pgd_t * pgd; - atomic_t count; + atomic_t mm_count; + atomic_t mm_users; int map_count; /* number of VMAs */ struct semaphore mmap_sem; spinlock_t page_table_lock; @@ -193,7 +194,7 @@ #define INIT_MM(name) { \ &init_mmap, NULL, NULL, \ swapper_pg_dir, \ - ATOMIC_INIT(2), 1, \ + ATOMIC_INIT(2), ATOMIC_INIT(0), 1, \ __MUTEX_INITIALIZER(name.mmap_sem), \ SPIN_LOCK_UNLOCKED, \ 0, \ @@ -593,7 +594,7 @@ extern struct mm_struct * mm_alloc(void); static inline void mmget(struct mm_struct * mm) { - atomic_inc(&mm->count); + atomic_inc(&mm->mm_count); } extern void mmput(struct mm_struct *); /* Remove the current tasks stale references to the old mm_struct */ diff -urN linux-2.3.11-pre7/kernel/exit.c linux-bird.lazy-TLB/kernel/exit.c --- linux-2.3.11-pre7/kernel/exit.c Wed Jul 21 02:31:58 1999 +++ linux-bird.lazy-TLB/kernel/exit.c Wed Jul 21 13:37:12 1999 @@ -234,26 +234,20 @@ struct mm_struct * mm = tsk->mm; /* Lazy TLB process? */ - if (!mm) { - mm = tsk->active_mm; - goto drop_mm; - } + if (!mm) + return; /* Set us up to use the kernel mm state */ flush_cache_mm(mm); flush_tlb_mm(mm); - destroy_context(mm); mm_release(); /* This turns us into a task with no MM */ tsk->mm = NULL; -drop_mm: - mmget(&init_mm); - tsk->active_mm = &init_mm; tsk->swappable = 0; - SET_PAGE_DIR(tsk, swapper_pg_dir); - mmput(mm); + if (atomic_dec_and_test(&mm->mm_users)) + exit_mmap(mm); } void exit_mm(struct task_struct *tsk) diff -urN linux-2.3.11-pre7/kernel/fork.c linux-bird.lazy-TLB/kernel/fork.c --- linux-2.3.11-pre7/kernel/fork.c Wed Jul 21 02:31:58 1999 +++ linux-bird.lazy-TLB/kernel/fork.c Wed Jul 21 13:50:20 1999 @@ -301,7 +301,8 @@ if (mm) { memset(mm, 0, sizeof(*mm)); init_new_context(mm); - atomic_set(&mm->count, 1); + atomic_set(&mm->mm_count, 1); + atomic_set(&mm->mm_users, 1); init_MUTEX(&mm->mmap_sem); mm->page_table_lock = SPIN_LOCK_UNLOCKED; } @@ -337,10 +338,10 @@ */ void mmput(struct mm_struct *mm) { - if (atomic_dec_and_test(&mm->count)) { + if (atomic_dec_and_test(&mm->mm_count)) { if (mm == &init_mm) BUG(); + destroy_context(mm); release_segments(mm); - exit_mmap(mm); free_page_tables(mm); kmem_cache_free(mm_cachep, mm); } @@ -368,6 +369,7 @@ return 0; if (clone_flags & CLONE_VM) { + atomic_inc(&mm->mm_users); mmget(mm); goto good_mm; } @@ -401,11 +403,12 @@ SET_PAGE_DIR(tsk, mm->pgd); return 0; +free_pt: + release_segments(mm); + exit_mmap(mm); + free_page_tables(mm); free_mm: kmem_cache_free(mm_cachep, mm); - return retval; -free_pt: - mmput(mm); fail_nomem: return retval; }
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.rutgers.edu Please read the FAQ at http://www.tux.org/lkml/
| |