diff options
| author | Linus Torvalds <torvalds@home.transmeta.com> | 2003-01-09 07:21:03 -0800 |
|---|---|---|
| committer | Linus Torvalds <torvalds@penguin.transmeta.com> | 2003-01-09 07:21:03 -0800 |
| commit | 03a85f8e25d52e15112eb5e146e2766337217ed5 (patch) | |
| tree | 1db25f2609646decf638d470b0b9e91dfb1ea5ff | |
| parent | 60e7fd5ede56305f4f05d24c4ae2b5491767efe6 (diff) | |
Fix exec_mmap() to release the MM while we still have it active,
to properly de-activate it and make the child_tid logic work
correctly.
Clear %fs/%gs in deactivate_mm() on x86, since our LDT will no
longer be valid after this.
Update mm_release() to deactivate MM state before releasing,
and avoid the expensive child_tid FUTEX if we're the last user
of the MM.
| -rw-r--r-- | fs/exec.c | 16 | ||||
| -rw-r--r-- | include/asm-alpha/mmu_context.h | 2 | ||||
| -rw-r--r-- | include/asm-arm/mmu_context.h | 2 | ||||
| -rw-r--r-- | include/asm-cris/mmu_context.h | 2 | ||||
| -rw-r--r-- | include/asm-i386/mmu_context.h | 3 | ||||
| -rw-r--r-- | include/asm-ia64/mmu_context.h | 2 | ||||
| -rw-r--r-- | include/asm-m68k/mmu_context.h | 2 | ||||
| -rw-r--r-- | include/asm-m68knommu/mmu_context.h | 2 | ||||
| -rw-r--r-- | include/asm-mips/mmu_context.h | 2 | ||||
| -rw-r--r-- | include/asm-mips64/mmu_context.h | 2 | ||||
| -rw-r--r-- | include/asm-parisc/mmu_context.h | 2 | ||||
| -rw-r--r-- | include/asm-ppc/mmu_context.h | 2 | ||||
| -rw-r--r-- | include/asm-ppc64/mmu_context.h | 2 | ||||
| -rw-r--r-- | include/asm-s390/mmu_context.h | 2 | ||||
| -rw-r--r-- | include/asm-s390x/mmu_context.h | 2 | ||||
| -rw-r--r-- | include/asm-sh/mmu_context.h | 2 | ||||
| -rw-r--r-- | include/asm-sparc/mmu_context.h | 2 | ||||
| -rw-r--r-- | include/asm-sparc64/mmu_context.h | 2 | ||||
| -rw-r--r-- | include/asm-um/mmu_context.h | 2 | ||||
| -rw-r--r-- | include/asm-v850/mmu_context.h | 1 | ||||
| -rw-r--r-- | include/asm-x86_64/mmu_context.h | 2 | ||||
| -rw-r--r-- | include/linux/sched.h | 2 | ||||
| -rw-r--r-- | kernel/exit.c | 2 | ||||
| -rw-r--r-- | kernel/fork.c | 8 |
24 files changed, 57 insertions, 11 deletions
diff --git a/fs/exec.c b/fs/exec.c index 7f6f6a06fa0a..4bc2f4d75f25 100644 --- a/fs/exec.c +++ b/fs/exec.c @@ -497,6 +497,7 @@ int kernel_read(struct file *file, unsigned long offset, static int exec_mmap(struct mm_struct *mm) { + struct task_struct *tsk; struct mm_struct * old_mm, *active_mm; /* Add it to the list of mm's */ @@ -505,14 +506,17 @@ static int exec_mmap(struct mm_struct *mm) mmlist_nr++; spin_unlock(&mmlist_lock); - task_lock(current); + /* Notify parent that we're no longer interested in the old VM */ + tsk = current; old_mm = current->mm; - active_mm = current->active_mm; - current->mm = mm; - current->active_mm = mm; + mm_release(tsk, old_mm); + + task_lock(tsk); + active_mm = tsk->active_mm; + tsk->mm = mm; + tsk->active_mm = mm; activate_mm(active_mm, mm); - task_unlock(current); - mm_release(); + task_unlock(tsk); if (old_mm) { if (active_mm != old_mm) BUG(); mmput(old_mm); diff --git a/include/asm-alpha/mmu_context.h b/include/asm-alpha/mmu_context.h index 6b811d4f692b..5136e8a36329 100644 --- a/include/asm-alpha/mmu_context.h +++ b/include/asm-alpha/mmu_context.h @@ -209,6 +209,8 @@ ev4_activate_mm(struct mm_struct *prev_mm, struct mm_struct *next_mm) tbiap(); } +#define deactivate_mm(tsk,mm) do { } while (0) + #ifdef CONFIG_ALPHA_GENERIC # define switch_mm(a,b,c,d) alpha_mv.mv_switch_mm((a),(b),(c),(d)) # define activate_mm(x,y) alpha_mv.mv_activate_mm((x),(y)) diff --git a/include/asm-arm/mmu_context.h b/include/asm-arm/mmu_context.h index bb96efd98d00..3b3b473c668f 100644 --- a/include/asm-arm/mmu_context.h +++ b/include/asm-arm/mmu_context.h @@ -47,6 +47,8 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next, } } +#define deactivate_mm(tsk,mm) do { } while (0) + static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next) { cpu_switch_mm(next->pgd, next); diff --git a/include/asm-cris/mmu_context.h b/include/asm-cris/mmu_context.h index d12f074c7cb2..6a6ea71a85cd 100644 --- a/include/asm-cris/mmu_context.h +++ b/include/asm-cris/mmu_context.h @@ -7,6 +7,8 @@ extern void destroy_context(struct mm_struct *mm); extern void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk, int cpu); +#define deactivate_mm(tsk,mm) do { } while (0) + #define activate_mm(prev,next) switch_mm((prev),(next),NULL,smp_processor_id()) /* current active pgd - this is similar to other processors pgd diff --git a/include/asm-i386/mmu_context.h b/include/asm-i386/mmu_context.h index 1bacef727bba..2c561831e7c5 100644 --- a/include/asm-i386/mmu_context.h +++ b/include/asm-i386/mmu_context.h @@ -62,6 +62,9 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, str #endif } +#define deactivate_mm(tsk, mm) \ + asm("movl %0,%%fs ; movl %0,%%gs": :"r" (0)) + #define activate_mm(prev, next) \ switch_mm((prev),(next),NULL,smp_processor_id()) diff --git a/include/asm-ia64/mmu_context.h b/include/asm-ia64/mmu_context.h index 9316945bd04f..479d63d05ed9 100644 --- a/include/asm-ia64/mmu_context.h +++ b/include/asm-ia64/mmu_context.h @@ -143,6 +143,8 @@ activate_context (struct mm_struct *mm) } while (unlikely(context != mm->context)); } +#define deactivate_mm(tsk,mm) do { } while (0) + /* * Switch from address space PREV to address space NEXT. */ diff --git a/include/asm-m68k/mmu_context.h b/include/asm-m68k/mmu_context.h index 0e7dcd886560..43e01962d5d8 100644 --- a/include/asm-m68k/mmu_context.h +++ b/include/asm-m68k/mmu_context.h @@ -89,6 +89,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, str } } +#define deactivate_mm(tsk,mm) do { } while (0) + extern inline void activate_mm(struct mm_struct *prev_mm, struct mm_struct *next_mm) { diff --git a/include/asm-m68knommu/mmu_context.h b/include/asm-m68knommu/mmu_context.h index 60a08a527e66..a4286176513c 100644 --- a/include/asm-m68knommu/mmu_context.h +++ b/include/asm-m68knommu/mmu_context.h @@ -23,6 +23,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, str { } +#define deactivate_mm(tsk,mm) do { } while (0) + extern inline void activate_mm(struct mm_struct *prev_mm, struct mm_struct *next_mm) { diff --git a/include/asm-mips/mmu_context.h b/include/asm-mips/mmu_context.h index 1e8e9614a012..831ac14231f8 100644 --- a/include/asm-mips/mmu_context.h +++ b/include/asm-mips/mmu_context.h @@ -98,6 +98,8 @@ extern inline void destroy_context(struct mm_struct *mm) /* Nothing to do. */ } +#define deactivate_mm(tsk,mm) do { } while (0) + /* * After we have set current->mm to a new value, this activates * the context for the new mm so we see the new mappings. diff --git a/include/asm-mips64/mmu_context.h b/include/asm-mips64/mmu_context.h index f47979cb9725..8ce94726497c 100644 --- a/include/asm-mips64/mmu_context.h +++ b/include/asm-mips64/mmu_context.h @@ -111,6 +111,8 @@ extern inline void destroy_context(struct mm_struct *mm) #endif } +#define deactivate_mm(tsk,mm) do { } while (0) + /* * After we have set current->mm to a new value, this activates * the context for the new mm so we see the new mappings. diff --git a/include/asm-parisc/mmu_context.h b/include/asm-parisc/mmu_context.h index e9687b2f8f03..1ff9e5f0582c 100644 --- a/include/asm-parisc/mmu_context.h +++ b/include/asm-parisc/mmu_context.h @@ -52,6 +52,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, str } } +#define deactivate_mm(tsk,mm) do { } while (0) + static inline void activate_mm(struct mm_struct *prev, struct mm_struct *next) { /* diff --git a/include/asm-ppc/mmu_context.h b/include/asm-ppc/mmu_context.h index e1bccc52fc3d..afed0d7151e5 100644 --- a/include/asm-ppc/mmu_context.h +++ b/include/asm-ppc/mmu_context.h @@ -160,6 +160,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, set_context(next->context, next->pgd); } +#define deactivate_mm(tsk,mm) do { } while (0) + /* * After we have set current->mm to a new value, this activates * the context for the new mm so we see the new mappings. diff --git a/include/asm-ppc64/mmu_context.h b/include/asm-ppc64/mmu_context.h index 08d8bd20976a..1014f086e5e7 100644 --- a/include/asm-ppc64/mmu_context.h +++ b/include/asm-ppc64/mmu_context.h @@ -146,6 +146,8 @@ switch_mm(struct mm_struct *prev, struct mm_struct *next, set_bit(cpu, &next->cpu_vm_mask); } +#define deactivate_mm(tsk,mm) do { } while (0) + /* * After we have set current->mm to a new value, this activates * the context for the new mm so we see the new mappings. diff --git a/include/asm-s390/mmu_context.h b/include/asm-s390/mmu_context.h index d58b14cbbdb3..346228089825 100644 --- a/include/asm-s390/mmu_context.h +++ b/include/asm-s390/mmu_context.h @@ -37,6 +37,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, set_bit(cpu, &next->cpu_vm_mask); } +#define deactivate_mm(tsk,mm) do { } while (0) + extern inline void activate_mm(struct mm_struct *prev, struct mm_struct *next) { diff --git a/include/asm-s390x/mmu_context.h b/include/asm-s390x/mmu_context.h index 2af3f46da94f..8d07debc3866 100644 --- a/include/asm-s390x/mmu_context.h +++ b/include/asm-s390x/mmu_context.h @@ -36,6 +36,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, set_bit(cpu, &next->cpu_vm_mask); } +#define deactivate_mm(tsk,mm) do { } while (0) + extern inline void activate_mm(struct mm_struct *prev, struct mm_struct *next) { diff --git a/include/asm-sh/mmu_context.h b/include/asm-sh/mmu_context.h index 47b497a7c77b..c0e1cb4309d7 100644 --- a/include/asm-sh/mmu_context.h +++ b/include/asm-sh/mmu_context.h @@ -178,6 +178,8 @@ static __inline__ void switch_mm(struct mm_struct *prev, } } +#define deactivate_mm(tsk,mm) do { } while (0) + #define activate_mm(prev, next) \ switch_mm((prev),(next),NULL,smp_processor_id()) diff --git a/include/asm-sparc/mmu_context.h b/include/asm-sparc/mmu_context.h index 274707e2d288..f386a8f4bbe8 100644 --- a/include/asm-sparc/mmu_context.h +++ b/include/asm-sparc/mmu_context.h @@ -30,6 +30,8 @@ BTFIXUPDEF_CALL(void, switch_mm, struct mm_struct *, struct mm_struct *, struct #define switch_mm(old_mm, mm, tsk, cpu) BTFIXUP_CALL(switch_mm)(old_mm, mm, tsk, cpu) +#define deactivate_mm(tsk,mm) do { } while (0) + /* Activate a new MM instance for the current task. */ #define activate_mm(active_mm, mm) switch_mm((active_mm), (mm), NULL, smp_processor_id()) diff --git a/include/asm-sparc64/mmu_context.h b/include/asm-sparc64/mmu_context.h index 9aab3e4e9d20..ab9eedf22860 100644 --- a/include/asm-sparc64/mmu_context.h +++ b/include/asm-sparc64/mmu_context.h @@ -143,6 +143,8 @@ static inline void switch_mm(struct mm_struct *old_mm, struct mm_struct *mm, str extern void __flush_tlb_mm(unsigned long, unsigned long); +#define deactivate_mm(tsk,mm) do { } while (0) + /* Activate a new MM instance for the current task. */ static inline void activate_mm(struct mm_struct *active_mm, struct mm_struct *mm) { diff --git a/include/asm-um/mmu_context.h b/include/asm-um/mmu_context.h index e735fe0a95a9..14ca8b2a4628 100644 --- a/include/asm-um/mmu_context.h +++ b/include/asm-um/mmu_context.h @@ -12,6 +12,8 @@ #define get_mmu_context(task) do ; while(0) #define activate_context(tsk) do ; while(0) +#define deactivate_mm(tsk,mm) do { } while (0) + static inline void activate_mm(struct mm_struct *old, struct mm_struct *new) { } diff --git a/include/asm-v850/mmu_context.h b/include/asm-v850/mmu_context.h index 2acc89920d05..24301a46a92e 100644 --- a/include/asm-v850/mmu_context.h +++ b/include/asm-v850/mmu_context.h @@ -4,6 +4,7 @@ #define destroy_context(mm) ((void)0) #define init_new_context(tsk,mm) 0 #define switch_mm(prev,next,tsk,cpu) ((void)0) +#define deactivate_mm(tsk,mm) do { } while (0) #define activate_mm(prev,next) ((void)0) #define enter_lazy_tlb(mm,tsk,cpu) ((void)0) diff --git a/include/asm-x86_64/mmu_context.h b/include/asm-x86_64/mmu_context.h index 3a0c29d2e02b..296390b6b5ad 100644 --- a/include/asm-x86_64/mmu_context.h +++ b/include/asm-x86_64/mmu_context.h @@ -62,6 +62,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, #endif } +#define deactivate_mm(tsk,mm) do { } while (0) + #define activate_mm(prev, next) \ switch_mm((prev),(next),NULL,smp_processor_id()) diff --git a/include/linux/sched.h b/include/linux/sched.h index 9545a1957089..9916d377a74b 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -566,7 +566,7 @@ static inline void mmdrop(struct mm_struct * mm) /* mmput gets rid of the mappings and all user-space */ extern void mmput(struct mm_struct *); /* Remove the current tasks stale references to the old mm_struct */ -extern void mm_release(void); +extern void mm_release(struct task_struct *, struct mm_struct *); extern int copy_thread(int, unsigned long, unsigned long, unsigned long, struct task_struct *, struct pt_regs *); extern void flush_thread(void); diff --git a/kernel/exit.c b/kernel/exit.c index 6adea537242a..1841978bfa4c 100644 --- a/kernel/exit.c +++ b/kernel/exit.c @@ -419,7 +419,7 @@ static inline void __exit_mm(struct task_struct * tsk) { struct mm_struct *mm = tsk->mm; - mm_release(); + mm_release(tsk, mm); if (!mm) return; /* diff --git a/kernel/fork.c b/kernel/fork.c index 1850fb64fd5d..b8fcbbc1862a 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -399,17 +399,19 @@ void mmput(struct mm_struct *mm) * restoring the old one. . . * Eric Biederman 10 January 1998 */ -void mm_release(void) +void mm_release(struct task_struct *tsk, struct mm_struct *mm) { - struct task_struct *tsk = current; struct completion *vfork_done = tsk->vfork_done; + /* Get rid of any cached register state */ + deactivate_mm(tsk, mm); + /* notify parent sleeping on vfork() */ if (vfork_done) { tsk->vfork_done = NULL; complete(vfork_done); } - if (tsk->clear_child_tid) { + if (tsk->clear_child_tid && atomic_read(&mm->mm_users) > 1) { int * tidptr = tsk->clear_child_tid; tsk->clear_child_tid = NULL; |
