Commit 7895536a authored by Andrea Arcangeli's avatar Andrea Arcangeli Committed by Linus Torvalds

[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: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 962bf131
...@@ -161,6 +161,7 @@ asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size, ...@@ -161,6 +161,7 @@ asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size,
unsigned long end = start + size; unsigned long end = start + size;
struct vm_area_struct *vma; struct vm_area_struct *vma;
int err = -EINVAL; int err = -EINVAL;
int has_write_lock = 0;
if (__prot) if (__prot)
return err; return err;
...@@ -181,7 +182,8 @@ asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size, ...@@ -181,7 +182,8 @@ asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size,
#endif #endif
/* We need down_write() to change vma->vm_flags. */ /* 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); vma = find_vma(mm, start);
/* /*
...@@ -200,6 +202,12 @@ asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size, ...@@ -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. */ /* Must set VM_NONLINEAR before any pages are populated. */
if (pgoff != linear_page_index(vma, start) && if (pgoff != linear_page_index(vma, start) &&
!(vma->vm_flags & VM_NONLINEAR)) { !(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; mapping = vma->vm_file->f_mapping;
spin_lock(&mapping->i_mmap_lock); spin_lock(&mapping->i_mmap_lock);
flush_dcache_mmap_lock(mapping); flush_dcache_mmap_lock(mapping);
...@@ -212,8 +220,6 @@ asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size, ...@@ -212,8 +220,6 @@ asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size,
spin_unlock(&mapping->i_mmap_lock); 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, err = vma->vm_ops->populate(vma, start, size,
vma->vm_page_prot, vma->vm_page_prot,
pgoff, flags & MAP_NONBLOCK); pgoff, flags & MAP_NONBLOCK);
...@@ -223,10 +229,11 @@ asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size, ...@@ -223,10 +229,11 @@ asmlinkage long sys_remap_file_pages(unsigned long start, unsigned long size,
* it after ->populate completes, and that would prevent * it after ->populate completes, and that would prevent
* downgrading the lock. (Locks can't be upgraded). * downgrading the lock. (Locks can't be upgraded).
*/ */
}
if (likely(!has_write_lock))
up_read(&mm->mmap_sem); up_read(&mm->mmap_sem);
} else { else
up_write(&mm->mmap_sem); up_write(&mm->mmap_sem);
}
return err; return err;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment