]> rtime.felk.cvut.cz Git - lisovros/linux_canprio.git/blobdiff - fs/proc/base.c
[PATCH] proc: Remove the hard coded inode numbers
[lisovros/linux_canprio.git] / fs / proc / base.c
index e8084eb037e3034cb7f0fe7adc9a059edbe40fa0..7bf28c3af70c3fcb7d5ba1e343826968bbee9e25 100644 (file)
  *     in /proc for a task before it execs a suid executable.
  */
 
-/*
- * For hysterical raisins we keep the same inumbers as in the old procfs.
- * Feel free to change the macro below - just keep the range distinct from
- * inumbers of the rest of procfs (currently those are in 0x0000--0xffff).
- * As soon as we'll get a separate superblock we will be able to forget
- * about magical ranges too.
- */
-
-#define fake_ino(pid,ino) (((pid)<<16)|(ino))
-
-enum pid_directory_inos {
-       PROC_TGID_INO = 2,
-       PROC_TGID_TASK,
-       PROC_TGID_STATUS,
-       PROC_TGID_MEM,
-#ifdef CONFIG_SECCOMP
-       PROC_TGID_SECCOMP,
-#endif
-       PROC_TGID_CWD,
-       PROC_TGID_ROOT,
-       PROC_TGID_EXE,
-       PROC_TGID_FD,
-       PROC_TGID_ENVIRON,
-       PROC_TGID_AUXV,
-       PROC_TGID_CMDLINE,
-       PROC_TGID_STAT,
-       PROC_TGID_STATM,
-       PROC_TGID_MAPS,
-       PROC_TGID_NUMA_MAPS,
-       PROC_TGID_MOUNTS,
-       PROC_TGID_MOUNTSTATS,
-       PROC_TGID_WCHAN,
-#ifdef CONFIG_MMU
-       PROC_TGID_SMAPS,
-#endif
-#ifdef CONFIG_SCHEDSTATS
-       PROC_TGID_SCHEDSTAT,
-#endif
-#ifdef CONFIG_CPUSETS
-       PROC_TGID_CPUSET,
-#endif
-#ifdef CONFIG_SECURITY
-       PROC_TGID_ATTR,
-       PROC_TGID_ATTR_CURRENT,
-       PROC_TGID_ATTR_PREV,
-       PROC_TGID_ATTR_EXEC,
-       PROC_TGID_ATTR_FSCREATE,
-       PROC_TGID_ATTR_KEYCREATE,
-       PROC_TGID_ATTR_SOCKCREATE,
-#endif
-#ifdef CONFIG_AUDITSYSCALL
-       PROC_TGID_LOGINUID,
-#endif
-       PROC_TGID_OOM_SCORE,
-       PROC_TGID_OOM_ADJUST,
-       PROC_TID_INO,
-       PROC_TID_STATUS,
-       PROC_TID_MEM,
-#ifdef CONFIG_SECCOMP
-       PROC_TID_SECCOMP,
-#endif
-       PROC_TID_CWD,
-       PROC_TID_ROOT,
-       PROC_TID_EXE,
-       PROC_TID_FD,
-       PROC_TID_ENVIRON,
-       PROC_TID_AUXV,
-       PROC_TID_CMDLINE,
-       PROC_TID_STAT,
-       PROC_TID_STATM,
-       PROC_TID_MAPS,
-       PROC_TID_NUMA_MAPS,
-       PROC_TID_MOUNTS,
-       PROC_TID_MOUNTSTATS,
-       PROC_TID_WCHAN,
-#ifdef CONFIG_MMU
-       PROC_TID_SMAPS,
-#endif
-#ifdef CONFIG_SCHEDSTATS
-       PROC_TID_SCHEDSTAT,
-#endif
-#ifdef CONFIG_CPUSETS
-       PROC_TID_CPUSET,
-#endif
-#ifdef CONFIG_SECURITY
-       PROC_TID_ATTR,
-       PROC_TID_ATTR_CURRENT,
-       PROC_TID_ATTR_PREV,
-       PROC_TID_ATTR_EXEC,
-       PROC_TID_ATTR_FSCREATE,
-       PROC_TID_ATTR_KEYCREATE,
-       PROC_TID_ATTR_SOCKCREATE,
-#endif
-#ifdef CONFIG_AUDITSYSCALL
-       PROC_TID_LOGINUID,
-#endif
-       PROC_TID_OOM_SCORE,
-       PROC_TID_OOM_ADJUST,
-
-       /* Add new entries before this */
-       PROC_TID_FD_DIR = 0x8000,       /* 0x8000-0xffff */
-};
 
 /* Worst case buffer size needed for holding an integer. */
 #define PROC_NUMBUF 10
 
 struct pid_entry {
-       int type;
        int len;
        char *name;
        mode_t mode;
@@ -200,8 +97,7 @@ struct pid_entry {
        union proc_op op;
 };
 
-#define NOD(TYPE, NAME, MODE, IOP, FOP, OP) {          \
-       .type = (TYPE),                                 \
+#define NOD(NAME, MODE, IOP, FOP, OP) {                        \
        .len  = sizeof(NAME) - 1,                       \
        .name = (NAME),                                 \
        .mode = MODE,                                   \
@@ -210,19 +106,19 @@ struct pid_entry {
        .op   = OP,                                     \
 }
 
-#define DIR(TYPE, NAME, MODE, OTYPE)                                           \
-       NOD(TYPE, NAME, (S_IFDIR|(MODE)),                                       \
+#define DIR(NAME, MODE, OTYPE)                                                 \
+       NOD(NAME, (S_IFDIR|(MODE)),                                             \
                &proc_##OTYPE##_inode_operations, &proc_##OTYPE##_operations,   \
                {} )
-#define LNK(TYPE, NAME, OTYPE)                                 \
-       NOD(TYPE, NAME, (S_IFLNK|S_IRWXUGO),                    \
+#define LNK(NAME, OTYPE)                                       \
+       NOD(NAME, (S_IFLNK|S_IRWXUGO),                          \
                &proc_pid_link_inode_operations, NULL,          \
                { .proc_get_link = &proc_##OTYPE##_link } )
-#define REG(TYPE, NAME, MODE, OTYPE)                   \
-       NOD(TYPE, NAME, (S_IFREG|(MODE)), NULL,         \
+#define REG(NAME, MODE, OTYPE)                         \
+       NOD(NAME, (S_IFREG|(MODE)), NULL,               \
                &proc_##OTYPE##_operations, {})
-#define INF(TYPE, NAME, MODE, OTYPE)                   \
-       NOD(TYPE, NAME, (S_IFREG|(MODE)),               \
+#define INF(NAME, MODE, OTYPE)                         \
+       NOD(NAME, (S_IFREG|(MODE)),                     \
                NULL, &proc_info_file_operations,       \
                { .proc_read = &proc_##OTYPE } )
 
@@ -1043,7 +939,7 @@ static int task_dumpable(struct task_struct *task)
 }
 
 
-static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *task, int ino)
+static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *task)
 {
        struct inode * inode;
        struct proc_inode *ei;
@@ -1057,7 +953,6 @@ static struct inode *proc_pid_make_inode(struct super_block * sb, struct task_st
        /* Common stuff */
        ei = PROC_I(inode);
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
-       inode->i_ino = fake_ino(task->pid, ino);
        inode->i_op = &proc_def_inode_operations;
 
        /*
@@ -1160,6 +1055,50 @@ static struct dentry_operations pid_dentry_operations =
 
 /* Lookups */
 
+typedef struct dentry *instantiate_t(struct inode *, struct dentry *, struct task_struct *, void *);
+
+static int proc_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
+       char *name, int len,
+       instantiate_t instantiate, struct task_struct *task, void *ptr)
+{
+       struct dentry *child, *dir = filp->f_dentry;
+       struct inode *inode;
+       struct qstr qname;
+       ino_t ino = 0;
+       unsigned type = DT_UNKNOWN;
+
+       qname.name = name;
+       qname.len  = len;
+       qname.hash = full_name_hash(name, len);
+
+       child = d_lookup(dir, &qname);
+       if (!child) {
+               struct dentry *new;
+               new = d_alloc(dir, &qname);
+               if (new) {
+                       child = instantiate(dir->d_inode, new, task, ptr);
+                       if (child)
+                               dput(new);
+                       else
+                               child = new;
+               }
+       }
+       if (!child || IS_ERR(child) || !child->d_inode)
+               goto end_instantiate;
+       inode = child->d_inode;
+       if (inode) {
+               ino = inode->i_ino;
+               type = inode->i_mode >> 12;
+       }
+       dput(child);
+end_instantiate:
+       if (!ino)
+               ino = find_inode_number(dir, &qname);
+       if (!ino)
+               ino = 1;
+       return filldir(dirent, name, len, filp->f_pos, ino, type);
+}
+
 static unsigned name_to_int(struct dentry *dentry)
 {
        const char *name = dentry->d_name.name;
@@ -1264,7 +1203,7 @@ static struct dentry *proc_fd_instantiate(struct inode *dir,
        struct proc_inode *ei;
        struct dentry *error = ERR_PTR(-ENOENT);
 
-       inode = proc_pid_make_inode(dir->i_sb, task, PROC_TID_FD_DIR+fd);
+       inode = proc_pid_make_inode(dir->i_sb, task);
        if (!inode)
                goto out;
        ei = PROC_I(inode);
@@ -1327,6 +1266,15 @@ out_no_task:
        return result;
 }
 
+static int proc_fd_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
+       struct task_struct *task, int fd)
+{
+       char name[PROC_NUMBUF];
+       int len = snprintf(name, sizeof(name), "%d", fd);
+       return proc_fill_cache(filp, dirent, filldir, name, len,
+                               proc_fd_instantiate, task, &fd);
+}
+
 static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
 {
        struct dentry *dentry = filp->f_dentry;
@@ -1334,7 +1282,6 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
        struct task_struct *p = get_proc_task(inode);
        unsigned int fd, tid, ino;
        int retval;
-       char buf[PROC_NUMBUF];
        struct files_struct * files;
        struct fdtable *fdt;
 
@@ -1364,22 +1311,12 @@ static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
                        for (fd = filp->f_pos-2;
                             fd < fdt->max_fds;
                             fd++, filp->f_pos++) {
-                               unsigned int i,j;
 
                                if (!fcheck_files(files, fd))
                                        continue;
                                rcu_read_unlock();
 
-                               j = PROC_NUMBUF;
-                               i = fd;
-                               do {
-                                       j--;
-                                       buf[j] = '0' + (i % 10);
-                                       i /= 10;
-                               } while (i);
-
-                               ino = fake_ino(tid, PROC_TID_FD_DIR + fd);
-                               if (filldir(dirent, buf+j, PROC_NUMBUF-j, fd+2, ino, DT_LNK) < 0) {
+                               if (proc_fd_fill_cache(filp, dirent, filldir, p, fd) < 0) {
                                        rcu_read_lock();
                                        break;
                                }
@@ -1415,7 +1352,7 @@ static struct dentry *proc_pident_instantiate(struct inode *dir,
        struct proc_inode *ei;
        struct dentry *error = ERR_PTR(-EINVAL);
 
-       inode = proc_pid_make_inode(dir->i_sb, task, p->type);
+       inode = proc_pid_make_inode(dir->i_sb, task);
        if (!inode)
                goto out;
 
@@ -1473,6 +1410,13 @@ out_no_task:
        return error;
 }
 
+static int proc_pident_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
+       struct task_struct *task, struct pid_entry *p)
+{
+       return proc_fill_cache(filp, dirent, filldir, p->name, p->len,
+                               proc_pident_instantiate, task, p);
+}
+
 static int proc_pident_readdir(struct file *filp,
                void *dirent, filldir_t filldir,
                struct pid_entry *ents, unsigned int nents)
@@ -1488,11 +1432,10 @@ static int proc_pident_readdir(struct file *filp,
 
        ret = -ENOENT;
        if (!task)
-               goto out;
+               goto out_no_task;
 
        ret = 0;
        pid = task->pid;
-       put_task_struct(task);
        i = filp->f_pos;
        switch (i) {
        case 0:
@@ -1517,8 +1460,7 @@ static int proc_pident_readdir(struct file *filp,
                }
                p = ents + i;
                while (p->name) {
-                       if (filldir(dirent, p->name, p->len, filp->f_pos,
-                                   fake_ino(pid, p->type), p->mode >> 12) < 0)
+                       if (proc_pident_fill_cache(filp, dirent, filldir, task, p) < 0)
                                goto out;
                        filp->f_pos++;
                        p++;
@@ -1527,6 +1469,8 @@ static int proc_pident_readdir(struct file *filp,
 
        ret = 1;
 out:
+       put_task_struct(task);
+out_no_task:
        return ret;
 }
 
@@ -1606,21 +1550,21 @@ static struct file_operations proc_pid_attr_operations = {
 };
 
 static struct pid_entry tgid_attr_stuff[] = {
-       REG(PROC_TGID_ATTR_CURRENT,    "current",    S_IRUGO|S_IWUGO, pid_attr),
-       REG(PROC_TGID_ATTR_PREV,       "prev",       S_IRUGO,         pid_attr),
-       REG(PROC_TGID_ATTR_EXEC,       "exec",       S_IRUGO|S_IWUGO, pid_attr),
-       REG(PROC_TGID_ATTR_FSCREATE,   "fscreate",   S_IRUGO|S_IWUGO, pid_attr),
-       REG(PROC_TGID_ATTR_KEYCREATE,  "keycreate",  S_IRUGO|S_IWUGO, pid_attr),
-       REG(PROC_TGID_ATTR_SOCKCREATE, "sockcreate", S_IRUGO|S_IWUGO, pid_attr),
+       REG("current",    S_IRUGO|S_IWUGO, pid_attr),
+       REG("prev",       S_IRUGO,         pid_attr),
+       REG("exec",       S_IRUGO|S_IWUGO, pid_attr),
+       REG("fscreate",   S_IRUGO|S_IWUGO, pid_attr),
+       REG("keycreate",  S_IRUGO|S_IWUGO, pid_attr),
+       REG("sockcreate", S_IRUGO|S_IWUGO, pid_attr),
        {}
 };
 static struct pid_entry tid_attr_stuff[] = {
-       REG(PROC_TID_ATTR_CURRENT,    "current",    S_IRUGO|S_IWUGO, pid_attr),
-       REG(PROC_TID_ATTR_PREV,       "prev",       S_IRUGO,         pid_attr),
-       REG(PROC_TID_ATTR_EXEC,       "exec",       S_IRUGO|S_IWUGO, pid_attr),
-       REG(PROC_TID_ATTR_FSCREATE,   "fscreate",   S_IRUGO|S_IWUGO, pid_attr),
-       REG(PROC_TID_ATTR_KEYCREATE,  "keycreate",  S_IRUGO|S_IWUGO, pid_attr),
-       REG(PROC_TID_ATTR_SOCKCREATE, "sockcreate", S_IRUGO|S_IWUGO, pid_attr),
+       REG("current",    S_IRUGO|S_IWUGO, pid_attr),
+       REG("prev",       S_IRUGO,         pid_attr),
+       REG("exec",       S_IRUGO|S_IWUGO, pid_attr),
+       REG("fscreate",   S_IRUGO|S_IWUGO, pid_attr),
+       REG("keycreate",  S_IRUGO|S_IWUGO, pid_attr),
+       REG("sockcreate", S_IRUGO|S_IWUGO, pid_attr),
        {}
 };
 
@@ -1704,7 +1648,7 @@ static struct inode_operations proc_self_inode_operations = {
  * describe something that is process related.
  */
 static struct pid_entry proc_base_stuff[] = {
-       NOD(PROC_TGID_INO,      "self", S_IFLNK|S_IRWXUGO,
+       NOD("self", S_IFLNK|S_IRWXUGO,
                &proc_self_inode_operations, NULL, {}),
        {}
 };
@@ -1749,7 +1693,6 @@ static struct dentry *proc_base_instantiate(struct inode *dir,
        /* Initialize the inode */
        ei = PROC_I(inode);
        inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
-       inode->i_ino = fake_ino(0, p->type);
 
        /*
         * grab the reference to the task.
@@ -1809,6 +1752,13 @@ out_no_task:
        return error;
 }
 
+static int proc_base_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
+       struct task_struct *task, struct pid_entry *p)
+{
+       return proc_fill_cache(filp, dirent, filldir, p->name, p->len,
+                               proc_base_instantiate, task, p);
+}
+
 /*
  * Thread groups
  */
@@ -1816,46 +1766,46 @@ static struct file_operations proc_task_operations;
 static struct inode_operations proc_task_inode_operations;
 
 static struct pid_entry tgid_base_stuff[] = {
-       DIR(PROC_TGID_TASK,       "task",       S_IRUGO|S_IXUGO, task),
-       DIR(PROC_TGID_FD,         "fd",         S_IRUSR|S_IXUSR, fd),
-       INF(PROC_TGID_ENVIRON,    "environ",    S_IRUSR, pid_environ),
-       INF(PROC_TGID_AUXV,       "auxv",       S_IRUSR, pid_auxv),
-       INF(PROC_TGID_STATUS,     "status",     S_IRUGO, pid_status),
-       INF(PROC_TGID_CMDLINE,    "cmdline",    S_IRUGO, pid_cmdline),
-       INF(PROC_TGID_STAT,       "stat",       S_IRUGO, tgid_stat),
-       INF(PROC_TGID_STATM,      "statm",      S_IRUGO, pid_statm),
-       REG(PROC_TGID_MAPS,       "maps",       S_IRUGO, maps),
+       DIR("task",       S_IRUGO|S_IXUGO, task),
+       DIR("fd",         S_IRUSR|S_IXUSR, fd),
+       INF("environ",    S_IRUSR, pid_environ),
+       INF("auxv",       S_IRUSR, pid_auxv),
+       INF("status",     S_IRUGO, pid_status),
+       INF("cmdline",    S_IRUGO, pid_cmdline),
+       INF("stat",       S_IRUGO, tgid_stat),
+       INF("statm",      S_IRUGO, pid_statm),
+       REG("maps",       S_IRUGO, maps),
 #ifdef CONFIG_NUMA
-       REG(PROC_TGID_NUMA_MAPS,  "numa_maps",  S_IRUGO, numa_maps),
+       REG("numa_maps",  S_IRUGO, numa_maps),
 #endif
-       REG(PROC_TGID_MEM,        "mem",        S_IRUSR|S_IWUSR, mem),
+       REG("mem",        S_IRUSR|S_IWUSR, mem),
 #ifdef CONFIG_SECCOMP
-       REG(PROC_TGID_SECCOMP,    "seccomp",    S_IRUSR|S_IWUSR, seccomp),
+       REG("seccomp",    S_IRUSR|S_IWUSR, seccomp),
 #endif
-       LNK(PROC_TGID_CWD,        "cwd",        cwd),
-       LNK(PROC_TGID_ROOT,       "root",       root),
-       LNK(PROC_TGID_EXE,        "exe",        exe),
-       REG(PROC_TGID_MOUNTS,     "mounts",     S_IRUGO, mounts),
-       REG(PROC_TGID_MOUNTSTATS, "mountstats", S_IRUSR, mountstats),
+       LNK("cwd",        cwd),
+       LNK("root",       root),
+       LNK("exe",        exe),
+       REG("mounts",     S_IRUGO, mounts),
+       REG("mountstats", S_IRUSR, mountstats),
 #ifdef CONFIG_MMU
-       REG(PROC_TGID_SMAPS,      "smaps",      S_IRUGO, smaps),
+       REG("smaps",      S_IRUGO, smaps),
 #endif
 #ifdef CONFIG_SECURITY
-       DIR(PROC_TGID_ATTR,       "attr",       S_IRUGO|S_IXUGO, tgid_attr),
+       DIR("attr",       S_IRUGO|S_IXUGO, tgid_attr),
 #endif
 #ifdef CONFIG_KALLSYMS
-       INF(PROC_TGID_WCHAN,      "wchan",      S_IRUGO, pid_wchan),
+       INF("wchan",      S_IRUGO, pid_wchan),
 #endif
 #ifdef CONFIG_SCHEDSTATS
-       INF(PROC_TGID_SCHEDSTAT,  "schedstat",  S_IRUGO, pid_schedstat),
+       INF("schedstat",  S_IRUGO, pid_schedstat),
 #endif
 #ifdef CONFIG_CPUSETS
-       REG(PROC_TGID_CPUSET,     "cpuset",     S_IRUGO, cpuset),
+       REG("cpuset",     S_IRUGO, cpuset),
 #endif
-       INF(PROC_TGID_OOM_SCORE,  "oom_score",  S_IRUGO, oom_score),
-       REG(PROC_TGID_OOM_ADJUST, "oom_adj",    S_IRUGO|S_IWUSR, oom_adjust),
+       INF("oom_score",  S_IRUGO, oom_score),
+       REG("oom_adj",    S_IRUGO|S_IWUSR, oom_adjust),
 #ifdef CONFIG_AUDITSYSCALL
-       REG(PROC_TGID_LOGINUID,   "loginuid",   S_IWUSR|S_IRUGO, loginuid),
+       REG("loginuid",   S_IWUSR|S_IRUGO, loginuid),
 #endif
        {}
 };
@@ -1955,7 +1905,7 @@ struct dentry *proc_pid_instantiate(struct inode *dir,
        struct dentry *error = ERR_PTR(-ENOENT);
        struct inode *inode;
 
-       inode = proc_pid_make_inode(dir->i_sb, task, PROC_TGID_INO);
+       inode = proc_pid_make_inode(dir->i_sb, task);
        if (!inode)
                goto out;
 
@@ -2045,18 +1995,29 @@ retry:
 
 #define TGID_OFFSET (FIRST_PROCESS_ENTRY + (1 /* /proc/self */))
 
+static int proc_pid_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
+       struct task_struct *task, int tgid)
+{
+       char name[PROC_NUMBUF];
+       int len = snprintf(name, sizeof(name), "%d", tgid);
+       return proc_fill_cache(filp, dirent, filldir, name, len,
+                               proc_pid_instantiate, task, NULL);
+}
+
 /* for the /proc/ directory itself, after non-process stuff has been done */
 int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
 {
-       char buf[PROC_NUMBUF];
        unsigned int nr = filp->f_pos - FIRST_PROCESS_ENTRY;
+       struct task_struct *reaper = get_proc_task(filp->f_dentry->d_inode);
        struct task_struct *task;
        int tgid;
 
+       if (!reaper)
+               goto out_no_task;
+
        for (; nr < (ARRAY_SIZE(proc_base_stuff) - 1); filp->f_pos++, nr++) {
                struct pid_entry *p = &proc_base_stuff[nr];
-               if (filldir(dirent, p->name, p->len, filp->f_pos,
-                           fake_ino(0, p->type), p->mode >> 12) < 0)
+               if (proc_base_fill_cache(filp, dirent, filldir, reaper, p) < 0)
                        goto out;
        }
 
@@ -2064,19 +2025,17 @@ int proc_pid_readdir(struct file * filp, void * dirent, filldir_t filldir)
        for (task = next_tgid(tgid);
             task;
             put_task_struct(task), task = next_tgid(tgid + 1)) {
-               int len;
-               ino_t ino;
                tgid = task->pid;
                filp->f_pos = tgid + TGID_OFFSET;
-               len = snprintf(buf, sizeof(buf), "%d", tgid);
-               ino = fake_ino(tgid, PROC_TGID_INO);
-               if (filldir(dirent, buf, len, filp->f_pos, ino, DT_DIR) < 0) {
+               if (proc_pid_fill_cache(filp, dirent, filldir, task, tgid) < 0) {
                        put_task_struct(task);
                        goto out;
                }
        }
        filp->f_pos = PID_MAX_LIMIT + TGID_OFFSET;
 out:
+       put_task_struct(reaper);
+out_no_task:
        return 0;
 }
 
@@ -2084,44 +2043,44 @@ out:
  * Tasks
  */
 static struct pid_entry tid_base_stuff[] = {
-       DIR(PROC_TID_FD,         "fd",        S_IRUSR|S_IXUSR, fd),
-       INF(PROC_TID_ENVIRON,    "environ",   S_IRUSR, pid_environ),
-       INF(PROC_TID_AUXV,       "auxv",      S_IRUSR, pid_auxv),
-       INF(PROC_TID_STATUS,     "status",    S_IRUGO, pid_status),
-       INF(PROC_TID_CMDLINE,    "cmdline",   S_IRUGO, pid_cmdline),
-       INF(PROC_TID_STAT,       "stat",      S_IRUGO, tid_stat),
-       INF(PROC_TID_STATM,      "statm",     S_IRUGO, pid_statm),
-       REG(PROC_TID_MAPS,       "maps",      S_IRUGO, maps),
+       DIR("fd",        S_IRUSR|S_IXUSR, fd),
+       INF("environ",   S_IRUSR, pid_environ),
+       INF("auxv",      S_IRUSR, pid_auxv),
+       INF("status",    S_IRUGO, pid_status),
+       INF("cmdline",   S_IRUGO, pid_cmdline),
+       INF("stat",      S_IRUGO, tid_stat),
+       INF("statm",     S_IRUGO, pid_statm),
+       REG("maps",      S_IRUGO, maps),
 #ifdef CONFIG_NUMA
-       REG(PROC_TID_NUMA_MAPS,  "numa_maps", S_IRUGO, numa_maps),
+       REG("numa_maps", S_IRUGO, numa_maps),
 #endif
-       REG(PROC_TID_MEM,        "mem",       S_IRUSR|S_IWUSR, mem),
+       REG("mem",       S_IRUSR|S_IWUSR, mem),
 #ifdef CONFIG_SECCOMP
-       REG(PROC_TID_SECCOMP,    "seccomp",   S_IRUSR|S_IWUSR, seccomp),
+       REG("seccomp",   S_IRUSR|S_IWUSR, seccomp),
 #endif
-       LNK(PROC_TID_CWD,        "cwd",       cwd),
-       LNK(PROC_TID_ROOT,       "root",      root),
-       LNK(PROC_TID_EXE,        "exe",       exe),
-       REG(PROC_TID_MOUNTS,     "mounts",    S_IRUGO, mounts),
+       LNK("cwd",       cwd),
+       LNK("root",      root),
+       LNK("exe",       exe),
+       REG("mounts",    S_IRUGO, mounts),
 #ifdef CONFIG_MMU
-       REG(PROC_TID_SMAPS,      "smaps",     S_IRUGO, smaps),
+       REG("smaps",     S_IRUGO, smaps),
 #endif
 #ifdef CONFIG_SECURITY
-       DIR(PROC_TID_ATTR,       "attr",      S_IRUGO|S_IXUGO, tid_attr),
+       DIR("attr",      S_IRUGO|S_IXUGO, tid_attr),
 #endif
 #ifdef CONFIG_KALLSYMS
-       INF(PROC_TID_WCHAN,      "wchan",     S_IRUGO, pid_wchan),
+       INF("wchan",     S_IRUGO, pid_wchan),
 #endif
 #ifdef CONFIG_SCHEDSTATS
-       INF(PROC_TID_SCHEDSTAT,  "schedstat", S_IRUGO, pid_schedstat),
+       INF("schedstat", S_IRUGO, pid_schedstat),
 #endif
 #ifdef CONFIG_CPUSETS
-       REG(PROC_TID_CPUSET,     "cpuset",    S_IRUGO, cpuset),
+       REG("cpuset",    S_IRUGO, cpuset),
 #endif
-       INF(PROC_TID_OOM_SCORE,  "oom_score", S_IRUGO, oom_score),
-       REG(PROC_TID_OOM_ADJUST, "oom_adj",   S_IRUGO|S_IWUSR, oom_adjust),
+       INF("oom_score", S_IRUGO, oom_score),
+       REG("oom_adj",   S_IRUGO|S_IWUSR, oom_adjust),
 #ifdef CONFIG_AUDITSYSCALL
-       REG(PROC_TID_LOGINUID,   "loginuid",  S_IWUSR|S_IRUGO, loginuid),
+       REG("loginuid",  S_IWUSR|S_IRUGO, loginuid),
 #endif
        {}
 };
@@ -2153,7 +2112,7 @@ static struct dentry *proc_task_instantiate(struct inode *dir,
 {
        struct dentry *error = ERR_PTR(-ENOENT);
        struct inode *inode;
-       inode = proc_pid_make_inode(dir->i_sb, task, PROC_TID_INO);
+       inode = proc_pid_make_inode(dir->i_sb, task);
 
        if (!inode)
                goto out;
@@ -2279,10 +2238,18 @@ static struct task_struct *next_tid(struct task_struct *start)
        return pos;
 }
 
+static int proc_task_fill_cache(struct file *filp, void *dirent, filldir_t filldir,
+       struct task_struct *task, int tid)
+{
+       char name[PROC_NUMBUF];
+       int len = snprintf(name, sizeof(name), "%d", tid);
+       return proc_fill_cache(filp, dirent, filldir, name, len,
+                               proc_task_instantiate, task, NULL);
+}
+
 /* for the /proc/TGID/task/ directories */
 static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldir)
 {
-       char buf[PROC_NUMBUF];
        struct dentry *dentry = filp->f_dentry;
        struct inode *inode = dentry->d_inode;
        struct task_struct *leader = get_proc_task(inode);
@@ -2319,11 +2286,8 @@ static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldi
        for (task = first_tid(leader, tid, pos - 2);
             task;
             task = next_tid(task), pos++) {
-               int len;
                tid = task->pid;
-               len = snprintf(buf, sizeof(buf), "%d", tid);
-               ino = fake_ino(tid, PROC_TID_INO);
-               if (filldir(dirent, buf, len, pos, ino, DT_DIR < 0)) {
+               if (proc_task_fill_cache(filp, dirent, filldir, task, tid) < 0) {
                        /* returning this tgid failed, save it as the first
                         * pid for the next readir call */
                        filp->f_version = tid;