lkml.org 
[lkml]   [1999]   [Jul]   [21]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectRe: [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(&current->mm->count) != 1)
+ if (!current->dumpable || atomic_read(&current->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(&current->mm->count) != 1)
+ atomic_read(&current->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/

\
 
 \ /
  Last update: 2005-03-22 13:53    [from the cache]
©2003-2011 Jasper Spaans. Advertise on this site