aboutsummaryrefslogtreecommitdiffstats
path: root/mm
diff options
context:
space:
mode:
authorMatt Helsley <matthltc@us.ibm.com>2008-04-29 04:01:36 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-29 11:06:17 -0400
commit925d1c401fa6cfd0df5d2e37da8981494ccdec07 (patch)
tree4f3b7a09311cd99783b822350628125e44f9902d /mm
parente93b4ea20adb20f1f1f07f10ba5d7dd739d2843e (diff)
procfs task exe symlink
The kernel implements readlink of /proc/pid/exe by getting the file from the first executable VMA. Then the path to the file is reconstructed and reported as the result. Because of the VMA walk the code is slightly different on nommu systems. This patch avoids separate /proc/pid/exe code on nommu systems. Instead of walking the VMAs to find the first executable file-backed VMA we store a reference to the exec'd file in the mm_struct. That reference would prevent the filesystem holding the executable file from being unmounted even after unmapping the VMAs. So we track the number of VM_EXECUTABLE VMAs and drop the new reference when the last one is unmapped. This avoids pinning the mounted filesystem. [akpm@linux-foundation.org: improve comments] [yamamoto@valinux.co.jp: fix dup_mmap] Signed-off-by: Matt Helsley <matthltc@us.ibm.com> Cc: Oleg Nesterov <oleg@tv-sign.ru> Cc: David Howells <dhowells@redhat.com> Cc:"Eric W. Biederman" <ebiederm@xmission.com> Cc: Christoph Hellwig <hch@lst.de> Cc: Al Viro <viro@zeniv.linux.org.uk> Cc: Hugh Dickins <hugh@veritas.com> Signed-off-by: YAMAMOTO Takashi <yamamoto@valinux.co.jp> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r--mm/mmap.c24
-rw-r--r--mm/nommu.c23
2 files changed, 37 insertions, 10 deletions
diff --git a/mm/mmap.c b/mm/mmap.c
index 677d184b0d42..fac66337da2a 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -230,8 +230,11 @@ static struct vm_area_struct *remove_vma(struct vm_area_struct *vma)
230 might_sleep(); 230 might_sleep();
231 if (vma->vm_ops && vma->vm_ops->close) 231 if (vma->vm_ops && vma->vm_ops->close)
232 vma->vm_ops->close(vma); 232 vma->vm_ops->close(vma);
233 if (vma->vm_file) 233 if (vma->vm_file) {
234 fput(vma->vm_file); 234 fput(vma->vm_file);
235 if (vma->vm_flags & VM_EXECUTABLE)
236 removed_exe_file_vma(vma->vm_mm);
237 }
235 mpol_put(vma_policy(vma)); 238 mpol_put(vma_policy(vma));
236 kmem_cache_free(vm_area_cachep, vma); 239 kmem_cache_free(vm_area_cachep, vma);
237 return next; 240 return next;
@@ -623,8 +626,11 @@ again: remove_next = 1 + (end > next->vm_end);
623 spin_unlock(&mapping->i_mmap_lock); 626 spin_unlock(&mapping->i_mmap_lock);
624 627
625 if (remove_next) { 628 if (remove_next) {
626 if (file) 629 if (file) {
627 fput(file); 630 fput(file);
631 if (next->vm_flags & VM_EXECUTABLE)
632 removed_exe_file_vma(mm);
633 }
628 mm->map_count--; 634 mm->map_count--;
629 mpol_put(vma_policy(next)); 635 mpol_put(vma_policy(next));
630 kmem_cache_free(vm_area_cachep, next); 636 kmem_cache_free(vm_area_cachep, next);
@@ -1154,6 +1160,8 @@ munmap_back:
1154 error = file->f_op->mmap(file, vma); 1160 error = file->f_op->mmap(file, vma);
1155 if (error) 1161 if (error)
1156 goto unmap_and_free_vma; 1162 goto unmap_and_free_vma;
1163 if (vm_flags & VM_EXECUTABLE)
1164 added_exe_file_vma(mm);
1157 } else if (vm_flags & VM_SHARED) { 1165 } else if (vm_flags & VM_SHARED) {
1158 error = shmem_zero_setup(vma); 1166 error = shmem_zero_setup(vma);
1159 if (error) 1167 if (error)
@@ -1185,6 +1193,8 @@ munmap_back:
1185 mpol_put(vma_policy(vma)); 1193 mpol_put(vma_policy(vma));
1186 kmem_cache_free(vm_area_cachep, vma); 1194 kmem_cache_free(vm_area_cachep, vma);
1187 fput(file); 1195 fput(file);
1196 if (vm_flags & VM_EXECUTABLE)
1197 removed_exe_file_vma(mm);
1188 } else { 1198 } else {
1189 vma_link(mm, vma, prev, rb_link, rb_parent); 1199 vma_link(mm, vma, prev, rb_link, rb_parent);
1190 file = vma->vm_file; 1200 file = vma->vm_file;
@@ -1817,8 +1827,11 @@ int split_vma(struct mm_struct * mm, struct vm_area_struct * vma,
1817 } 1827 }
1818 vma_set_policy(new, pol); 1828 vma_set_policy(new, pol);
1819 1829
1820 if (new->vm_file) 1830 if (new->vm_file) {
1821 get_file(new->vm_file); 1831 get_file(new->vm_file);
1832 if (vma->vm_flags & VM_EXECUTABLE)
1833 added_exe_file_vma(mm);
1834 }
1822 1835
1823 if (new->vm_ops && new->vm_ops->open) 1836 if (new->vm_ops && new->vm_ops->open)
1824 new->vm_ops->open(new); 1837 new->vm_ops->open(new);
@@ -2135,8 +2148,11 @@ struct vm_area_struct *copy_vma(struct vm_area_struct **vmap,
2135 new_vma->vm_start = addr; 2148 new_vma->vm_start = addr;
2136 new_vma->vm_end = addr + len; 2149 new_vma->vm_end = addr + len;
2137 new_vma->vm_pgoff = pgoff; 2150 new_vma->vm_pgoff = pgoff;
2138 if (new_vma->vm_file) 2151 if (new_vma->vm_file) {
2139 get_file(new_vma->vm_file); 2152 get_file(new_vma->vm_file);
2153 if (vma->vm_flags & VM_EXECUTABLE)
2154 added_exe_file_vma(mm);
2155 }
2140 if (new_vma->vm_ops && new_vma->vm_ops->open) 2156 if (new_vma->vm_ops && new_vma->vm_ops->open)
2141 new_vma->vm_ops->open(new_vma); 2157 new_vma->vm_ops->open(new_vma);
2142 vma_link(mm, new_vma, prev, rb_link, rb_parent); 2158 vma_link(mm, new_vma, prev, rb_link, rb_parent);
diff --git a/mm/nommu.c b/mm/nommu.c
index 1d32fe89d57b..ef8c62cec697 100644
--- a/mm/nommu.c
+++ b/mm/nommu.c
@@ -966,8 +966,13 @@ unsigned long do_mmap_pgoff(struct file *file,
966 966
967 INIT_LIST_HEAD(&vma->anon_vma_node); 967 INIT_LIST_HEAD(&vma->anon_vma_node);
968 atomic_set(&vma->vm_usage, 1); 968 atomic_set(&vma->vm_usage, 1);
969 if (file) 969 if (file) {
970 get_file(file); 970 get_file(file);
971 if (vm_flags & VM_EXECUTABLE) {
972 added_exe_file_vma(current->mm);
973 vma->vm_mm = current->mm;
974 }
975 }
971 vma->vm_file = file; 976 vma->vm_file = file;
972 vma->vm_flags = vm_flags; 977 vma->vm_flags = vm_flags;
973 vma->vm_start = addr; 978 vma->vm_start = addr;
@@ -1022,8 +1027,11 @@ unsigned long do_mmap_pgoff(struct file *file,
1022 up_write(&nommu_vma_sem); 1027 up_write(&nommu_vma_sem);
1023 kfree(vml); 1028 kfree(vml);
1024 if (vma) { 1029 if (vma) {
1025 if (vma->vm_file) 1030 if (vma->vm_file) {
1026 fput(vma->vm_file); 1031 fput(vma->vm_file);
1032 if (vma->vm_flags & VM_EXECUTABLE)
1033 removed_exe_file_vma(vma->vm_mm);
1034 }
1027 kfree(vma); 1035 kfree(vma);
1028 } 1036 }
1029 return ret; 1037 return ret;
@@ -1053,7 +1061,7 @@ EXPORT_SYMBOL(do_mmap_pgoff);
1053/* 1061/*
1054 * handle mapping disposal for uClinux 1062 * handle mapping disposal for uClinux
1055 */ 1063 */
1056static void put_vma(struct vm_area_struct *vma) 1064static void put_vma(struct mm_struct *mm, struct vm_area_struct *vma)
1057{ 1065{
1058 if (vma) { 1066 if (vma) {
1059 down_write(&nommu_vma_sem); 1067 down_write(&nommu_vma_sem);
@@ -1075,8 +1083,11 @@ static void put_vma(struct vm_area_struct *vma)
1075 realalloc -= kobjsize(vma); 1083 realalloc -= kobjsize(vma);
1076 askedalloc -= sizeof(*vma); 1084 askedalloc -= sizeof(*vma);
1077 1085
1078 if (vma->vm_file) 1086 if (vma->vm_file) {
1079 fput(vma->vm_file); 1087 fput(vma->vm_file);
1088 if (vma->vm_flags & VM_EXECUTABLE)
1089 removed_exe_file_vma(mm);
1090 }
1080 kfree(vma); 1091 kfree(vma);
1081 } 1092 }
1082 1093
@@ -1113,7 +1124,7 @@ int do_munmap(struct mm_struct *mm, unsigned long addr, size_t len)
1113 found: 1124 found:
1114 vml = *parent; 1125 vml = *parent;
1115 1126
1116 put_vma(vml->vma); 1127 put_vma(mm, vml->vma);
1117 1128
1118 *parent = vml->next; 1129 *parent = vml->next;
1119 realalloc -= kobjsize(vml); 1130 realalloc -= kobjsize(vml);
@@ -1158,7 +1169,7 @@ void exit_mmap(struct mm_struct * mm)
1158 1169
1159 while ((tmp = mm->context.vmlist)) { 1170 while ((tmp = mm->context.vmlist)) {
1160 mm->context.vmlist = tmp->next; 1171 mm->context.vmlist = tmp->next;
1161 put_vma(tmp->vma); 1172 put_vma(mm, tmp->vma);
1162 1173
1163 realalloc -= kobjsize(tmp); 1174 realalloc -= kobjsize(tmp);
1164 askedalloc -= sizeof(*tmp); 1175 askedalloc -= sizeof(*tmp);