The new and relatively unused (compared to VM ops) mm_struct exe file reference uses the mmap semaphore. It may be preferrable to avoid using the mmap semaphore at some point in the future. This patch demonstrates one way to avoid using the mmap semaphore for the exe file reference inside /proc/pid/exe ops. Unfortunately we can't entirely avoid using the mmap semaphore because we need to drop the exe file reference when the VMA mapping the executable file does -- otherwise we'd pin mounted filesystems until all applications executed from them exitted. Signed-off-by: Matt Helsley --- include/linux/sched.h | 1 + mm/mmap.c | 17 +++++++++++------ 2 files changed, 12 insertions(+), 6 deletions(-) Index: linux-2.6.23/include/linux/sched.h =================================================================== --- linux-2.6.23.orig/include/linux/sched.h +++ linux-2.6.23/include/linux/sched.h @@ -432,10 +432,11 @@ struct mm_struct { /* aio bits */ rwlock_t ioctx_list_lock; struct kioctx *ioctx_list; /* store ref to file /proc//exe symlink points to */ + spinlock_t exe_file_lock; struct file *exe_file; }; struct sighand_struct { atomic_t count; Index: linux-2.6.23/mm/mmap.c =================================================================== --- linux-2.6.23.orig/mm/mmap.c +++ linux-2.6.23/mm/mmap.c @@ -1706,27 +1706,27 @@ find_extend_vma(struct mm_struct * mm, u * reference; only puts old ones */ void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file) { struct file *old_exe_file; - down_write(&mm->mmap_sem); + spin_lock(&mm->exe_file_lock); old_exe_file = mm->exe_file; mm->exe_file = new_exe_file; - up_write(&mm->mmap_sem); + spin_unlock(&mm->exe_file_lock); if (old_exe_file) fput(old_exe_file); } struct file *get_mm_exe_file(struct mm_struct *mm) { struct file *exe_file; - down_read(&mm->mmap_sem); + spin_lock(&mm->exe_file_lock); exe_file = mm->exe_file; if (exe_file) get_file(exe_file); - up_read(&mm->mmap_sem); + spin_unlock(&mm->exe_file_lock); return exe_file; } #endif /* @@ -1744,14 +1744,19 @@ static void remove_vma_list(struct mm_st mm->total_vm -= nrpages; if (vma->vm_flags & VM_LOCKED) mm->locked_vm -= nrpages; vm_stat_account(mm, vma->vm_flags, vma->vm_file, -nrpages); + spin_lock(&mm->exe_file_lock); if (mm->exe_file && (vma->vm_file == mm->exe_file)) { - fput(mm->exe_file); + struct file *old_exe_file = mm->exe_file; + mm->exe_file = NULL; - } + spin_unlock(&mm->exe_file_lock); + fput(old_exe_file); + } else + spin_unlock(&mm->exe_file_lock); vma = remove_vma(vma); } while (vma); validate_mm(mm); } -- - To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/