aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorAndrea Arcangeli <andrea@suse.de>2004-06-17 18:07:59 -0700
committerLinus Torvalds <torvalds@ppc970.osdl.org>2004-06-17 18:07:59 -0700
commit7895536ad84ff642b38e381facae35dc76dc6a6d (patch)
tree3fc6956b4b6c396438cdeb698662f1568b4b8c1b /mm
parent962bf13162ecc57e14eb5bec6b83d07ea92383ef (diff)
downloadhistory-7895536ad84ff642b38e381facae35dc76dc6a6d.tar.gz
[PATCH] remap_file_pages() speedup
Avoid taking down_write(mmap_sem) unless we really need it. Seems that the only reason we're taking it for writing is to protect vma->vm_flags. Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/fremap.c17
1 files changed, 12 insertions, 5 deletions
diff --git a/mm/fremap.c b/mm/fremap.c
index eb056db90eb4e8..eae08b22a0544a 100644
--- a/mm/fremap.c
+++ b/mm/fremap.c
@@ -161,6 +161,7 @@ asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size,
unsigned long end = start + size;
struct vm_area_struct *vma;
int err = -EINVAL;
+ int has_write_lock = 0;
if (__prot)
return err;
@@ -181,7 +182,8 @@ asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size,
#endif
/* We need down_write() to change vma->vm_flags. */
- down_write(&mm->mmap_sem);
+ down_read(&mm->mmap_sem);
+ retry:
vma = find_vma(mm, start);
/*
@@ -200,6 +202,12 @@ asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size,
/* Must set VM_NONLINEAR before any pages are populated. */
if (pgoff != linear_page_index(vma, start) &&
!(vma->vm_flags & VM_NONLINEAR)) {
+ if (!has_write_lock) {
+ up_read(&mm->mmap_sem);
+ down_write(&mm->mmap_sem);
+ has_write_lock = 1;
+ goto retry;
+ }
mapping = vma->vm_file->f_mapping;
spin_lock(&mapping->i_mmap_lock);
flush_dcache_mmap_lock(mapping);
@@ -212,8 +220,6 @@ asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size,
spin_unlock(&mapping->i_mmap_lock);
}
- /* ->populate can take a long time, so downgrade the lock. */
- downgrade_write(&mm->mmap_sem);
err = vma->vm_ops->populate(vma, start, size,
vma->vm_page_prot,
pgoff, flags & MAP_NONBLOCK);
@@ -223,10 +229,11 @@ asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size,
* it after ->populate completes, and that would prevent
* downgrading the lock. (Locks can't be upgraded).
*/
+ }
+ if (likely(!has_write_lock))
up_read(&mm->mmap_sem);
- } else {
+ else
up_write(&mm->mmap_sem);
- }
return err;
}