diff options
author | Andrea Arcangeli <andrea@suse.de> | 2004-06-17 18:07:59 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@ppc970.osdl.org> | 2004-06-17 18:07:59 -0700 |
commit | 7895536ad84ff642b38e381facae35dc76dc6a6d (patch) | |
tree | 3fc6956b4b6c396438cdeb698662f1568b4b8c1b /mm | |
parent | 962bf13162ecc57e14eb5bec6b83d07ea92383ef (diff) | |
download | history-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.c | 17 |
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; } |