aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-04-20 20:13:58 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-04-20 20:29:13 -0400
commit6be5ceb02e98eaf6cfc4f8b12a896d04023f340d (patch)
treef34de1392300bbf63549f4eeb20f7606d6f7b1f9
parenta46ef99d80817a167477ed1c8b4d90ee0c2e726f (diff)
VM: add "vm_mmap()" helper function
This continues the theme started with vm_brk() and vm_munmap(): vm_mmap() does the same thing as do_mmap(), but additionally does the required VM locking. This uninlines (and rewrites it to be clearer) do_mmap(), which sadly duplicates it in mm/mmap.c and mm/nommu.c. But that way we don't have to export our internal do_mmap_pgoff() function. Some day we hopefully don't have to export do_mmap() either, if all modular users can become the simpler vm_mmap() instead. We're actually very close to that already, with the notable exception of the (broken) use in i810, and a couple of stragglers in binfmt_elf. Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--arch/tile/kernel/single_step.c4
-rw-r--r--arch/x86/ia32/ia32_aout.c12
-rw-r--r--arch/x86/kvm/x86.c4
-rw-r--r--drivers/gpu/drm/drm_bufs.c12
-rw-r--r--drivers/gpu/drm/exynos/exynos_drm_gem.c4
-rw-r--r--drivers/gpu/drm/i810/i810_dma.c1
-rw-r--r--drivers/gpu/drm/i915/i915_gem.c4
-rw-r--r--fs/binfmt_aout.c12
-rw-r--r--fs/binfmt_elf.c8
-rw-r--r--fs/binfmt_elf_fdpic.c18
-rw-r--r--fs/binfmt_flat.c12
-rw-r--r--fs/binfmt_som.c12
-rw-r--r--include/linux/mm.h23
-rw-r--r--mm/mmap.c29
-rw-r--r--mm/nommu.c29
15 files changed, 87 insertions, 97 deletions
diff --git a/arch/tile/kernel/single_step.c b/arch/tile/kernel/single_step.c
index 9efbc1391b3c..89529c9f0605 100644
--- a/arch/tile/kernel/single_step.c
+++ b/arch/tile/kernel/single_step.c
@@ -346,12 +346,10 @@ void single_step_once(struct pt_regs *regs)
346 } 346 }
347 347
348 /* allocate a cache line of writable, executable memory */ 348 /* allocate a cache line of writable, executable memory */
349 down_write(&current->mm->mmap_sem); 349 buffer = (void __user *) vm_mmap(NULL, 0, 64,
350 buffer = (void __user *) do_mmap(NULL, 0, 64,
351 PROT_EXEC | PROT_READ | PROT_WRITE, 350 PROT_EXEC | PROT_READ | PROT_WRITE,
352 MAP_PRIVATE | MAP_ANONYMOUS, 351 MAP_PRIVATE | MAP_ANONYMOUS,
353 0); 352 0);
354 up_write(&current->mm->mmap_sem);
355 353
356 if (IS_ERR((void __force *)buffer)) { 354 if (IS_ERR((void __force *)buffer)) {
357 kfree(state); 355 kfree(state);
diff --git a/arch/x86/ia32/ia32_aout.c b/arch/x86/ia32/ia32_aout.c
index b6817ee9033f..4824fb45560f 100644
--- a/arch/x86/ia32/ia32_aout.c
+++ b/arch/x86/ia32/ia32_aout.c
@@ -379,26 +379,22 @@ static int load_aout_binary(struct linux_binprm *bprm, struct pt_regs *regs)
379 goto beyond_if; 379 goto beyond_if;
380 } 380 }
381 381
382 down_write(&current->mm->mmap_sem); 382 error = vm_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
383 error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
384 PROT_READ | PROT_EXEC, 383 PROT_READ | PROT_EXEC,
385 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | 384 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE |
386 MAP_EXECUTABLE | MAP_32BIT, 385 MAP_EXECUTABLE | MAP_32BIT,
387 fd_offset); 386 fd_offset);
388 up_write(&current->mm->mmap_sem);
389 387
390 if (error != N_TXTADDR(ex)) { 388 if (error != N_TXTADDR(ex)) {
391 send_sig(SIGKILL, current, 0); 389 send_sig(SIGKILL, current, 0);
392 return error; 390 return error;
393 } 391 }
394 392
395 down_write(&current->mm->mmap_sem); 393 error = vm_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
396 error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
397 PROT_READ | PROT_WRITE | PROT_EXEC, 394 PROT_READ | PROT_WRITE | PROT_EXEC,
398 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | 395 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE |
399 MAP_EXECUTABLE | MAP_32BIT, 396 MAP_EXECUTABLE | MAP_32BIT,
400 fd_offset + ex.a_text); 397 fd_offset + ex.a_text);
401 up_write(&current->mm->mmap_sem);
402 if (error != N_DATADDR(ex)) { 398 if (error != N_DATADDR(ex)) {
403 send_sig(SIGKILL, current, 0); 399 send_sig(SIGKILL, current, 0);
404 return error; 400 return error;
@@ -482,12 +478,10 @@ static int load_aout_library(struct file *file)
482 goto out; 478 goto out;
483 } 479 }
484 /* Now use mmap to map the library into memory. */ 480 /* Now use mmap to map the library into memory. */
485 down_write(&current->mm->mmap_sem); 481 error = vm_mmap(file, start_addr, ex.a_text + ex.a_data,
486 error = do_mmap(file, start_addr, ex.a_text + ex.a_data,
487 PROT_READ | PROT_WRITE | PROT_EXEC, 482 PROT_READ | PROT_WRITE | PROT_EXEC,
488 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_32BIT, 483 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_32BIT,
489 N_TXTOFF(ex)); 484 N_TXTOFF(ex));
490 up_write(&current->mm->mmap_sem);
491 retval = error; 485 retval = error;
492 if (error != start_addr) 486 if (error != start_addr)
493 goto out; 487 goto out;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 8beb9ce79364..1457be305fb1 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -6336,13 +6336,11 @@ int kvm_arch_prepare_memory_region(struct kvm *kvm,
6336 if (npages && !old.rmap) { 6336 if (npages && !old.rmap) {
6337 unsigned long userspace_addr; 6337 unsigned long userspace_addr;
6338 6338
6339 down_write(&current->mm->mmap_sem); 6339 userspace_addr = vm_mmap(NULL, 0,
6340 userspace_addr = do_mmap(NULL, 0,
6341 npages * PAGE_SIZE, 6340 npages * PAGE_SIZE,
6342 PROT_READ | PROT_WRITE, 6341 PROT_READ | PROT_WRITE,
6343 map_flags, 6342 map_flags,
6344 0); 6343 0);
6345 up_write(&current->mm->mmap_sem);
6346 6344
6347 if (IS_ERR((void *)userspace_addr)) 6345 if (IS_ERR((void *)userspace_addr))
6348 return PTR_ERR((void *)userspace_addr); 6346 return PTR_ERR((void *)userspace_addr);
diff --git a/drivers/gpu/drm/drm_bufs.c b/drivers/gpu/drm/drm_bufs.c
index 30372f7b2d45..348b367debeb 100644
--- a/drivers/gpu/drm/drm_bufs.c
+++ b/drivers/gpu/drm/drm_bufs.c
@@ -1510,8 +1510,8 @@ int drm_freebufs(struct drm_device *dev, void *data,
1510 * \param arg pointer to a drm_buf_map structure. 1510 * \param arg pointer to a drm_buf_map structure.
1511 * \return zero on success or a negative number on failure. 1511 * \return zero on success or a negative number on failure.
1512 * 1512 *
1513 * Maps the AGP, SG or PCI buffer region with do_mmap(), and copies information 1513 * Maps the AGP, SG or PCI buffer region with vm_mmap(), and copies information
1514 * about each buffer into user space. For PCI buffers, it calls do_mmap() with 1514 * about each buffer into user space. For PCI buffers, it calls vm_mmap() with
1515 * offset equal to 0, which drm_mmap() interpretes as PCI buffers and calls 1515 * offset equal to 0, which drm_mmap() interpretes as PCI buffers and calls
1516 * drm_mmap_dma(). 1516 * drm_mmap_dma().
1517 */ 1517 */
@@ -1553,18 +1553,14 @@ int drm_mapbufs(struct drm_device *dev, void *data,
1553 retcode = -EINVAL; 1553 retcode = -EINVAL;
1554 goto done; 1554 goto done;
1555 } 1555 }
1556 down_write(&current->mm->mmap_sem); 1556 virtual = vm_mmap(file_priv->filp, 0, map->size,
1557 virtual = do_mmap(file_priv->filp, 0, map->size,
1558 PROT_READ | PROT_WRITE, 1557 PROT_READ | PROT_WRITE,
1559 MAP_SHARED, 1558 MAP_SHARED,
1560 token); 1559 token);
1561 up_write(&current->mm->mmap_sem);
1562 } else { 1560 } else {
1563 down_write(&current->mm->mmap_sem); 1561 virtual = vm_mmap(file_priv->filp, 0, dma->byte_count,
1564 virtual = do_mmap(file_priv->filp, 0, dma->byte_count,
1565 PROT_READ | PROT_WRITE, 1562 PROT_READ | PROT_WRITE,
1566 MAP_SHARED, 0); 1563 MAP_SHARED, 0);
1567 up_write(&current->mm->mmap_sem);
1568 } 1564 }
1569 if (virtual > -1024UL) { 1565 if (virtual > -1024UL) {
1570 /* Real error */ 1566 /* Real error */
diff --git a/drivers/gpu/drm/exynos/exynos_drm_gem.c b/drivers/gpu/drm/exynos/exynos_drm_gem.c
index 26d51979116b..392ce71ed6a1 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_gem.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_gem.c
@@ -581,10 +581,8 @@ int exynos_drm_gem_mmap_ioctl(struct drm_device *dev, void *data,
581 obj->filp->f_op = &exynos_drm_gem_fops; 581 obj->filp->f_op = &exynos_drm_gem_fops;
582 obj->filp->private_data = obj; 582 obj->filp->private_data = obj;
583 583
584 down_write(&current->mm->mmap_sem); 584 addr = vm_mmap(obj->filp, 0, args->size,
585 addr = do_mmap(obj->filp, 0, args->size,
586 PROT_READ | PROT_WRITE, MAP_SHARED, 0); 585 PROT_READ | PROT_WRITE, MAP_SHARED, 0);
587 up_write(&current->mm->mmap_sem);
588 586
589 drm_gem_object_unreference_unlocked(obj); 587 drm_gem_object_unreference_unlocked(obj);
590 588
diff --git a/drivers/gpu/drm/i810/i810_dma.c b/drivers/gpu/drm/i810/i810_dma.c
index b85337f06fbf..a4ba453b3d27 100644
--- a/drivers/gpu/drm/i810/i810_dma.c
+++ b/drivers/gpu/drm/i810/i810_dma.c
@@ -129,6 +129,7 @@ static int i810_map_buffer(struct drm_buf *buf, struct drm_file *file_priv)
129 if (buf_priv->currently_mapped == I810_BUF_MAPPED) 129 if (buf_priv->currently_mapped == I810_BUF_MAPPED)
130 return -EINVAL; 130 return -EINVAL;
131 131
132 /* This is all entirely broken */
132 down_write(&current->mm->mmap_sem); 133 down_write(&current->mm->mmap_sem);
133 old_fops = file_priv->filp->f_op; 134 old_fops = file_priv->filp->f_op;
134 file_priv->filp->f_op = &i810_buffer_fops; 135 file_priv->filp->f_op = &i810_buffer_fops;
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index 0e3c6acde955..0d1e4b7b4b99 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1087,11 +1087,9 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
1087 if (obj == NULL) 1087 if (obj == NULL)
1088 return -ENOENT; 1088 return -ENOENT;
1089 1089
1090 down_write(&current->mm->mmap_sem); 1090 addr = vm_mmap(obj->filp, 0, args->size,
1091 addr = do_mmap(obj->filp, 0, args->size,
1092 PROT_READ | PROT_WRITE, MAP_SHARED, 1091 PROT_READ | PROT_WRITE, MAP_SHARED,
1093 args->offset); 1092 args->offset);
1094 up_write(&current->mm->mmap_sem);
1095 drm_gem_object_unreference_unlocked(obj); 1093 drm_gem_object_unreference_unlocked(obj);
1096 if (IS_ERR((void *)addr)) 1094 if (IS_ERR((void *)addr))
1097 return addr; 1095 return addr;
diff --git a/fs/binfmt_aout.c b/fs/binfmt_aout.c
index 88527492b917..d146e181d10d 100644
--- a/fs/binfmt_aout.c
+++ b/fs/binfmt_aout.c
@@ -319,24 +319,20 @@ static int load_aout_binary(struct linux_binprm * bprm, struct pt_regs * regs)
319 goto beyond_if; 319 goto beyond_if;
320 } 320 }
321 321
322 down_write(&current->mm->mmap_sem); 322 error = vm_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
323 error = do_mmap(bprm->file, N_TXTADDR(ex), ex.a_text,
324 PROT_READ | PROT_EXEC, 323 PROT_READ | PROT_EXEC,
325 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, 324 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
326 fd_offset); 325 fd_offset);
327 up_write(&current->mm->mmap_sem);
328 326
329 if (error != N_TXTADDR(ex)) { 327 if (error != N_TXTADDR(ex)) {
330 send_sig(SIGKILL, current, 0); 328 send_sig(SIGKILL, current, 0);
331 return error; 329 return error;
332 } 330 }
333 331
334 down_write(&current->mm->mmap_sem); 332 error = vm_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
335 error = do_mmap(bprm->file, N_DATADDR(ex), ex.a_data,
336 PROT_READ | PROT_WRITE | PROT_EXEC, 333 PROT_READ | PROT_WRITE | PROT_EXEC,
337 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE, 334 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE | MAP_EXECUTABLE,
338 fd_offset + ex.a_text); 335 fd_offset + ex.a_text);
339 up_write(&current->mm->mmap_sem);
340 if (error != N_DATADDR(ex)) { 336 if (error != N_DATADDR(ex)) {
341 send_sig(SIGKILL, current, 0); 337 send_sig(SIGKILL, current, 0);
342 return error; 338 return error;
@@ -417,12 +413,10 @@ static int load_aout_library(struct file *file)
417 goto out; 413 goto out;
418 } 414 }
419 /* Now use mmap to map the library into memory. */ 415 /* Now use mmap to map the library into memory. */
420 down_write(&current->mm->mmap_sem); 416 error = vm_mmap(file, start_addr, ex.a_text + ex.a_data,
421 error = do_mmap(file, start_addr, ex.a_text + ex.a_data,
422 PROT_READ | PROT_WRITE | PROT_EXEC, 417 PROT_READ | PROT_WRITE | PROT_EXEC,
423 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE, 418 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
424 N_TXTOFF(ex)); 419 N_TXTOFF(ex));
425 up_write(&current->mm->mmap_sem);
426 retval = error; 420 retval = error;
427 if (error != start_addr) 421 if (error != start_addr)
428 goto out; 422 goto out;
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 0708a0bf0ba9..16f735417072 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -958,10 +958,8 @@ static int load_elf_binary(struct linux_binprm *bprm, struct pt_regs *regs)
958 and some applications "depend" upon this behavior. 958 and some applications "depend" upon this behavior.
959 Since we do not have the power to recompile these, we 959 Since we do not have the power to recompile these, we
960 emulate the SVr4 behavior. Sigh. */ 960 emulate the SVr4 behavior. Sigh. */
961 down_write(&current->mm->mmap_sem); 961 error = vm_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC,
962 error = do_mmap(NULL, 0, PAGE_SIZE, PROT_READ | PROT_EXEC,
963 MAP_FIXED | MAP_PRIVATE, 0); 962 MAP_FIXED | MAP_PRIVATE, 0);
964 up_write(&current->mm->mmap_sem);
965 } 963 }
966 964
967#ifdef ELF_PLAT_INIT 965#ifdef ELF_PLAT_INIT
@@ -1046,8 +1044,7 @@ static int load_elf_library(struct file *file)
1046 eppnt++; 1044 eppnt++;
1047 1045
1048 /* Now use mmap to map the library into memory. */ 1046 /* Now use mmap to map the library into memory. */
1049 down_write(&current->mm->mmap_sem); 1047 error = vm_mmap(file,
1050 error = do_mmap(file,
1051 ELF_PAGESTART(eppnt->p_vaddr), 1048 ELF_PAGESTART(eppnt->p_vaddr),
1052 (eppnt->p_filesz + 1049 (eppnt->p_filesz +
1053 ELF_PAGEOFFSET(eppnt->p_vaddr)), 1050 ELF_PAGEOFFSET(eppnt->p_vaddr)),
@@ -1055,7 +1052,6 @@ static int load_elf_library(struct file *file)
1055 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE, 1052 MAP_FIXED | MAP_PRIVATE | MAP_DENYWRITE,
1056 (eppnt->p_offset - 1053 (eppnt->p_offset -
1057 ELF_PAGEOFFSET(eppnt->p_vaddr))); 1054 ELF_PAGEOFFSET(eppnt->p_vaddr)));
1058 up_write(&current->mm->mmap_sem);
1059 if (error != ELF_PAGESTART(eppnt->p_vaddr)) 1055 if (error != ELF_PAGESTART(eppnt->p_vaddr))
1060 goto out_free_ph; 1056 goto out_free_ph;
1061 1057
diff --git a/fs/binfmt_elf_fdpic.c b/fs/binfmt_elf_fdpic.c
index 9bd5612a8224..d390a0fffc65 100644
--- a/fs/binfmt_elf_fdpic.c
+++ b/fs/binfmt_elf_fdpic.c
@@ -390,21 +390,17 @@ static int load_elf_fdpic_binary(struct linux_binprm *bprm,
390 (executable_stack == EXSTACK_DEFAULT && VM_STACK_FLAGS & VM_EXEC)) 390 (executable_stack == EXSTACK_DEFAULT && VM_STACK_FLAGS & VM_EXEC))
391 stack_prot |= PROT_EXEC; 391 stack_prot |= PROT_EXEC;
392 392
393 down_write(&current->mm->mmap_sem); 393 current->mm->start_brk = vm_mmap(NULL, 0, stack_size, stack_prot,
394 current->mm->start_brk = do_mmap(NULL, 0, stack_size, stack_prot,
395 MAP_PRIVATE | MAP_ANONYMOUS | 394 MAP_PRIVATE | MAP_ANONYMOUS |
396 MAP_UNINITIALIZED | MAP_GROWSDOWN, 395 MAP_UNINITIALIZED | MAP_GROWSDOWN,
397 0); 396 0);
398 397
399 if (IS_ERR_VALUE(current->mm->start_brk)) { 398 if (IS_ERR_VALUE(current->mm->start_brk)) {
400 up_write(&current->mm->mmap_sem);
401 retval = current->mm->start_brk; 399 retval = current->mm->start_brk;
402 current->mm->start_brk = 0; 400 current->mm->start_brk = 0;
403 goto error_kill; 401 goto error_kill;
404 } 402 }
405 403
406 up_write(&current->mm->mmap_sem);
407
408 current->mm->brk = current->mm->start_brk; 404 current->mm->brk = current->mm->start_brk;
409 current->mm->context.end_brk = current->mm->start_brk; 405 current->mm->context.end_brk = current->mm->start_brk;
410 current->mm->context.end_brk += 406 current->mm->context.end_brk +=
@@ -955,10 +951,8 @@ static int elf_fdpic_map_file_constdisp_on_uclinux(
955 if (params->flags & ELF_FDPIC_FLAG_EXECUTABLE) 951 if (params->flags & ELF_FDPIC_FLAG_EXECUTABLE)
956 mflags |= MAP_EXECUTABLE; 952 mflags |= MAP_EXECUTABLE;
957 953
958 down_write(&mm->mmap_sem); 954 maddr = vm_mmap(NULL, load_addr, top - base,
959 maddr = do_mmap(NULL, load_addr, top - base,
960 PROT_READ | PROT_WRITE | PROT_EXEC, mflags, 0); 955 PROT_READ | PROT_WRITE | PROT_EXEC, mflags, 0);
961 up_write(&mm->mmap_sem);
962 if (IS_ERR_VALUE(maddr)) 956 if (IS_ERR_VALUE(maddr))
963 return (int) maddr; 957 return (int) maddr;
964 958
@@ -1096,10 +1090,8 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
1096 1090
1097 /* create the mapping */ 1091 /* create the mapping */
1098 disp = phdr->p_vaddr & ~PAGE_MASK; 1092 disp = phdr->p_vaddr & ~PAGE_MASK;
1099 down_write(&mm->mmap_sem); 1093 maddr = vm_mmap(file, maddr, phdr->p_memsz + disp, prot, flags,
1100 maddr = do_mmap(file, maddr, phdr->p_memsz + disp, prot, flags,
1101 phdr->p_offset - disp); 1094 phdr->p_offset - disp);
1102 up_write(&mm->mmap_sem);
1103 1095
1104 kdebug("mmap[%d] <file> sz=%lx pr=%x fl=%x of=%lx --> %08lx", 1096 kdebug("mmap[%d] <file> sz=%lx pr=%x fl=%x of=%lx --> %08lx",
1105 loop, phdr->p_memsz + disp, prot, flags, 1097 loop, phdr->p_memsz + disp, prot, flags,
@@ -1143,10 +1135,8 @@ static int elf_fdpic_map_file_by_direct_mmap(struct elf_fdpic_params *params,
1143 unsigned long xmaddr; 1135 unsigned long xmaddr;
1144 1136
1145 flags |= MAP_FIXED | MAP_ANONYMOUS; 1137 flags |= MAP_FIXED | MAP_ANONYMOUS;
1146 down_write(&mm->mmap_sem); 1138 xmaddr = vm_mmap(NULL, xaddr, excess - excess1,
1147 xmaddr = do_mmap(NULL, xaddr, excess - excess1,
1148 prot, flags, 0); 1139 prot, flags, 0);
1149 up_write(&mm->mmap_sem);
1150 1140
1151 kdebug("mmap[%d] <anon>" 1141 kdebug("mmap[%d] <anon>"
1152 " ad=%lx sz=%lx pr=%x fl=%x of=0 --> %08lx", 1142 " ad=%lx sz=%lx pr=%x fl=%x of=0 --> %08lx",
diff --git a/fs/binfmt_flat.c b/fs/binfmt_flat.c
index 024d20ee3ca3..6b2daf99fab8 100644
--- a/fs/binfmt_flat.c
+++ b/fs/binfmt_flat.c
@@ -542,10 +542,8 @@ static int load_flat_file(struct linux_binprm * bprm,
542 */ 542 */
543 DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n"); 543 DBG_FLT("BINFMT_FLAT: ROM mapping of file (we hope)\n");
544 544
545 down_write(&current->mm->mmap_sem); 545 textpos = vm_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC,
546 textpos = do_mmap(bprm->file, 0, text_len, PROT_READ|PROT_EXEC,
547 MAP_PRIVATE|MAP_EXECUTABLE, 0); 546 MAP_PRIVATE|MAP_EXECUTABLE, 0);
548 up_write(&current->mm->mmap_sem);
549 if (!textpos || IS_ERR_VALUE(textpos)) { 547 if (!textpos || IS_ERR_VALUE(textpos)) {
550 if (!textpos) 548 if (!textpos)
551 textpos = (unsigned long) -ENOMEM; 549 textpos = (unsigned long) -ENOMEM;
@@ -556,10 +554,8 @@ static int load_flat_file(struct linux_binprm * bprm,
556 554
557 len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long); 555 len = data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
558 len = PAGE_ALIGN(len); 556 len = PAGE_ALIGN(len);
559 down_write(&current->mm->mmap_sem); 557 realdatastart = vm_mmap(0, 0, len,
560 realdatastart = do_mmap(0, 0, len,
561 PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0); 558 PROT_READ|PROT_WRITE|PROT_EXEC, MAP_PRIVATE, 0);
562 up_write(&current->mm->mmap_sem);
563 559
564 if (realdatastart == 0 || IS_ERR_VALUE(realdatastart)) { 560 if (realdatastart == 0 || IS_ERR_VALUE(realdatastart)) {
565 if (!realdatastart) 561 if (!realdatastart)
@@ -603,10 +599,8 @@ static int load_flat_file(struct linux_binprm * bprm,
603 599
604 len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long); 600 len = text_len + data_len + extra + MAX_SHARED_LIBS * sizeof(unsigned long);
605 len = PAGE_ALIGN(len); 601 len = PAGE_ALIGN(len);
606 down_write(&current->mm->mmap_sem); 602 textpos = vm_mmap(0, 0, len,
607 textpos = do_mmap(0, 0, len,
608 PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0); 603 PROT_READ | PROT_EXEC | PROT_WRITE, MAP_PRIVATE, 0);
609 up_write(&current->mm->mmap_sem);
610 604
611 if (!textpos || IS_ERR_VALUE(textpos)) { 605 if (!textpos || IS_ERR_VALUE(textpos)) {
612 if (!textpos) 606 if (!textpos)
diff --git a/fs/binfmt_som.c b/fs/binfmt_som.c
index e4fc746629a7..4517aaff61b4 100644
--- a/fs/binfmt_som.c
+++ b/fs/binfmt_som.c
@@ -147,10 +147,8 @@ static int map_som_binary(struct file *file,
147 code_size = SOM_PAGEALIGN(hpuxhdr->exec_tsize); 147 code_size = SOM_PAGEALIGN(hpuxhdr->exec_tsize);
148 current->mm->start_code = code_start; 148 current->mm->start_code = code_start;
149 current->mm->end_code = code_start + code_size; 149 current->mm->end_code = code_start + code_size;
150 down_write(&current->mm->mmap_sem); 150 retval = vm_mmap(file, code_start, code_size, prot,
151 retval = do_mmap(file, code_start, code_size, prot,
152 flags, SOM_PAGESTART(hpuxhdr->exec_tfile)); 151 flags, SOM_PAGESTART(hpuxhdr->exec_tfile));
153 up_write(&current->mm->mmap_sem);
154 if (retval < 0 && retval > -1024) 152 if (retval < 0 && retval > -1024)
155 goto out; 153 goto out;
156 154
@@ -158,20 +156,16 @@ static int map_som_binary(struct file *file,
158 data_size = SOM_PAGEALIGN(hpuxhdr->exec_dsize); 156 data_size = SOM_PAGEALIGN(hpuxhdr->exec_dsize);
159 current->mm->start_data = data_start; 157 current->mm->start_data = data_start;
160 current->mm->end_data = bss_start = data_start + data_size; 158 current->mm->end_data = bss_start = data_start + data_size;
161 down_write(&current->mm->mmap_sem); 159 retval = vm_mmap(file, data_start, data_size,
162 retval = do_mmap(file, data_start, data_size,
163 prot | PROT_WRITE, flags, 160 prot | PROT_WRITE, flags,
164 SOM_PAGESTART(hpuxhdr->exec_dfile)); 161 SOM_PAGESTART(hpuxhdr->exec_dfile));
165 up_write(&current->mm->mmap_sem);
166 if (retval < 0 && retval > -1024) 162 if (retval < 0 && retval > -1024)
167 goto out; 163 goto out;
168 164
169 som_brk = bss_start + SOM_PAGEALIGN(hpuxhdr->exec_bsize); 165 som_brk = bss_start + SOM_PAGEALIGN(hpuxhdr->exec_bsize);
170 current->mm->start_brk = current->mm->brk = som_brk; 166 current->mm->start_brk = current->mm->brk = som_brk;
171 down_write(&current->mm->mmap_sem); 167 retval = vm_mmap(NULL, bss_start, som_brk - bss_start,
172 retval = do_mmap(NULL, bss_start, som_brk - bss_start,
173 prot | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, 0); 168 prot | PROT_WRITE, MAP_FIXED | MAP_PRIVATE, 0);
174 up_write(&current->mm->mmap_sem);
175 if (retval > 0 || retval < -1024) 169 if (retval > 0 || retval < -1024)
176 retval = 0; 170 retval = 0;
177out: 171out:
diff --git a/include/linux/mm.h b/include/linux/mm.h
index cb61950a3aa1..86a692c3b238 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -1393,31 +1393,20 @@ extern int install_special_mapping(struct mm_struct *mm,
1393 1393
1394extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long); 1394extern unsigned long get_unmapped_area(struct file *, unsigned long, unsigned long, unsigned long, unsigned long);
1395 1395
1396extern unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
1397 unsigned long len, unsigned long prot,
1398 unsigned long flag, unsigned long pgoff);
1399extern unsigned long mmap_region(struct file *file, unsigned long addr, 1396extern unsigned long mmap_region(struct file *file, unsigned long addr,
1400 unsigned long len, unsigned long flags, 1397 unsigned long len, unsigned long flags,
1401 vm_flags_t vm_flags, unsigned long pgoff); 1398 vm_flags_t vm_flags, unsigned long pgoff);
1402 1399extern unsigned long do_mmap(struct file *, unsigned long,
1403static inline unsigned long do_mmap(struct file *file, unsigned long addr, 1400 unsigned long, unsigned long,
1404 unsigned long len, unsigned long prot, 1401 unsigned long, unsigned long);
1405 unsigned long flag, unsigned long offset)
1406{
1407 unsigned long ret = -EINVAL;
1408 if ((offset + PAGE_ALIGN(len)) < offset)
1409 goto out;
1410 if (!(offset & ~PAGE_MASK))
1411 ret = do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT);
1412out:
1413 return ret;
1414}
1415
1416extern int do_munmap(struct mm_struct *, unsigned long, size_t); 1402extern int do_munmap(struct mm_struct *, unsigned long, size_t);
1417 1403
1418/* These take the mm semaphore themselves */ 1404/* These take the mm semaphore themselves */
1419extern unsigned long vm_brk(unsigned long, unsigned long); 1405extern unsigned long vm_brk(unsigned long, unsigned long);
1420extern int vm_munmap(struct mm_struct *, unsigned long, size_t); 1406extern int vm_munmap(struct mm_struct *, unsigned long, size_t);
1407extern unsigned long vm_mmap(struct file *, unsigned long,
1408 unsigned long, unsigned long,
1409 unsigned long, unsigned long);
1421 1410
1422/* truncate.c */ 1411/* truncate.c */
1423extern void truncate_inode_pages(struct address_space *, loff_t); 1412extern void truncate_inode_pages(struct address_space *, loff_t);
diff --git a/mm/mmap.c b/mm/mmap.c
index 4af45f519f19..b38b47ef1f77 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -953,7 +953,7 @@ static inline unsigned long round_hint_to_min(unsigned long hint)
953 * The caller must hold down_write(&current->mm->mmap_sem). 953 * The caller must hold down_write(&current->mm->mmap_sem).
954 */ 954 */
955 955
956unsigned long do_mmap_pgoff(struct file *file, unsigned long addr, 956static unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
957 unsigned long len, unsigned long prot, 957 unsigned long len, unsigned long prot,
958 unsigned long flags, unsigned long pgoff) 958 unsigned long flags, unsigned long pgoff)
959{ 959{
@@ -1089,7 +1089,32 @@ unsigned long do_mmap_pgoff(struct file *file, unsigned long addr,
1089 1089
1090 return mmap_region(file, addr, len, flags, vm_flags, pgoff); 1090 return mmap_region(file, addr, len, flags, vm_flags, pgoff);
1091} 1091}
1092EXPORT_SYMBOL(do_mmap_pgoff); 1092
1093unsigned long do_mmap(struct file *file, unsigned long addr,
1094 unsigned long len, unsigned long prot,
1095 unsigned long flag, unsigned long offset)
1096{
1097 if (unlikely(offset + PAGE_ALIGN(len) < offset))
1098 return -EINVAL;
1099 if (unlikely(offset & ~PAGE_MASK))
1100 return -EINVAL;
1101 return do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT);
1102}
1103EXPORT_SYMBOL(do_mmap);
1104
1105unsigned long vm_mmap(struct file *file, unsigned long addr,
1106 unsigned long len, unsigned long prot,
1107 unsigned long flag, unsigned long offset)
1108{
1109 unsigned long ret;
1110 struct mm_struct *mm = current->mm;
1111
1112 down_write(&mm->mmap_sem);
1113 ret = do_mmap(file, addr, len, prot, flag, offset);
1114 up_write(&mm->mmap_sem);
1115 return ret;
1116}
1117EXPORT_SYMBOL(vm_mmap);
1093 1118
1094SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, 1119SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
1095 unsigned long, prot, unsigned long, flags, 1120 unsigned long, prot, unsigned long, flags,
diff --git a/mm/nommu.c b/mm/nommu.c
index 11a69b22bd4b..dd00383be2d9 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -1233,7 +1233,7 @@ enomem:
1233/* 1233/*
1234 * handle mapping creation for uClinux 1234 * handle mapping creation for uClinux
1235 */ 1235 */
1236unsigned long do_mmap_pgoff(struct file *file, 1236static unsigned long do_mmap_pgoff(struct file *file,
1237 unsigned long addr, 1237 unsigned long addr,
1238 unsigned long len, 1238 unsigned long len,
1239 unsigned long prot, 1239 unsigned long prot,
@@ -1470,7 +1470,32 @@ error_getting_region:
1470 show_free_areas(0); 1470 show_free_areas(0);
1471 return -ENOMEM; 1471 return -ENOMEM;
1472} 1472}
1473EXPORT_SYMBOL(do_mmap_pgoff); 1473
1474unsigned long do_mmap(struct file *file, unsigned long addr,
1475 unsigned long len, unsigned long prot,
1476 unsigned long flag, unsigned long offset)
1477{
1478 if (unlikely(offset + PAGE_ALIGN(len) < offset))
1479 return -EINVAL;
1480 if (unlikely(offset & ~PAGE_MASK))
1481 return -EINVAL;
1482 return do_mmap_pgoff(file, addr, len, prot, flag, offset >> PAGE_SHIFT);
1483}
1484EXPORT_SYMBOL(do_mmap);
1485
1486unsigned long vm_mmap(struct file *file, unsigned long addr,
1487 unsigned long len, unsigned long prot,
1488 unsigned long flag, unsigned long offset)
1489{
1490 unsigned long ret;
1491 struct mm_struct *mm = current->mm;
1492
1493 down_write(&mm->mmap_sem);
1494 ret = do_mmap(file, addr, len, prot, flag, offset);
1495 up_write(&mm->mmap_sem);
1496 return ret;
1497}
1498EXPORT_SYMBOL(vm_mmap);
1474 1499
1475SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len, 1500SYSCALL_DEFINE6(mmap_pgoff, unsigned long, addr, unsigned long, len,
1476 unsigned long, prot, unsigned long, flags, 1501 unsigned long, prot, unsigned long, flags,