aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc/base.c
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 /fs/proc/base.c
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 'fs/proc/base.c')
-rw-r--r--fs/proc/base.c75
1 files changed, 75 insertions, 0 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c
index c5e412a00b17..b48ddb119945 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1181,6 +1181,81 @@ static const struct file_operations proc_pid_sched_operations = {
1181 1181
1182#endif 1182#endif
1183 1183
1184/*
1185 * We added or removed a vma mapping the executable. The vmas are only mapped
1186 * during exec and are not mapped with the mmap system call.
1187 * Callers must hold down_write() on the mm's mmap_sem for these
1188 */
1189void added_exe_file_vma(struct mm_struct *mm)
1190{
1191 mm->num_exe_file_vmas++;
1192}
1193
1194void removed_exe_file_vma(struct mm_struct *mm)
1195{
1196 mm->num_exe_file_vmas--;
1197 if ((mm->num_exe_file_vmas == 0) && mm->exe_file){
1198 fput(mm->exe_file);
1199 mm->exe_file = NULL;
1200 }
1201
1202}
1203
1204void set_mm_exe_file(struct mm_struct *mm, struct file *new_exe_file)
1205{
1206 if (new_exe_file)
1207 get_file(new_exe_file);
1208 if (mm->exe_file)
1209 fput(mm->exe_file);
1210 mm->exe_file = new_exe_file;
1211 mm->num_exe_file_vmas = 0;
1212}
1213
1214struct file *get_mm_exe_file(struct mm_struct *mm)
1215{
1216 struct file *exe_file;
1217
1218 /* We need mmap_sem to protect against races with removal of
1219 * VM_EXECUTABLE vmas */
1220 down_read(&mm->mmap_sem);
1221 exe_file = mm->exe_file;
1222 if (exe_file)
1223 get_file(exe_file);
1224 up_read(&mm->mmap_sem);
1225 return exe_file;
1226}
1227
1228void dup_mm_exe_file(struct mm_struct *oldmm, struct mm_struct *newmm)
1229{
1230 /* It's safe to write the exe_file pointer without exe_file_lock because
1231 * this is called during fork when the task is not yet in /proc */
1232 newmm->exe_file = get_mm_exe_file(oldmm);
1233}
1234
1235static int proc_exe_link(struct inode *inode, struct path *exe_path)
1236{
1237 struct task_struct *task;
1238 struct mm_struct *mm;
1239 struct file *exe_file;
1240
1241 task = get_proc_task(inode);
1242 if (!task)
1243 return -ENOENT;
1244 mm = get_task_mm(task);
1245 put_task_struct(task);
1246 if (!mm)
1247 return -ENOENT;
1248 exe_file = get_mm_exe_file(mm);
1249 mmput(mm);
1250 if (exe_file) {
1251 *exe_path = exe_file->f_path;
1252 path_get(&exe_file->f_path);
1253 fput(exe_file);
1254 return 0;
1255 } else
1256 return -ENOENT;
1257}
1258
1184static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd) 1259static void *proc_pid_follow_link(struct dentry *dentry, struct nameidata *nd)
1185{ 1260{
1186 struct inode *inode = dentry->d_inode; 1261 struct inode *inode = dentry->d_inode;