--- fs/proc/base.c~ 2006-03-22 21:39:04.000000000 +0000 +++ fs/proc/base.c 2006-03-22 09:42:28.000000000 +0000 @@ -95,6 +95,7 @@ PROC_TGID_CWD, PROC_TGID_ROOT, PROC_TGID_EXE, + PROC_TGID_EXEDIR, PROC_TGID_FD, PROC_TGID_ENVIRON, PROC_TGID_AUXV, @@ -135,6 +136,7 @@ PROC_TID_CWD, PROC_TID_ROOT, PROC_TID_EXE, + PROC_TID_EXEDIR, PROC_TID_FD, PROC_TID_ENVIRON, PROC_TID_AUXV, @@ -200,6 +202,7 @@ E(PROC_TGID_CWD, "cwd", S_IFLNK|S_IRWXUGO), E(PROC_TGID_ROOT, "root", S_IFLNK|S_IRWXUGO), E(PROC_TGID_EXE, "exe", S_IFLNK|S_IRWXUGO), + E(PROC_TGID_EXEDIR, "exedir", S_IFLNK|S_IRWXUGO), E(PROC_TGID_MOUNTS, "mounts", S_IFREG|S_IRUGO), #ifdef CONFIG_MMU E(PROC_TGID_SMAPS, "smaps", S_IFREG|S_IRUGO), @@ -242,6 +245,7 @@ E(PROC_TID_CWD, "cwd", S_IFLNK|S_IRWXUGO), E(PROC_TID_ROOT, "root", S_IFLNK|S_IRWXUGO), E(PROC_TID_EXE, "exe", S_IFLNK|S_IRWXUGO), + E(PROC_TID_EXEDIR, "exedir", S_IFLNK|S_IRWXUGO), E(PROC_TID_MOUNTS, "mounts", S_IFREG|S_IRUGO), #ifdef CONFIG_MMU E(PROC_TID_SMAPS, "smaps", S_IFREG|S_IRUGO), @@ -1656,6 +1660,11 @@ inode->i_op = &proc_pid_link_inode_operations; ei->op.proc_get_link = proc_exe_link; break; + case PROC_TID_EXEDIR: + case PROC_TGID_EXEDIR: + inode->i_op = &proc_pid_link_inode_operations; + ei->op.proc_get_link = proc_exedir_link; + break; case PROC_TID_CWD: case PROC_TGID_CWD: inode->i_op = &proc_pid_link_inode_operations; --- fs/proc/internal.h~ 2006-03-13 23:40:39.000000000 +0000 +++ fs/proc/internal.h 2006-03-22 09:46:08.000000000 +0000 @@ -32,6 +32,7 @@ extern void create_seq_entry(char *name, mode_t mode, struct file_operations *f); extern int proc_exe_link(struct inode *, struct dentry **, struct vfsmount **); +extern int proc_exedir_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt); extern int proc_tid_stat(struct task_struct *, char *); extern int proc_tgid_stat(struct task_struct *, char *); extern int proc_pid_status(struct task_struct *, char *); --- fs/proc/task_mmu.c~ 2006-03-22 21:43:37.000000000 +0000 +++ fs/proc/task_mmu.c 2006-03-22 10:26:37.000000000 +0000 @@ -101,6 +101,20 @@ return result; } +int proc_exedir_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt) +{ + struct dentry *exe; + int result = proc_exe_link(inode, &exe, mnt); + + if (result < 0) + return result; + + *dentry = dget_parent(exe); + dput(exe); + + return result; +} + static void pad_len_spaces(struct seq_file *m, int len) { len = 25 + sizeof(void*) * 6 - len; --- fs/proc/task_nommu.c~ 2006-03-22 21:45:24.000000000 +0000 +++ fs/proc/task_nommu.c 2006-03-22 10:20:26.000000000 +0000 @@ -137,6 +137,20 @@ return result; } +int proc_exedir_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt) +{ + struct dentry *exe; + int result = proc_exe_link(inode, &exe, mnt); + + if (result < 0) + return result; + + *dentry = dget_parent(exe); + dput(exe); + + return result; +} + /* * Albert D. Cahalan suggested to fake entries for the traditional * sections here. This might be worth investigating.