From: Andrea Arcangeli 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 --- 25-akpm/mm/fremap.c | 17 ++++++++++++----- 1 files changed, 12 insertions(+), 5 deletions(-) diff -puN mm/fremap.c~remap_file_pages-speedup mm/fremap.c --- 25/mm/fremap.c~remap_file_pages-speedup Tue Jun 8 13:21:46 2004 +++ 25-akpm/mm/fremap.c Tue Jun 8 13:22:03 2004 @@ -161,6 +161,7 @@ asmlinkage long sys_remap_file_pages(uns 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(uns #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(uns /* 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(uns 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(uns * 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; } _