summaryrefslogtreecommitdiffstats
path: root/fs/proc/link.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/proc/link.c')
-rw-r--r--fs/proc/link.c74
1 files changed, 42 insertions, 32 deletions
diff --git a/fs/proc/link.c b/fs/proc/link.c
index 6f5c63ec3..69d435600 100644
--- a/fs/proc/link.c
+++ b/fs/proc/link.c
@@ -82,60 +82,70 @@ static struct dentry * proc_follow_link(struct dentry *dentry,
ino &= 0x0000ffff;
result = ERR_PTR(-ENOENT);
- read_lock(&tasklist_lock);
- p = find_task_by_pid(pid);
- if (!p)
- goto out_unlock;
switch (ino) {
case PROC_PID_CWD:
- if (!p->fs || !p->fs->pwd)
- goto out_unlock;
- result = p->fs->pwd;
- goto out_dget;
+ read_lock(&tasklist_lock);
+ p = find_task_by_pid(pid);
+ if (p && p->fs && p->fs->pwd)
+ result = dget(p->fs->pwd);
+ read_unlock(&tasklist_lock);
+ break;
case PROC_PID_ROOT:
- if (!p->fs || !p->fs->root)
- goto out_unlock;
- result = p->fs->root;
- goto out_dget;
+ read_lock(&tasklist_lock);
+ p = find_task_by_pid(pid);
+ if (p && p->fs && p->fs->root)
+ result = dget(p->fs->root);
+ read_unlock(&tasklist_lock);
+ break;
case PROC_PID_EXE: {
+ struct mm_struct *mm = NULL;
struct vm_area_struct * vma;
- if (!p->mm)
- goto out_unlock;
- vma = p->mm->mmap;
+ read_lock(&tasklist_lock);
+ p = find_task_by_pid(pid);
+ if (p)
+ mm = p->mm;
+ if (mm)
+ atomic_inc(&mm->mm_users);
+ read_unlock(&tasklist_lock);
+ if (!mm)
+ break;
+ down(&mm->mmap_sem);
+ vma = mm->mmap;
while (vma) {
if ((vma->vm_flags & VM_EXECUTABLE) &&
vma->vm_file) {
- result = vma->vm_file->f_dentry;
- goto out_dget;
+ result = dget(vma->vm_file->f_dentry);
+ break;
}
vma = vma->vm_next;
}
- goto out_unlock;
+ up(&mm->mmap_sem);
+ mmput(mm);
+ break;
}
default:
if (ino & PROC_PID_FD_DIR) {
struct file * file;
+ struct files_struct *files = NULL;
+ read_lock(&tasklist_lock);
+ p = find_task_by_pid(pid);
+ if (p)
+ files = p->files;
+ read_unlock(&tasklist_lock);
+ if (!files)
+ break;
ino &= 0x7fff;
- if (!p->files) /* shouldn't happen here */
- goto out_unlock;
- read_lock(&p->files->file_lock);
- file = fcheck_task(p, ino);
- if (!file || !file->f_dentry)
- goto out_unlock;
- result = file->f_dentry;
+ read_lock(&files->file_lock);
+ /* XXXXXXXXXXXXXXXXXXXXXXXXXXXXXX */
+ if (ino < files->max_fds &&
+ (file = files->fd[ino]) && file->f_dentry)
+ result = dget(file->f_dentry);
read_unlock(&p->files->file_lock);
- goto out_dget;
}
}
-out_dget:
- result = dget(result);
-
-out_unlock:
- read_unlock(&tasklist_lock);
-
out:
return result;
}