* [PATCH 1/7] proc: Reorder the functions in base.c
2006-08-15 18:00 The rest of my proc cleanup Eric W. Biederman
@ 2006-08-15 18:05 ` Eric W. Biederman
2006-08-15 18:05 ` [PATCH 2/7] proc: Modify proc_pident_lookup to be completely table driven Eric W. Biederman
` (6 subsequent siblings)
7 siblings, 0 replies; 18+ messages in thread
From: Eric W. Biederman @ 2006-08-15 18:05 UTC (permalink / raw)
To: Andrew Morton
Cc: linux-kernel, containers, Eric W. Biederman, Eric W. Biederman
From: Eric W. Biederman <ebiederm@xmisison.com>
Group the functions by what they implement instead of
by type of operation. As it existed base.c was quickly approaching
the point where it could not be followed.
No functionality or code changes asside from adding/removing
forward declartions are implemented in this patch.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
fs/proc/base.c | 994 ++++++++++++++++++++++++++++----------------------------
1 files changed, 499 insertions(+), 495 deletions(-)
diff --git a/fs/proc/base.c b/fs/proc/base.c
index fbc03b5..605ae9c 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -199,147 +199,6 @@ struct pid_entry {
#define E(type,name,mode) {(type),sizeof(name)-1,(name),(mode)}
-static struct pid_entry tgid_base_stuff[] = {
- E(PROC_TGID_TASK, "task", S_IFDIR|S_IRUGO|S_IXUGO),
- E(PROC_TGID_FD, "fd", S_IFDIR|S_IRUSR|S_IXUSR),
- E(PROC_TGID_ENVIRON, "environ", S_IFREG|S_IRUSR),
- E(PROC_TGID_AUXV, "auxv", S_IFREG|S_IRUSR),
- E(PROC_TGID_STATUS, "status", S_IFREG|S_IRUGO),
- E(PROC_TGID_CMDLINE, "cmdline", S_IFREG|S_IRUGO),
- E(PROC_TGID_STAT, "stat", S_IFREG|S_IRUGO),
- E(PROC_TGID_STATM, "statm", S_IFREG|S_IRUGO),
- E(PROC_TGID_MAPS, "maps", S_IFREG|S_IRUGO),
-#ifdef CONFIG_NUMA
- E(PROC_TGID_NUMA_MAPS, "numa_maps", S_IFREG|S_IRUGO),
-#endif
- E(PROC_TGID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR),
-#ifdef CONFIG_SECCOMP
- E(PROC_TGID_SECCOMP, "seccomp", S_IFREG|S_IRUSR|S_IWUSR),
-#endif
- 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_MOUNTS, "mounts", S_IFREG|S_IRUGO),
- E(PROC_TGID_MOUNTSTATS, "mountstats", S_IFREG|S_IRUSR),
-#ifdef CONFIG_MMU
- E(PROC_TGID_SMAPS, "smaps", S_IFREG|S_IRUGO),
-#endif
-#ifdef CONFIG_SECURITY
- E(PROC_TGID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO),
-#endif
-#ifdef CONFIG_KALLSYMS
- E(PROC_TGID_WCHAN, "wchan", S_IFREG|S_IRUGO),
-#endif
-#ifdef CONFIG_SCHEDSTATS
- E(PROC_TGID_SCHEDSTAT, "schedstat", S_IFREG|S_IRUGO),
-#endif
-#ifdef CONFIG_CPUSETS
- E(PROC_TGID_CPUSET, "cpuset", S_IFREG|S_IRUGO),
-#endif
- E(PROC_TGID_OOM_SCORE, "oom_score",S_IFREG|S_IRUGO),
- E(PROC_TGID_OOM_ADJUST,"oom_adj", S_IFREG|S_IRUGO|S_IWUSR),
-#ifdef CONFIG_AUDITSYSCALL
- E(PROC_TGID_LOGINUID, "loginuid", S_IFREG|S_IWUSR|S_IRUGO),
-#endif
- {0,0,NULL,0}
-};
-static struct pid_entry tid_base_stuff[] = {
- E(PROC_TID_FD, "fd", S_IFDIR|S_IRUSR|S_IXUSR),
- E(PROC_TID_ENVIRON, "environ", S_IFREG|S_IRUSR),
- E(PROC_TID_AUXV, "auxv", S_IFREG|S_IRUSR),
- E(PROC_TID_STATUS, "status", S_IFREG|S_IRUGO),
- E(PROC_TID_CMDLINE, "cmdline", S_IFREG|S_IRUGO),
- E(PROC_TID_STAT, "stat", S_IFREG|S_IRUGO),
- E(PROC_TID_STATM, "statm", S_IFREG|S_IRUGO),
- E(PROC_TID_MAPS, "maps", S_IFREG|S_IRUGO),
-#ifdef CONFIG_NUMA
- E(PROC_TID_NUMA_MAPS, "numa_maps", S_IFREG|S_IRUGO),
-#endif
- E(PROC_TID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR),
-#ifdef CONFIG_SECCOMP
- E(PROC_TID_SECCOMP, "seccomp", S_IFREG|S_IRUSR|S_IWUSR),
-#endif
- 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_MOUNTS, "mounts", S_IFREG|S_IRUGO),
-#ifdef CONFIG_MMU
- E(PROC_TID_SMAPS, "smaps", S_IFREG|S_IRUGO),
-#endif
-#ifdef CONFIG_SECURITY
- E(PROC_TID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO),
-#endif
-#ifdef CONFIG_KALLSYMS
- E(PROC_TID_WCHAN, "wchan", S_IFREG|S_IRUGO),
-#endif
-#ifdef CONFIG_SCHEDSTATS
- E(PROC_TID_SCHEDSTAT, "schedstat",S_IFREG|S_IRUGO),
-#endif
-#ifdef CONFIG_CPUSETS
- E(PROC_TID_CPUSET, "cpuset", S_IFREG|S_IRUGO),
-#endif
- E(PROC_TID_OOM_SCORE, "oom_score",S_IFREG|S_IRUGO),
- E(PROC_TID_OOM_ADJUST, "oom_adj", S_IFREG|S_IRUGO|S_IWUSR),
-#ifdef CONFIG_AUDITSYSCALL
- E(PROC_TID_LOGINUID, "loginuid", S_IFREG|S_IWUSR|S_IRUGO),
-#endif
- {0,0,NULL,0}
-};
-
-#ifdef CONFIG_SECURITY
-static struct pid_entry tgid_attr_stuff[] = {
- E(PROC_TGID_ATTR_CURRENT, "current", S_IFREG|S_IRUGO|S_IWUGO),
- E(PROC_TGID_ATTR_PREV, "prev", S_IFREG|S_IRUGO),
- E(PROC_TGID_ATTR_EXEC, "exec", S_IFREG|S_IRUGO|S_IWUGO),
- E(PROC_TGID_ATTR_FSCREATE, "fscreate", S_IFREG|S_IRUGO|S_IWUGO),
- E(PROC_TGID_ATTR_KEYCREATE, "keycreate", S_IFREG|S_IRUGO|S_IWUGO),
- E(PROC_TGID_ATTR_SOCKCREATE, "sockcreate", S_IFREG|S_IRUGO|S_IWUGO),
- {0,0,NULL,0}
-};
-static struct pid_entry tid_attr_stuff[] = {
- E(PROC_TID_ATTR_CURRENT, "current", S_IFREG|S_IRUGO|S_IWUGO),
- E(PROC_TID_ATTR_PREV, "prev", S_IFREG|S_IRUGO),
- E(PROC_TID_ATTR_EXEC, "exec", S_IFREG|S_IRUGO|S_IWUGO),
- E(PROC_TID_ATTR_FSCREATE, "fscreate", S_IFREG|S_IRUGO|S_IWUGO),
- E(PROC_TID_ATTR_KEYCREATE, "keycreate", S_IFREG|S_IRUGO|S_IWUGO),
- E(PROC_TID_ATTR_SOCKCREATE, "sockcreate", S_IFREG|S_IRUGO|S_IWUGO),
- {0,0,NULL,0}
-};
-#endif
-
-#undef E
-
-static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
-{
- struct task_struct *task = get_proc_task(inode);
- struct files_struct *files = NULL;
- struct file *file;
- int fd = proc_fd(inode);
-
- if (task) {
- files = get_files_struct(task);
- put_task_struct(task);
- }
- if (files) {
- /*
- * We are not taking a ref to the file structure, so we must
- * hold ->file_lock.
- */
- spin_lock(&files->file_lock);
- file = fcheck_files(files, fd);
- if (file) {
- *mnt = mntget(file->f_vfsmnt);
- *dentry = dget(file->f_dentry);
- spin_unlock(&files->file_lock);
- put_files_struct(files);
- return 0;
- }
- spin_unlock(&files->file_lock);
- put_files_struct(files);
- }
- return -ENOENT;
-}
-
static struct fs_struct *get_fs_struct(struct task_struct *task)
{
struct fs_struct *fs;
@@ -1137,143 +996,6 @@ static struct inode_operations proc_pid_
.setattr = proc_setattr,
};
-static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
-{
- struct dentry *dentry = filp->f_dentry;
- struct inode *inode = dentry->d_inode;
- 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;
-
- retval = -ENOENT;
- if (!p)
- goto out_no_task;
- retval = 0;
- tid = p->pid;
-
- fd = filp->f_pos;
- switch (fd) {
- case 0:
- if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0)
- goto out;
- filp->f_pos++;
- case 1:
- ino = parent_ino(dentry);
- if (filldir(dirent, "..", 2, 1, ino, DT_DIR) < 0)
- goto out;
- filp->f_pos++;
- default:
- files = get_files_struct(p);
- if (!files)
- goto out;
- rcu_read_lock();
- fdt = files_fdtable(files);
- 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) {
- rcu_read_lock();
- break;
- }
- rcu_read_lock();
- }
- rcu_read_unlock();
- put_files_struct(files);
- }
-out:
- put_task_struct(p);
-out_no_task:
- return retval;
-}
-
-static int proc_pident_readdir(struct file *filp,
- void *dirent, filldir_t filldir,
- struct pid_entry *ents, unsigned int nents)
-{
- int i;
- int pid;
- struct dentry *dentry = filp->f_dentry;
- struct inode *inode = dentry->d_inode;
- struct task_struct *task = get_proc_task(inode);
- struct pid_entry *p;
- ino_t ino;
- int ret;
-
- ret = -ENOENT;
- if (!task)
- goto out;
-
- ret = 0;
- pid = task->pid;
- put_task_struct(task);
- i = filp->f_pos;
- switch (i) {
- case 0:
- ino = inode->i_ino;
- if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0)
- goto out;
- i++;
- filp->f_pos++;
- /* fall through */
- case 1:
- ino = parent_ino(dentry);
- if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0)
- goto out;
- i++;
- filp->f_pos++;
- /* fall through */
- default:
- i -= 2;
- if (i >= nents) {
- ret = 1;
- goto out;
- }
- 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)
- goto out;
- filp->f_pos++;
- p++;
- }
- }
-
- ret = 1;
-out:
- return ret;
-}
-
-static int proc_tgid_base_readdir(struct file * filp,
- void * dirent, filldir_t filldir)
-{
- return proc_pident_readdir(filp,dirent,filldir,
- tgid_base_stuff,ARRAY_SIZE(tgid_base_stuff));
-}
-
-static int proc_tid_base_readdir(struct file * filp,
- void * dirent, filldir_t filldir)
-{
- return proc_pident_readdir(filp,dirent,filldir,
- tid_base_stuff,ARRAY_SIZE(tid_base_stuff));
-}
/* building an inode */
@@ -1333,6 +1055,27 @@ out_unlock:
return NULL;
}
+static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+{
+ struct inode *inode = dentry->d_inode;
+ struct task_struct *task;
+ generic_fillattr(inode, stat);
+
+ rcu_read_lock();
+ stat->uid = 0;
+ stat->gid = 0;
+ task = pid_task(proc_pid(inode), PIDTYPE_PID);
+ if (task) {
+ if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
+ task_dumpable(task)) {
+ stat->uid = task->euid;
+ stat->gid = task->egid;
+ }
+ }
+ rcu_read_unlock();
+ return 0;
+}
+
/* dentry stuff */
/*
@@ -1372,25 +1115,74 @@ static int pid_revalidate(struct dentry
return 0;
}
-static int pid_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+static int pid_delete_dentry(struct dentry * dentry)
{
- struct inode *inode = dentry->d_inode;
- struct task_struct *task;
- generic_fillattr(inode, stat);
+ /* Is the task we represent dead?
+ * If so, then don't put the dentry on the lru list,
+ * kill it immediately.
+ */
+ return !proc_pid(dentry->d_inode)->tasks[PIDTYPE_PID].first;
+}
+
+static struct dentry_operations pid_dentry_operations =
+{
+ .d_revalidate = pid_revalidate,
+ .d_delete = pid_delete_dentry,
+};
+
+/* Lookups */
+
+static unsigned name_to_int(struct dentry *dentry)
+{
+ const char *name = dentry->d_name.name;
+ int len = dentry->d_name.len;
+ unsigned n = 0;
+
+ if (len > 1 && *name == '0')
+ goto out;
+ while (len-- > 0) {
+ unsigned c = *name++ - '0';
+ if (c > 9)
+ goto out;
+ if (n >= (~0U-9)/10)
+ goto out;
+ n *= 10;
+ n += c;
+ }
+ return n;
+out:
+ return ~0U;
+}
+
+static int proc_fd_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt)
+{
+ struct task_struct *task = get_proc_task(inode);
+ struct files_struct *files = NULL;
+ struct file *file;
+ int fd = proc_fd(inode);
- rcu_read_lock();
- stat->uid = 0;
- stat->gid = 0;
- task = pid_task(proc_pid(inode), PIDTYPE_PID);
if (task) {
- if ((inode->i_mode == (S_IFDIR|S_IRUGO|S_IXUGO)) ||
- task_dumpable(task)) {
- stat->uid = task->euid;
- stat->gid = task->egid;
+ files = get_files_struct(task);
+ put_task_struct(task);
+ }
+ if (files) {
+ /*
+ * We are not taking a ref to the file structure, so we must
+ * hold ->file_lock.
+ */
+ spin_lock(&files->file_lock);
+ file = fcheck_files(files, fd);
+ if (file) {
+ *mnt = mntget(file->f_vfsmnt);
+ *dentry = dget(file->f_dentry);
+ spin_unlock(&files->file_lock);
+ put_files_struct(files);
+ return 0;
}
+ spin_unlock(&files->file_lock);
+ put_files_struct(files);
}
- rcu_read_unlock();
- return 0;
+ return -ENOENT;
}
static int tid_fd_revalidate(struct dentry *dentry, struct nameidata *nd)
@@ -1428,51 +1220,12 @@ static int tid_fd_revalidate(struct dent
return 0;
}
-static int pid_delete_dentry(struct dentry * dentry)
-{
- /* Is the task we represent dead?
- * If so, then don't put the dentry on the lru list,
- * kill it immediately.
- */
- return !proc_pid(dentry->d_inode)->tasks[PIDTYPE_PID].first;
-}
-
static struct dentry_operations tid_fd_dentry_operations =
{
.d_revalidate = tid_fd_revalidate,
.d_delete = pid_delete_dentry,
};
-static struct dentry_operations pid_dentry_operations =
-{
- .d_revalidate = pid_revalidate,
- .d_delete = pid_delete_dentry,
-};
-
-/* Lookups */
-
-static unsigned name_to_int(struct dentry *dentry)
-{
- const char *name = dentry->d_name.name;
- int len = dentry->d_name.len;
- unsigned n = 0;
-
- if (len > 1 && *name == '0')
- goto out;
- while (len-- > 0) {
- unsigned c = *name++ - '0';
- if (c > 9)
- goto out;
- if (n >= (~0U-9)/10)
- goto out;
- n *= 10;
- n += c;
- }
- return n;
-out:
- return ~0U;
-}
-
/* SMP-safe */
static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
{
@@ -1534,20 +1287,78 @@ out_unlock:
goto out;
}
-static int proc_task_readdir(struct file * filp, void * dirent, filldir_t filldir);
-static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd);
-static int proc_task_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat);
+static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
+{
+ struct dentry *dentry = filp->f_dentry;
+ struct inode *inode = dentry->d_inode;
+ 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;
+
+ retval = -ENOENT;
+ if (!p)
+ goto out_no_task;
+ retval = 0;
+ tid = p->pid;
+
+ fd = filp->f_pos;
+ switch (fd) {
+ case 0:
+ if (filldir(dirent, ".", 1, 0, inode->i_ino, DT_DIR) < 0)
+ goto out;
+ filp->f_pos++;
+ case 1:
+ ino = parent_ino(dentry);
+ if (filldir(dirent, "..", 2, 1, ino, DT_DIR) < 0)
+ goto out;
+ filp->f_pos++;
+ default:
+ files = get_files_struct(p);
+ if (!files)
+ goto out;
+ rcu_read_lock();
+ fdt = files_fdtable(files);
+ 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) {
+ rcu_read_lock();
+ break;
+ }
+ rcu_read_lock();
+ }
+ rcu_read_unlock();
+ put_files_struct(files);
+ }
+out:
+ put_task_struct(p);
+out_no_task:
+ return retval;
+}
static struct file_operations proc_fd_operations = {
.read = generic_read_dir,
.readdir = proc_readfd,
};
-static struct file_operations proc_task_operations = {
- .read = generic_read_dir,
- .readdir = proc_task_readdir,
-};
-
/*
* proc directories can do almost nothing..
*/
@@ -1556,87 +1367,11 @@ static struct inode_operations proc_fd_i
.setattr = proc_setattr,
};
-static struct inode_operations proc_task_inode_operations = {
- .lookup = proc_task_lookup,
- .getattr = proc_task_getattr,
- .setattr = proc_setattr,
-};
+static struct file_operations proc_task_operations;
+static struct inode_operations proc_task_inode_operations;
#ifdef CONFIG_SECURITY
-static ssize_t proc_pid_attr_read(struct file * file, char __user * buf,
- size_t count, loff_t *ppos)
-{
- struct inode * inode = file->f_dentry->d_inode;
- unsigned long page;
- ssize_t length;
- struct task_struct *task = get_proc_task(inode);
-
- length = -ESRCH;
- if (!task)
- goto out_no_task;
-
- if (count > PAGE_SIZE)
- count = PAGE_SIZE;
- length = -ENOMEM;
- if (!(page = __get_free_page(GFP_KERNEL)))
- goto out;
-
- length = security_getprocattr(task,
- (char*)file->f_dentry->d_name.name,
- (void*)page, count);
- if (length >= 0)
- length = simple_read_from_buffer(buf, count, ppos, (char *)page, length);
- free_page(page);
-out:
- put_task_struct(task);
-out_no_task:
- return length;
-}
-
-static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
- size_t count, loff_t *ppos)
-{
- struct inode * inode = file->f_dentry->d_inode;
- char *page;
- ssize_t length;
- struct task_struct *task = get_proc_task(inode);
-
- length = -ESRCH;
- if (!task)
- goto out_no_task;
- if (count > PAGE_SIZE)
- count = PAGE_SIZE;
-
- /* No partial writes. */
- length = -EINVAL;
- if (*ppos != 0)
- goto out;
-
- length = -ENOMEM;
- page = (char*)__get_free_page(GFP_USER);
- if (!page)
- goto out;
-
- length = -EFAULT;
- if (copy_from_user(page, buf, count))
- goto out_free;
-
- length = security_setprocattr(task,
- (char*)file->f_dentry->d_name.name,
- (void*)page, count);
-out_free:
- free_page((unsigned long) page);
-out:
- put_task_struct(task);
-out_no_task:
- return length;
-}
-
-static struct file_operations proc_pid_attr_operations = {
- .read = proc_pid_attr_read,
- .write = proc_pid_attr_write,
-};
-
+static struct file_operations proc_pid_attr_operations;
static struct file_operations proc_tid_attr_operations;
static struct inode_operations proc_tid_attr_inode_operations;
static struct file_operations proc_tgid_attr_operations;
@@ -1852,37 +1587,157 @@ out_no_task:
return error;
}
-static struct dentry *proc_tgid_base_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){
- return proc_pident_lookup(dir, dentry, tgid_base_stuff);
+static int proc_pident_readdir(struct file *filp,
+ void *dirent, filldir_t filldir,
+ struct pid_entry *ents, unsigned int nents)
+{
+ int i;
+ int pid;
+ struct dentry *dentry = filp->f_dentry;
+ struct inode *inode = dentry->d_inode;
+ struct task_struct *task = get_proc_task(inode);
+ struct pid_entry *p;
+ ino_t ino;
+ int ret;
+
+ ret = -ENOENT;
+ if (!task)
+ goto out;
+
+ ret = 0;
+ pid = task->pid;
+ put_task_struct(task);
+ i = filp->f_pos;
+ switch (i) {
+ case 0:
+ ino = inode->i_ino;
+ if (filldir(dirent, ".", 1, i, ino, DT_DIR) < 0)
+ goto out;
+ i++;
+ filp->f_pos++;
+ /* fall through */
+ case 1:
+ ino = parent_ino(dentry);
+ if (filldir(dirent, "..", 2, i, ino, DT_DIR) < 0)
+ goto out;
+ i++;
+ filp->f_pos++;
+ /* fall through */
+ default:
+ i -= 2;
+ if (i >= nents) {
+ ret = 1;
+ goto out;
+ }
+ 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)
+ goto out;
+ filp->f_pos++;
+ p++;
+ }
+ }
+
+ ret = 1;
+out:
+ return ret;
}
-static struct dentry *proc_tid_base_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){
- return proc_pident_lookup(dir, dentry, tid_base_stuff);
+#ifdef CONFIG_SECURITY
+static ssize_t proc_pid_attr_read(struct file * file, char __user * buf,
+ size_t count, loff_t *ppos)
+{
+ struct inode * inode = file->f_dentry->d_inode;
+ unsigned long page;
+ ssize_t length;
+ struct task_struct *task = get_proc_task(inode);
+
+ length = -ESRCH;
+ if (!task)
+ goto out_no_task;
+
+ if (count > PAGE_SIZE)
+ count = PAGE_SIZE;
+ length = -ENOMEM;
+ if (!(page = __get_free_page(GFP_KERNEL)))
+ goto out;
+
+ length = security_getprocattr(task,
+ (char*)file->f_dentry->d_name.name,
+ (void*)page, count);
+ if (length >= 0)
+ length = simple_read_from_buffer(buf, count, ppos, (char *)page, length);
+ free_page(page);
+out:
+ put_task_struct(task);
+out_no_task:
+ return length;
}
-static struct file_operations proc_tgid_base_operations = {
- .read = generic_read_dir,
- .readdir = proc_tgid_base_readdir,
-};
+static ssize_t proc_pid_attr_write(struct file * file, const char __user * buf,
+ size_t count, loff_t *ppos)
+{
+ struct inode * inode = file->f_dentry->d_inode;
+ char *page;
+ ssize_t length;
+ struct task_struct *task = get_proc_task(inode);
-static struct file_operations proc_tid_base_operations = {
- .read = generic_read_dir,
- .readdir = proc_tid_base_readdir,
-};
+ length = -ESRCH;
+ if (!task)
+ goto out_no_task;
+ if (count > PAGE_SIZE)
+ count = PAGE_SIZE;
-static struct inode_operations proc_tgid_base_inode_operations = {
- .lookup = proc_tgid_base_lookup,
- .getattr = pid_getattr,
- .setattr = proc_setattr,
+ /* No partial writes. */
+ length = -EINVAL;
+ if (*ppos != 0)
+ goto out;
+
+ length = -ENOMEM;
+ page = (char*)__get_free_page(GFP_USER);
+ if (!page)
+ goto out;
+
+ length = -EFAULT;
+ if (copy_from_user(page, buf, count))
+ goto out_free;
+
+ length = security_setprocattr(task,
+ (char*)file->f_dentry->d_name.name,
+ (void*)page, count);
+out_free:
+ free_page((unsigned long) page);
+out:
+ put_task_struct(task);
+out_no_task:
+ return length;
+}
+
+static struct file_operations proc_pid_attr_operations = {
+ .read = proc_pid_attr_read,
+ .write = proc_pid_attr_write,
};
-static struct inode_operations proc_tid_base_inode_operations = {
- .lookup = proc_tid_base_lookup,
- .getattr = pid_getattr,
- .setattr = proc_setattr,
+static struct pid_entry tgid_attr_stuff[] = {
+ E(PROC_TGID_ATTR_CURRENT, "current", S_IFREG|S_IRUGO|S_IWUGO),
+ E(PROC_TGID_ATTR_PREV, "prev", S_IFREG|S_IRUGO),
+ E(PROC_TGID_ATTR_EXEC, "exec", S_IFREG|S_IRUGO|S_IWUGO),
+ E(PROC_TGID_ATTR_FSCREATE, "fscreate", S_IFREG|S_IRUGO|S_IWUGO),
+ E(PROC_TGID_ATTR_KEYCREATE, "keycreate", S_IFREG|S_IRUGO|S_IWUGO),
+ E(PROC_TGID_ATTR_SOCKCREATE, "sockcreate", S_IFREG|S_IRUGO|S_IWUGO),
+ {0,0,NULL,0}
+};
+static struct pid_entry tid_attr_stuff[] = {
+ E(PROC_TID_ATTR_CURRENT, "current", S_IFREG|S_IRUGO|S_IWUGO),
+ E(PROC_TID_ATTR_PREV, "prev", S_IFREG|S_IRUGO),
+ E(PROC_TID_ATTR_EXEC, "exec", S_IFREG|S_IRUGO|S_IWUGO),
+ E(PROC_TID_ATTR_FSCREATE, "fscreate", S_IFREG|S_IRUGO|S_IWUGO),
+ E(PROC_TID_ATTR_KEYCREATE, "keycreate", S_IFREG|S_IRUGO|S_IWUGO),
+ E(PROC_TID_ATTR_SOCKCREATE, "sockcreate", S_IFREG|S_IRUGO|S_IWUGO),
+ {0,0,NULL,0}
};
-#ifdef CONFIG_SECURITY
static int proc_tgid_attr_readdir(struct file * filp,
void * dirent, filldir_t filldir)
{
@@ -1955,6 +1810,76 @@ static struct inode_operations proc_self
.follow_link = proc_self_follow_link,
};
+/*
+ * Thread groups
+ */
+static struct pid_entry tgid_base_stuff[] = {
+ E(PROC_TGID_TASK, "task", S_IFDIR|S_IRUGO|S_IXUGO),
+ E(PROC_TGID_FD, "fd", S_IFDIR|S_IRUSR|S_IXUSR),
+ E(PROC_TGID_ENVIRON, "environ", S_IFREG|S_IRUSR),
+ E(PROC_TGID_AUXV, "auxv", S_IFREG|S_IRUSR),
+ E(PROC_TGID_STATUS, "status", S_IFREG|S_IRUGO),
+ E(PROC_TGID_CMDLINE, "cmdline", S_IFREG|S_IRUGO),
+ E(PROC_TGID_STAT, "stat", S_IFREG|S_IRUGO),
+ E(PROC_TGID_STATM, "statm", S_IFREG|S_IRUGO),
+ E(PROC_TGID_MAPS, "maps", S_IFREG|S_IRUGO),
+#ifdef CONFIG_NUMA
+ E(PROC_TGID_NUMA_MAPS, "numa_maps", S_IFREG|S_IRUGO),
+#endif
+ E(PROC_TGID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR),
+#ifdef CONFIG_SECCOMP
+ E(PROC_TGID_SECCOMP, "seccomp", S_IFREG|S_IRUSR|S_IWUSR),
+#endif
+ 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_MOUNTS, "mounts", S_IFREG|S_IRUGO),
+ E(PROC_TGID_MOUNTSTATS, "mountstats", S_IFREG|S_IRUSR),
+#ifdef CONFIG_MMU
+ E(PROC_TGID_SMAPS, "smaps", S_IFREG|S_IRUGO),
+#endif
+#ifdef CONFIG_SECURITY
+ E(PROC_TGID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO),
+#endif
+#ifdef CONFIG_KALLSYMS
+ E(PROC_TGID_WCHAN, "wchan", S_IFREG|S_IRUGO),
+#endif
+#ifdef CONFIG_SCHEDSTATS
+ E(PROC_TGID_SCHEDSTAT, "schedstat", S_IFREG|S_IRUGO),
+#endif
+#ifdef CONFIG_CPUSETS
+ E(PROC_TGID_CPUSET, "cpuset", S_IFREG|S_IRUGO),
+#endif
+ E(PROC_TGID_OOM_SCORE, "oom_score",S_IFREG|S_IRUGO),
+ E(PROC_TGID_OOM_ADJUST,"oom_adj", S_IFREG|S_IRUGO|S_IWUSR),
+#ifdef CONFIG_AUDITSYSCALL
+ E(PROC_TGID_LOGINUID, "loginuid", S_IFREG|S_IWUSR|S_IRUGO),
+#endif
+ {0,0,NULL,0}
+};
+
+static int proc_tgid_base_readdir(struct file * filp,
+ void * dirent, filldir_t filldir)
+{
+ return proc_pident_readdir(filp,dirent,filldir,
+ tgid_base_stuff,ARRAY_SIZE(tgid_base_stuff));
+}
+
+static struct file_operations proc_tgid_base_operations = {
+ .read = generic_read_dir,
+ .readdir = proc_tgid_base_readdir,
+};
+
+static struct dentry *proc_tgid_base_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){
+ return proc_pident_lookup(dir, dentry, tgid_base_stuff);
+}
+
+static struct inode_operations proc_tgid_base_inode_operations = {
+ .lookup = proc_tgid_base_lookup,
+ .getattr = pid_getattr,
+ .setattr = proc_setattr,
+};
+
/**
* proc_flush_task - Remove dcache entries for @task from the /proc dcache.
*
@@ -2085,62 +2010,6 @@ out:
return result;
}
-/* SMP-safe */
-static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
-{
- struct dentry *result = ERR_PTR(-ENOENT);
- struct task_struct *task;
- struct task_struct *leader = get_proc_task(dir);
- struct inode *inode;
- unsigned tid;
-
- if (!leader)
- goto out_no_task;
-
- tid = name_to_int(dentry);
- if (tid == ~0U)
- goto out;
-
- rcu_read_lock();
- task = find_task_by_pid(tid);
- if (task)
- get_task_struct(task);
- rcu_read_unlock();
- if (!task)
- goto out;
- if (leader->tgid != task->tgid)
- goto out_drop_task;
-
- inode = proc_pid_make_inode(dir->i_sb, task, PROC_TID_INO);
-
-
- if (!inode)
- goto out_drop_task;
- inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
- inode->i_op = &proc_tid_base_inode_operations;
- inode->i_fop = &proc_tid_base_operations;
- inode->i_flags|=S_IMMUTABLE;
-#ifdef CONFIG_SECURITY
- inode->i_nlink = 4;
-#else
- inode->i_nlink = 3;
-#endif
-
- dentry->d_op = &pid_dentry_operations;
-
- d_add(dentry, inode);
- /* Close the race of the process dying before we return the dentry */
- if (pid_revalidate(dentry, NULL))
- result = NULL;
-
-out_drop_task:
- put_task_struct(task);
-out:
- put_task_struct(leader);
-out_no_task:
- return result;
-}
-
/*
* Find the first tgid to return to user space.
*
@@ -2250,6 +2119,130 @@ int proc_pid_readdir(struct file * filp,
}
/*
+ * Tasks
+ */
+static struct pid_entry tid_base_stuff[] = {
+ E(PROC_TID_FD, "fd", S_IFDIR|S_IRUSR|S_IXUSR),
+ E(PROC_TID_ENVIRON, "environ", S_IFREG|S_IRUSR),
+ E(PROC_TID_AUXV, "auxv", S_IFREG|S_IRUSR),
+ E(PROC_TID_STATUS, "status", S_IFREG|S_IRUGO),
+ E(PROC_TID_CMDLINE, "cmdline", S_IFREG|S_IRUGO),
+ E(PROC_TID_STAT, "stat", S_IFREG|S_IRUGO),
+ E(PROC_TID_STATM, "statm", S_IFREG|S_IRUGO),
+ E(PROC_TID_MAPS, "maps", S_IFREG|S_IRUGO),
+#ifdef CONFIG_NUMA
+ E(PROC_TID_NUMA_MAPS, "numa_maps", S_IFREG|S_IRUGO),
+#endif
+ E(PROC_TID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR),
+#ifdef CONFIG_SECCOMP
+ E(PROC_TID_SECCOMP, "seccomp", S_IFREG|S_IRUSR|S_IWUSR),
+#endif
+ 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_MOUNTS, "mounts", S_IFREG|S_IRUGO),
+#ifdef CONFIG_MMU
+ E(PROC_TID_SMAPS, "smaps", S_IFREG|S_IRUGO),
+#endif
+#ifdef CONFIG_SECURITY
+ E(PROC_TID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO),
+#endif
+#ifdef CONFIG_KALLSYMS
+ E(PROC_TID_WCHAN, "wchan", S_IFREG|S_IRUGO),
+#endif
+#ifdef CONFIG_SCHEDSTATS
+ E(PROC_TID_SCHEDSTAT, "schedstat",S_IFREG|S_IRUGO),
+#endif
+#ifdef CONFIG_CPUSETS
+ E(PROC_TID_CPUSET, "cpuset", S_IFREG|S_IRUGO),
+#endif
+ E(PROC_TID_OOM_SCORE, "oom_score",S_IFREG|S_IRUGO),
+ E(PROC_TID_OOM_ADJUST, "oom_adj", S_IFREG|S_IRUGO|S_IWUSR),
+#ifdef CONFIG_AUDITSYSCALL
+ E(PROC_TID_LOGINUID, "loginuid", S_IFREG|S_IWUSR|S_IRUGO),
+#endif
+ {0,0,NULL,0}
+};
+
+static int proc_tid_base_readdir(struct file * filp,
+ void * dirent, filldir_t filldir)
+{
+ return proc_pident_readdir(filp,dirent,filldir,
+ tid_base_stuff,ARRAY_SIZE(tid_base_stuff));
+}
+
+static struct dentry *proc_tid_base_lookup(struct inode *dir, struct dentry *dentry, struct nameidata *nd){
+ return proc_pident_lookup(dir, dentry, tid_base_stuff);
+}
+
+static struct file_operations proc_tid_base_operations = {
+ .read = generic_read_dir,
+ .readdir = proc_tid_base_readdir,
+};
+
+static struct inode_operations proc_tid_base_inode_operations = {
+ .lookup = proc_tid_base_lookup,
+ .getattr = pid_getattr,
+ .setattr = proc_setattr,
+};
+
+/* SMP-safe */
+static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
+{
+ struct dentry *result = ERR_PTR(-ENOENT);
+ struct task_struct *task;
+ struct task_struct *leader = get_proc_task(dir);
+ struct inode *inode;
+ unsigned tid;
+
+ if (!leader)
+ goto out_no_task;
+
+ tid = name_to_int(dentry);
+ if (tid == ~0U)
+ goto out;
+
+ rcu_read_lock();
+ task = find_task_by_pid(tid);
+ if (task)
+ get_task_struct(task);
+ rcu_read_unlock();
+ if (!task)
+ goto out;
+ if (leader->tgid != task->tgid)
+ goto out_drop_task;
+
+ inode = proc_pid_make_inode(dir->i_sb, task, PROC_TID_INO);
+
+
+ if (!inode)
+ goto out_drop_task;
+ inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
+ inode->i_op = &proc_tid_base_inode_operations;
+ inode->i_fop = &proc_tid_base_operations;
+ inode->i_flags|=S_IMMUTABLE;
+#ifdef CONFIG_SECURITY
+ inode->i_nlink = 4;
+#else
+ inode->i_nlink = 3;
+#endif
+
+ dentry->d_op = &pid_dentry_operations;
+
+ d_add(dentry, inode);
+ /* Close the race of the process dying before we return the dentry */
+ if (pid_revalidate(dentry, NULL))
+ result = NULL;
+
+out_drop_task:
+ put_task_struct(task);
+out:
+ put_task_struct(leader);
+out_no_task:
+ return result;
+}
+
+/*
* Find the first tid of a thread group to return to user space.
*
* Usually this is just the thread group leader, but if the users
@@ -2392,3 +2385,14 @@ static int proc_task_getattr(struct vfsm
return 0;
}
+
+static struct inode_operations proc_task_inode_operations = {
+ .lookup = proc_task_lookup,
+ .getattr = proc_task_getattr,
+ .setattr = proc_setattr,
+};
+
+static struct file_operations proc_task_operations = {
+ .read = generic_read_dir,
+ .readdir = proc_task_readdir,
+};
--
1.4.2.rc3.g7e18e-dirty
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH 2/7] proc: Modify proc_pident_lookup to be completely table driven.
2006-08-15 18:00 The rest of my proc cleanup Eric W. Biederman
2006-08-15 18:05 ` [PATCH 1/7] proc: Reorder the functions in base.c Eric W. Biederman
@ 2006-08-15 18:05 ` Eric W. Biederman
2006-08-15 18:31 ` Dave Hansen
2006-08-16 14:48 ` Jan Engelhardt
2006-08-15 18:05 ` [PATCH 3/7] proc: Give the root directory a task Eric W. Biederman
` (5 subsequent siblings)
7 siblings, 2 replies; 18+ messages in thread
From: Eric W. Biederman @ 2006-08-15 18:05 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-kernel, containers, Eric W. Biederman
Currently proc_pident_lookup gets the names and types from a table
and then has a huge switch statement to get the inode and file
operations it needs. That is silly and is becoming increasingly hard
to maintain so I just put all of the information in the table.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
fs/proc/base.c | 347 ++++++++++++++---------------------------------
include/linux/proc_fs.h | 10 +
2 files changed, 112 insertions(+), 245 deletions(-)
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 605ae9c..c46b42b 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -195,9 +195,36 @@ struct pid_entry {
int len;
char *name;
mode_t mode;
+ struct inode_operations *iop;
+ struct file_operations *fop;
+ union proc_op op;
};
-#define E(type,name,mode) {(type),sizeof(name)-1,(name),(mode)}
+#define NOD(TYPE, NAME, MODE, IOP, FOP, OP) { \
+ .type = (TYPE), \
+ .len = sizeof(NAME) - 1, \
+ .name = (NAME), \
+ .mode = MODE, \
+ .iop = IOP, \
+ .fop = FOP, \
+ .op = OP, \
+}
+
+#define DIR(TYPE, NAME, MODE, OTYPE) \
+ NOD(TYPE, NAME, (S_IFDIR|(MODE)), \
+ &proc_##OTYPE##_inode_operations, &proc_##OTYPE##_operations, \
+ {} )
+#define LNK(TYPE, NAME, OTYPE) \
+ NOD(TYPE, 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, \
+ &proc_##OTYPE##_operations, {})
+#define INF(TYPE, NAME, MODE, OTYPE) \
+ NOD(TYPE, NAME, (S_IFREG|(MODE)), \
+ NULL, &proc_info_file_operations, \
+ { .proc_read = &proc_##OTYPE } )
static struct fs_struct *get_fs_struct(struct task_struct *task)
{
@@ -1367,17 +1394,6 @@ static struct inode_operations proc_fd_i
.setattr = proc_setattr,
};
-static struct file_operations proc_task_operations;
-static struct inode_operations proc_task_inode_operations;
-
-#ifdef CONFIG_SECURITY
-static struct file_operations proc_pid_attr_operations;
-static struct file_operations proc_tid_attr_operations;
-static struct inode_operations proc_tid_attr_inode_operations;
-static struct file_operations proc_tgid_attr_operations;
-static struct inode_operations proc_tgid_attr_inode_operations;
-#endif
-
/* SMP-safe */
static struct dentry *proc_pident_lookup(struct inode *dir,
struct dentry *dentry,
@@ -1395,6 +1411,10 @@ static struct dentry *proc_pident_lookup
if (!task)
goto out_no_task;
+ /*
+ * Yes, it does not scale. And it should not. Don't add
+ * new entries into /proc/<tgid>/ without very good reasons.
+ */
for (p = ents; p->name; p++) {
if (p->len != dentry->d_name.len)
continue;
@@ -1411,171 +1431,13 @@ static struct dentry *proc_pident_lookup
ei = PROC_I(inode);
inode->i_mode = p->mode;
- /*
- * Yes, it does not scale. And it should not. Don't add
- * new entries into /proc/<tgid>/ without very good reasons.
- */
- switch(p->type) {
- case PROC_TGID_TASK:
- inode->i_nlink = 2;
- inode->i_op = &proc_task_inode_operations;
- inode->i_fop = &proc_task_operations;
- break;
- case PROC_TID_FD:
- case PROC_TGID_FD:
- inode->i_nlink = 2;
- inode->i_op = &proc_fd_inode_operations;
- inode->i_fop = &proc_fd_operations;
- break;
- case PROC_TID_EXE:
- case PROC_TGID_EXE:
- inode->i_op = &proc_pid_link_inode_operations;
- ei->op.proc_get_link = proc_exe_link;
- break;
- case PROC_TID_CWD:
- case PROC_TGID_CWD:
- inode->i_op = &proc_pid_link_inode_operations;
- ei->op.proc_get_link = proc_cwd_link;
- break;
- case PROC_TID_ROOT:
- case PROC_TGID_ROOT:
- inode->i_op = &proc_pid_link_inode_operations;
- ei->op.proc_get_link = proc_root_link;
- break;
- case PROC_TID_ENVIRON:
- case PROC_TGID_ENVIRON:
- inode->i_fop = &proc_info_file_operations;
- ei->op.proc_read = proc_pid_environ;
- break;
- case PROC_TID_AUXV:
- case PROC_TGID_AUXV:
- inode->i_fop = &proc_info_file_operations;
- ei->op.proc_read = proc_pid_auxv;
- break;
- case PROC_TID_STATUS:
- case PROC_TGID_STATUS:
- inode->i_fop = &proc_info_file_operations;
- ei->op.proc_read = proc_pid_status;
- break;
- case PROC_TID_STAT:
- inode->i_fop = &proc_info_file_operations;
- ei->op.proc_read = proc_tid_stat;
- break;
- case PROC_TGID_STAT:
- inode->i_fop = &proc_info_file_operations;
- ei->op.proc_read = proc_tgid_stat;
- break;
- case PROC_TID_CMDLINE:
- case PROC_TGID_CMDLINE:
- inode->i_fop = &proc_info_file_operations;
- ei->op.proc_read = proc_pid_cmdline;
- break;
- case PROC_TID_STATM:
- case PROC_TGID_STATM:
- inode->i_fop = &proc_info_file_operations;
- ei->op.proc_read = proc_pid_statm;
- break;
- case PROC_TID_MAPS:
- case PROC_TGID_MAPS:
- inode->i_fop = &proc_maps_operations;
- break;
-#ifdef CONFIG_NUMA
- case PROC_TID_NUMA_MAPS:
- case PROC_TGID_NUMA_MAPS:
- inode->i_fop = &proc_numa_maps_operations;
- break;
-#endif
- case PROC_TID_MEM:
- case PROC_TGID_MEM:
- inode->i_fop = &proc_mem_operations;
- break;
-#ifdef CONFIG_SECCOMP
- case PROC_TID_SECCOMP:
- case PROC_TGID_SECCOMP:
- inode->i_fop = &proc_seccomp_operations;
- break;
-#endif /* CONFIG_SECCOMP */
- case PROC_TID_MOUNTS:
- case PROC_TGID_MOUNTS:
- inode->i_fop = &proc_mounts_operations;
- break;
-#ifdef CONFIG_MMU
- case PROC_TID_SMAPS:
- case PROC_TGID_SMAPS:
- inode->i_fop = &proc_smaps_operations;
- break;
-#endif
- case PROC_TID_MOUNTSTATS:
- case PROC_TGID_MOUNTSTATS:
- inode->i_fop = &proc_mountstats_operations;
- break;
-#ifdef CONFIG_SECURITY
- case PROC_TID_ATTR:
- inode->i_nlink = 2;
- inode->i_op = &proc_tid_attr_inode_operations;
- inode->i_fop = &proc_tid_attr_operations;
- break;
- case PROC_TGID_ATTR:
- inode->i_nlink = 2;
- inode->i_op = &proc_tgid_attr_inode_operations;
- inode->i_fop = &proc_tgid_attr_operations;
- break;
- case PROC_TID_ATTR_CURRENT:
- case PROC_TGID_ATTR_CURRENT:
- case PROC_TID_ATTR_PREV:
- case PROC_TGID_ATTR_PREV:
- case PROC_TID_ATTR_EXEC:
- case PROC_TGID_ATTR_EXEC:
- case PROC_TID_ATTR_FSCREATE:
- case PROC_TGID_ATTR_FSCREATE:
- case PROC_TID_ATTR_KEYCREATE:
- case PROC_TGID_ATTR_KEYCREATE:
- case PROC_TID_ATTR_SOCKCREATE:
- case PROC_TGID_ATTR_SOCKCREATE:
- inode->i_fop = &proc_pid_attr_operations;
- break;
-#endif
-#ifdef CONFIG_KALLSYMS
- case PROC_TID_WCHAN:
- case PROC_TGID_WCHAN:
- inode->i_fop = &proc_info_file_operations;
- ei->op.proc_read = proc_pid_wchan;
- break;
-#endif
-#ifdef CONFIG_SCHEDSTATS
- case PROC_TID_SCHEDSTAT:
- case PROC_TGID_SCHEDSTAT:
- inode->i_fop = &proc_info_file_operations;
- ei->op.proc_read = proc_pid_schedstat;
- break;
-#endif
-#ifdef CONFIG_CPUSETS
- case PROC_TID_CPUSET:
- case PROC_TGID_CPUSET:
- inode->i_fop = &proc_cpuset_operations;
- break;
-#endif
- case PROC_TID_OOM_SCORE:
- case PROC_TGID_OOM_SCORE:
- inode->i_fop = &proc_info_file_operations;
- ei->op.proc_read = proc_oom_score;
- break;
- case PROC_TID_OOM_ADJUST:
- case PROC_TGID_OOM_ADJUST:
- inode->i_fop = &proc_oom_adjust_operations;
- break;
-#ifdef CONFIG_AUDITSYSCALL
- case PROC_TID_LOGINUID:
- case PROC_TGID_LOGINUID:
- inode->i_fop = &proc_loginuid_operations;
- break;
-#endif
- default:
- printk("procfs: impossible type (%d)",p->type);
- iput(inode);
- error = ERR_PTR(-EINVAL);
- goto out;
- }
+ if (S_ISDIR(inode->i_mode))
+ inode->i_nlink = 2; /* Use getattr to fix if necessary */
+ if (p->iop)
+ inode->i_op = p->iop;
+ if (p->fop)
+ inode->i_fop = p->fop;
+ ei->op = p->op;
dentry->d_op = &pid_dentry_operations;
d_add(dentry, inode);
/* Close the race of the process dying before we return the dentry */
@@ -1720,22 +1582,22 @@ static struct file_operations proc_pid_a
};
static struct pid_entry tgid_attr_stuff[] = {
- E(PROC_TGID_ATTR_CURRENT, "current", S_IFREG|S_IRUGO|S_IWUGO),
- E(PROC_TGID_ATTR_PREV, "prev", S_IFREG|S_IRUGO),
- E(PROC_TGID_ATTR_EXEC, "exec", S_IFREG|S_IRUGO|S_IWUGO),
- E(PROC_TGID_ATTR_FSCREATE, "fscreate", S_IFREG|S_IRUGO|S_IWUGO),
- E(PROC_TGID_ATTR_KEYCREATE, "keycreate", S_IFREG|S_IRUGO|S_IWUGO),
- E(PROC_TGID_ATTR_SOCKCREATE, "sockcreate", S_IFREG|S_IRUGO|S_IWUGO),
- {0,0,NULL,0}
+ 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),
+ {}
};
static struct pid_entry tid_attr_stuff[] = {
- E(PROC_TID_ATTR_CURRENT, "current", S_IFREG|S_IRUGO|S_IWUGO),
- E(PROC_TID_ATTR_PREV, "prev", S_IFREG|S_IRUGO),
- E(PROC_TID_ATTR_EXEC, "exec", S_IFREG|S_IRUGO|S_IWUGO),
- E(PROC_TID_ATTR_FSCREATE, "fscreate", S_IFREG|S_IRUGO|S_IWUGO),
- E(PROC_TID_ATTR_KEYCREATE, "keycreate", S_IFREG|S_IRUGO|S_IWUGO),
- E(PROC_TID_ATTR_SOCKCREATE, "sockcreate", S_IFREG|S_IRUGO|S_IWUGO),
- {0,0,NULL,0}
+ 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),
+ {}
};
static int proc_tgid_attr_readdir(struct file * filp,
@@ -1813,49 +1675,52 @@ static struct inode_operations proc_self
/*
* Thread groups
*/
+static struct file_operations proc_task_operations;
+static struct inode_operations proc_task_inode_operations;
+
static struct pid_entry tgid_base_stuff[] = {
- E(PROC_TGID_TASK, "task", S_IFDIR|S_IRUGO|S_IXUGO),
- E(PROC_TGID_FD, "fd", S_IFDIR|S_IRUSR|S_IXUSR),
- E(PROC_TGID_ENVIRON, "environ", S_IFREG|S_IRUSR),
- E(PROC_TGID_AUXV, "auxv", S_IFREG|S_IRUSR),
- E(PROC_TGID_STATUS, "status", S_IFREG|S_IRUGO),
- E(PROC_TGID_CMDLINE, "cmdline", S_IFREG|S_IRUGO),
- E(PROC_TGID_STAT, "stat", S_IFREG|S_IRUGO),
- E(PROC_TGID_STATM, "statm", S_IFREG|S_IRUGO),
- E(PROC_TGID_MAPS, "maps", S_IFREG|S_IRUGO),
+ 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),
#ifdef CONFIG_NUMA
- E(PROC_TGID_NUMA_MAPS, "numa_maps", S_IFREG|S_IRUGO),
+ REG(PROC_TGID_NUMA_MAPS, "numa_maps", S_IRUGO, numa_maps),
#endif
- E(PROC_TGID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR),
+ REG(PROC_TGID_MEM, "mem", S_IRUSR|S_IWUSR, mem),
#ifdef CONFIG_SECCOMP
- E(PROC_TGID_SECCOMP, "seccomp", S_IFREG|S_IRUSR|S_IWUSR),
+ REG(PROC_TGID_SECCOMP, "seccomp", S_IRUSR|S_IWUSR, seccomp),
#endif
- 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_MOUNTS, "mounts", S_IFREG|S_IRUGO),
- E(PROC_TGID_MOUNTSTATS, "mountstats", S_IFREG|S_IRUSR),
+ 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),
#ifdef CONFIG_MMU
- E(PROC_TGID_SMAPS, "smaps", S_IFREG|S_IRUGO),
+ REG(PROC_TGID_SMAPS, "smaps", S_IRUGO, smaps),
#endif
#ifdef CONFIG_SECURITY
- E(PROC_TGID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO),
+ DIR(PROC_TGID_ATTR, "attr", S_IRUGO|S_IXUGO, tgid_attr),
#endif
#ifdef CONFIG_KALLSYMS
- E(PROC_TGID_WCHAN, "wchan", S_IFREG|S_IRUGO),
+ INF(PROC_TGID_WCHAN, "wchan", S_IRUGO, pid_wchan),
#endif
#ifdef CONFIG_SCHEDSTATS
- E(PROC_TGID_SCHEDSTAT, "schedstat", S_IFREG|S_IRUGO),
+ INF(PROC_TGID_SCHEDSTAT, "schedstat", S_IRUGO, pid_schedstat),
#endif
#ifdef CONFIG_CPUSETS
- E(PROC_TGID_CPUSET, "cpuset", S_IFREG|S_IRUGO),
+ REG(PROC_TGID_CPUSET, "cpuset", S_IRUGO, cpuset),
#endif
- E(PROC_TGID_OOM_SCORE, "oom_score",S_IFREG|S_IRUGO),
- E(PROC_TGID_OOM_ADJUST,"oom_adj", S_IFREG|S_IRUGO|S_IWUSR),
+ INF(PROC_TGID_OOM_SCORE, "oom_score", S_IRUGO, oom_score),
+ REG(PROC_TGID_OOM_ADJUST, "oom_adj", S_IRUGO|S_IWUSR, oom_adjust),
#ifdef CONFIG_AUDITSYSCALL
- E(PROC_TGID_LOGINUID, "loginuid", S_IFREG|S_IWUSR|S_IRUGO),
+ REG(PROC_TGID_LOGINUID, "loginuid", S_IWUSR|S_IRUGO, loginuid),
#endif
- {0,0,NULL,0}
+ {}
};
static int proc_tgid_base_readdir(struct file * filp,
@@ -2122,46 +1987,46 @@ int proc_pid_readdir(struct file * filp,
* Tasks
*/
static struct pid_entry tid_base_stuff[] = {
- E(PROC_TID_FD, "fd", S_IFDIR|S_IRUSR|S_IXUSR),
- E(PROC_TID_ENVIRON, "environ", S_IFREG|S_IRUSR),
- E(PROC_TID_AUXV, "auxv", S_IFREG|S_IRUSR),
- E(PROC_TID_STATUS, "status", S_IFREG|S_IRUGO),
- E(PROC_TID_CMDLINE, "cmdline", S_IFREG|S_IRUGO),
- E(PROC_TID_STAT, "stat", S_IFREG|S_IRUGO),
- E(PROC_TID_STATM, "statm", S_IFREG|S_IRUGO),
- E(PROC_TID_MAPS, "maps", S_IFREG|S_IRUGO),
+ 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),
#ifdef CONFIG_NUMA
- E(PROC_TID_NUMA_MAPS, "numa_maps", S_IFREG|S_IRUGO),
+ REG(PROC_TID_NUMA_MAPS, "numa_maps", S_IRUGO, numa_maps),
#endif
- E(PROC_TID_MEM, "mem", S_IFREG|S_IRUSR|S_IWUSR),
+ REG(PROC_TID_MEM, "mem", S_IRUSR|S_IWUSR, mem),
#ifdef CONFIG_SECCOMP
- E(PROC_TID_SECCOMP, "seccomp", S_IFREG|S_IRUSR|S_IWUSR),
+ REG(PROC_TID_SECCOMP, "seccomp", S_IRUSR|S_IWUSR, seccomp),
#endif
- 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_MOUNTS, "mounts", S_IFREG|S_IRUGO),
+ 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),
#ifdef CONFIG_MMU
- E(PROC_TID_SMAPS, "smaps", S_IFREG|S_IRUGO),
+ REG(PROC_TID_SMAPS, "smaps", S_IRUGO, smaps),
#endif
#ifdef CONFIG_SECURITY
- E(PROC_TID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO),
+ DIR(PROC_TID_ATTR, "attr", S_IRUGO|S_IXUGO, tid_attr),
#endif
#ifdef CONFIG_KALLSYMS
- E(PROC_TID_WCHAN, "wchan", S_IFREG|S_IRUGO),
+ INF(PROC_TID_WCHAN, "wchan", S_IRUGO, pid_wchan),
#endif
#ifdef CONFIG_SCHEDSTATS
- E(PROC_TID_SCHEDSTAT, "schedstat",S_IFREG|S_IRUGO),
+ INF(PROC_TID_SCHEDSTAT, "schedstat", S_IRUGO, pid_schedstat),
#endif
#ifdef CONFIG_CPUSETS
- E(PROC_TID_CPUSET, "cpuset", S_IFREG|S_IRUGO),
+ REG(PROC_TID_CPUSET, "cpuset", S_IRUGO, cpuset),
#endif
- E(PROC_TID_OOM_SCORE, "oom_score",S_IFREG|S_IRUGO),
- E(PROC_TID_OOM_ADJUST, "oom_adj", S_IFREG|S_IRUGO|S_IWUSR),
+ INF(PROC_TID_OOM_SCORE, "oom_score", S_IRUGO, oom_score),
+ REG(PROC_TID_OOM_ADJUST, "oom_adj", S_IRUGO|S_IWUSR, oom_adjust),
#ifdef CONFIG_AUDITSYSCALL
- E(PROC_TID_LOGINUID, "loginuid", S_IFREG|S_IWUSR|S_IRUGO),
+ REG(PROC_TID_LOGINUID, "loginuid", S_IWUSR|S_IRUGO, loginuid),
#endif
- {0,0,NULL,0}
+ {}
};
static int proc_tid_base_readdir(struct file * filp,
diff --git a/include/linux/proc_fs.h b/include/linux/proc_fs.h
index 17e7578..533a25c 100644
--- a/include/linux/proc_fs.h
+++ b/include/linux/proc_fs.h
@@ -245,13 +245,15 @@ #else
extern void kclist_add(struct kcore_list *, void *, size_t);
#endif
+union proc_op {
+ int (*proc_get_link)(struct inode *, struct dentry **, struct vfsmount **);
+ int (*proc_read)(struct task_struct *task, char *page);
+};
+
struct proc_inode {
struct pid *pid;
int fd;
- union {
- int (*proc_get_link)(struct inode *, struct dentry **, struct vfsmount **);
- int (*proc_read)(struct task_struct *task, char *page);
- } op;
+ union proc_op op;
struct proc_dir_entry *pde;
struct inode vfs_inode;
};
--
1.4.2.rc3.g7e18e-dirty
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH 2/7] proc: Modify proc_pident_lookup to be completely table driven.
2006-08-15 18:05 ` [PATCH 2/7] proc: Modify proc_pident_lookup to be completely table driven Eric W. Biederman
@ 2006-08-15 18:31 ` Dave Hansen
2006-08-15 18:55 ` Eric W. Biederman
2006-08-16 14:48 ` Jan Engelhardt
1 sibling, 1 reply; 18+ messages in thread
From: Dave Hansen @ 2006-08-15 18:31 UTC (permalink / raw)
To: Eric W. Biederman; +Cc: Andrew Morton, linux-kernel, Linux Containers, dave
On Tue, 2006-08-15 at 12:05 -0600, Eric W. Biederman wrote:
> Currently proc_pident_lookup gets the names and types from a table
> and then has a huge switch statement to get the inode and file
> operations it needs. That is silly and is becoming increasingly hard
> to maintain so I just put all of the information in the table.
Looks pretty reasonable.
> +#define INF(TYPE, NAME, MODE, OTYPE) \
> + NOD(TYPE, NAME, (S_IFREG|(MODE)), \
> + NULL, &proc_info_file_operations, \
> + { .proc_read = &proc_##OTYPE } )
...
> + INF(PROC_TID_OOM_SCORE, "oom_score", S_IRUGO, oom_score),
> + REG(PROC_TID_OOM_ADJUST, "oom_adj", S_IRUGO|S_IWUSR, oom_adjust),
Could we give these some slightly more intuitive names? INF is a bit
terse ;)
Since these #defines and function are also all in base.c, and not
referenced elsewhere, might it be reasonable to take some of the PROC_
headers off of them? I know I've been frustrated more than once by
popping things like "oom_score" in to cscope and finding no definitions.
-- Dave
^ permalink raw reply [flat|nested] 18+ messages in thread* Re: [PATCH 2/7] proc: Modify proc_pident_lookup to be completely table driven.
2006-08-15 18:31 ` Dave Hansen
@ 2006-08-15 18:55 ` Eric W. Biederman
0 siblings, 0 replies; 18+ messages in thread
From: Eric W. Biederman @ 2006-08-15 18:55 UTC (permalink / raw)
To: Dave Hansen; +Cc: Andrew Morton, linux-kernel, Linux Containers, dave
Dave Hansen <haveblue@us.ibm.com> writes:
> On Tue, 2006-08-15 at 12:05 -0600, Eric W. Biederman wrote:
>> Currently proc_pident_lookup gets the names and types from a table
>> and then has a huge switch statement to get the inode and file
>> operations it needs. That is silly and is becoming increasingly hard
>> to maintain so I just put all of the information in the table.
>
> Looks pretty reasonable.
>
>> +#define INF(TYPE, NAME, MODE, OTYPE) \
>> + NOD(TYPE, NAME, (S_IFREG|(MODE)), \
>> + NULL, &proc_info_file_operations, \
>> + { .proc_read = &proc_##OTYPE } )
> ...
>> + INF(PROC_TID_OOM_SCORE, "oom_score", S_IRUGO, oom_score),
>> + REG(PROC_TID_OOM_ADJUST, "oom_adj", S_IRUGO|S_IWUSR, oom_adjust),
>
> Could we give these some slightly more intuitive names? INF is a bit
> terse ;)
> Since these #defines and function are also all in base.c, and not
> referenced elsewhere, might it be reasonable to take some of the PROC_
> headers off of them? I know I've been frustrated more than once by
> popping things like "oom_score" in to cscope and finding no definitions.
So as for taking the proc_ prefix off I don't see a real problem with
that but that should really be a different increment patch. Although removing
a little magic from my macros might be reasonable.
The only macro whose name really seems to terse is INF short for info,
so adding the O would be ok. What I would really like to see however
is all of these proc info things just go away. I seem to recall
they all have some pretty weird corner cases and a seq file implementation
is probably better there.
The other half of this is that I would very much like to see some of
these things moved out of base.c
Eric
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 2/7] proc: Modify proc_pident_lookup to be completely table driven.
2006-08-15 18:05 ` [PATCH 2/7] proc: Modify proc_pident_lookup to be completely table driven Eric W. Biederman
2006-08-15 18:31 ` Dave Hansen
@ 2006-08-16 14:48 ` Jan Engelhardt
1 sibling, 0 replies; 18+ messages in thread
From: Jan Engelhardt @ 2006-08-16 14:48 UTC (permalink / raw)
To: Eric W. Biederman; +Cc: Andrew Morton, linux-kernel, containers
>
>-#define E(type,name,mode) {(type),sizeof(name)-1,(name),(mode)}
>+#define NOD(TYPE, NAME, MODE, IOP, FOP, OP) { \
>+ .type = (TYPE), \
>+ .len = sizeof(NAME) - 1, \
>+ .name = (NAME), \
>+ .mode = MODE, \
>+ .iop = IOP, \
>+ .fop = FOP, \
>+ .op = OP, \
>+}
Please () around MODE IOP FOP and OP, just like it's already done
with TYPE and NAME.
Jan Engelhardt
--
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 3/7] proc: Give the root directory a task.
2006-08-15 18:00 The rest of my proc cleanup Eric W. Biederman
2006-08-15 18:05 ` [PATCH 1/7] proc: Reorder the functions in base.c Eric W. Biederman
2006-08-15 18:05 ` [PATCH 2/7] proc: Modify proc_pident_lookup to be completely table driven Eric W. Biederman
@ 2006-08-15 18:05 ` Eric W. Biederman
2006-08-15 18:05 ` [PATCH 4/7] proc: Make the generation of the self symlink table driven Eric W. Biederman
` (4 subsequent siblings)
7 siblings, 0 replies; 18+ messages in thread
From: Eric W. Biederman @ 2006-08-15 18:05 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-kernel, containers, Eric W. Biederman
Helper functions in base.c like proc_pident_readdir and proc_pident_lookup
assume the directories have an associated task, and cannot currently be used on
the /proc root directory because it does not have such a task.
This small changes allows for base.c to be simplified and later when multiple
pid spaces are introduced it makes getting the needed context information trivial.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
fs/proc/root.c | 12 ++++++++++++
1 files changed, 12 insertions(+), 0 deletions(-)
diff --git a/fs/proc/root.c b/fs/proc/root.c
index 8901c65..ffe66c3 100644
--- a/fs/proc/root.c
+++ b/fs/proc/root.c
@@ -16,6 +16,7 @@ #include <linux/init.h>
#include <linux/module.h>
#include <linux/bitops.h>
#include <linux/smp_lock.h>
+#include <linux/mount.h>
#include "internal.h"
@@ -28,6 +29,17 @@ #endif
static int proc_get_sb(struct file_system_type *fs_type,
int flags, const char *dev_name, void *data, struct vfsmount *mnt)
{
+ if (proc_mnt) {
+ /* Seed the root directory with a pid so it doesn't need
+ * to be special in base.c. I would do this earlier but
+ * the only task alive when /proc is mounted the first time
+ * is the init_task and it doesn't have any pids.
+ */
+ struct proc_inode *ei;
+ ei = PROC_I(proc_mnt->mnt_sb->s_root->d_inode);
+ if (!ei->pid)
+ ei->pid = find_get_pid(1);
+ }
return get_sb_single(fs_type, flags, data, proc_fill_super, mnt);
}
--
1.4.2.rc3.g7e18e-dirty
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH 4/7] proc: Make the generation of the self symlink table driven.
2006-08-15 18:00 The rest of my proc cleanup Eric W. Biederman
` (2 preceding siblings ...)
2006-08-15 18:05 ` [PATCH 3/7] proc: Give the root directory a task Eric W. Biederman
@ 2006-08-15 18:05 ` Eric W. Biederman
2006-08-19 8:06 ` Andrew Morton
2006-08-15 18:05 ` [PATCH 5/7] proc: Factor out an instantiate method from every lookup method Eric W. Biederman
` (3 subsequent siblings)
7 siblings, 1 reply; 18+ messages in thread
From: Eric W. Biederman @ 2006-08-15 18:05 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-kernel, containers, Eric W. Biederman
By not rolling our own inode we get a little more code reuse,
and things get a little simpler and we don't have special
cases to contend with later.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
fs/proc/base.c | 41 ++++++++++++++++++-----------------------
1 files changed, 18 insertions(+), 23 deletions(-)
diff --git a/fs/proc/base.c b/fs/proc/base.c
index c46b42b..96e22d7 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1745,6 +1745,13 @@ static struct inode_operations proc_tgid
.setattr = proc_setattr,
};
+static struct pid_entry proc_base_stuff[] = {
+ NOD(PROC_TGID_INO, "self", S_IFLNK|S_IRWXUGO,
+ &proc_self_inode_operations, NULL, {}),
+ {}
+};
+
+
/**
* proc_flush_task - Remove dcache entries for @task from the /proc dcache.
*
@@ -1818,24 +1825,12 @@ struct dentry *proc_pid_lookup(struct in
struct dentry *result = ERR_PTR(-ENOENT);
struct task_struct *task;
struct inode *inode;
- struct proc_inode *ei;
unsigned tgid;
- if (dentry->d_name.len == 4 && !memcmp(dentry->d_name.name,"self",4)) {
- inode = new_inode(dir->i_sb);
- if (!inode)
- return ERR_PTR(-ENOMEM);
- ei = PROC_I(inode);
- inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME;
- inode->i_ino = fake_ino(0, PROC_TGID_INO);
- ei->pde = NULL;
- inode->i_mode = S_IFLNK|S_IRWXUGO;
- inode->i_uid = inode->i_gid = 0;
- inode->i_size = 64;
- inode->i_op = &proc_self_inode_operations;
- d_add(dentry, inode);
- return NULL;
- }
+ result = proc_pident_lookup(dir, dentry, proc_base_stuff);
+ if (!IS_ERR(result) || PTR_ERR(result) != -ENOENT)
+ goto out;
+
tgid = name_to_int(dentry);
if (tgid == ~0U)
goto out;
@@ -1950,14 +1945,13 @@ int proc_pid_readdir(struct file * filp,
struct task_struct *task;
int tgid;
- if (!nr) {
- ino_t ino = fake_ino(0,PROC_TGID_INO);
- if (filldir(dirent, "self", 4, filp->f_pos, ino, DT_LNK) < 0)
- return 0;
- filp->f_pos++;
- nr++;
+ 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)
+ goto out;
}
- nr -= 1;
+ nr -= ARRAY_SIZE(proc_base_stuff) - 1;
/* f_version caches the tgid value that the last readdir call couldn't
* return. lseek aka telldir automagically resets f_version to 0.
@@ -1980,6 +1974,7 @@ int proc_pid_readdir(struct file * filp,
break;
}
}
+out:
return 0;
}
--
1.4.2.rc3.g7e18e-dirty
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: [PATCH 4/7] proc: Make the generation of the self symlink table driven.
2006-08-15 18:05 ` [PATCH 4/7] proc: Make the generation of the self symlink table driven Eric W. Biederman
@ 2006-08-19 8:06 ` Andrew Morton
2006-08-19 9:07 ` Eric W. Biederman
2006-08-19 9:54 ` Eric W. Biederman
0 siblings, 2 replies; 18+ messages in thread
From: Andrew Morton @ 2006-08-19 8:06 UTC (permalink / raw)
To: Eric W. Biederman; +Cc: linux-kernel, containers
On Tue, 15 Aug 2006 12:05:27 -0600
"Eric W. Biederman" <ebiederm@xmission.com> wrote:
> By not rolling our own inode we get a little more code reuse,
> and things get a little simpler and we don't have special
> cases to contend with later.
On a standard FC5 install (which has selinux enabled) things get very ugly.
udev: MAKEDEV: mkdir: file exists
followed by a stream of udev errors of various sorts and then an infinite
loop of auditd complaints about klogd and "/" and tmpfs. Nothing makes it
to logs because klogd itself is failing.
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 4/7] proc: Make the generation of the self symlink table driven.
2006-08-19 8:06 ` Andrew Morton
@ 2006-08-19 9:07 ` Eric W. Biederman
2006-08-19 16:03 ` Andrew Morton
2006-08-19 9:54 ` Eric W. Biederman
1 sibling, 1 reply; 18+ messages in thread
From: Eric W. Biederman @ 2006-08-19 9:07 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-kernel, containers
Andrew Morton <akpm@osdl.org> writes:
> On Tue, 15 Aug 2006 12:05:27 -0600
> "Eric W. Biederman" <ebiederm@xmission.com> wrote:
>
>> By not rolling our own inode we get a little more code reuse,
>> and things get a little simpler and we don't have special
>> cases to contend with later.
>
> On a standard FC5 install (which has selinux enabled) things get very ugly.
>
> udev: MAKEDEV: mkdir: file exists
>
> followed by a stream of udev errors of various sorts and then an infinite
> loop of auditd complaints about klogd and "/" and tmpfs. Nothing makes it
> to logs because klogd itself is failing.
I'm not feeling very generous today. I'm wondering what selinux bug
I have found now. Without selinux everything is fine on FC5.
Any chance of a search through that patchset to see which patch selinux
trips on?
Eric
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 4/7] proc: Make the generation of the self symlink table driven.
2006-08-19 9:07 ` Eric W. Biederman
@ 2006-08-19 16:03 ` Andrew Morton
2006-08-19 19:04 ` Eric W. Biederman
0 siblings, 1 reply; 18+ messages in thread
From: Andrew Morton @ 2006-08-19 16:03 UTC (permalink / raw)
To: Eric W. Biederman; +Cc: linux-kernel, containers
On Sat, 19 Aug 2006 03:07:37 -0600
ebiederm@xmission.com (Eric W. Biederman) wrote:
> Andrew Morton <akpm@osdl.org> writes:
>
> > On Tue, 15 Aug 2006 12:05:27 -0600
> > "Eric W. Biederman" <ebiederm@xmission.com> wrote:
> >
> >> By not rolling our own inode we get a little more code reuse,
> >> and things get a little simpler and we don't have special
> >> cases to contend with later.
> >
> > On a standard FC5 install (which has selinux enabled) things get very ugly.
> >
> > udev: MAKEDEV: mkdir: file exists
> >
> > followed by a stream of udev errors of various sorts and then an infinite
> > loop of auditd complaints about klogd and "/" and tmpfs. Nothing makes it
> > to logs because klogd itself is failing.
>
> I'm not feeling very generous today. I'm wondering what selinux bug
> I have found now. Without selinux everything is fine on FC5.
>
> Any chance of a search through that patchset to see which patch selinux
> trips on?
>
This one. "PATCH 4/7] proc: Make the generation of the self symlink table driven."
^ permalink raw reply [flat|nested] 18+ messages in thread
* Re: [PATCH 4/7] proc: Make the generation of the self symlink table driven.
2006-08-19 16:03 ` Andrew Morton
@ 2006-08-19 19:04 ` Eric W. Biederman
0 siblings, 0 replies; 18+ messages in thread
From: Eric W. Biederman @ 2006-08-19 19:04 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-kernel, containers, Stephen Smalley
Andrew Morton <akpm@osdl.org> writes:
> On Sat, 19 Aug 2006 03:07:37 -0600
> ebiederm@xmission.com (Eric W. Biederman) wrote:
>
>> Andrew Morton <akpm@osdl.org> writes:
>>
>> > On Tue, 15 Aug 2006 12:05:27 -0600
>> > "Eric W. Biederman" <ebiederm@xmission.com> wrote:
>> >
>> >> By not rolling our own inode we get a little more code reuse,
>> >> and things get a little simpler and we don't have special
>> >> cases to contend with later.
>> >
>> > On a standard FC5 install (which has selinux enabled) things get very ugly.
>> >
>> > udev: MAKEDEV: mkdir: file exists
>> >
>> > followed by a stream of udev errors of various sorts and then an infinite
>> > loop of auditd complaints about klogd and "/" and tmpfs. Nothing makes it
>> > to logs because klogd itself is failing.
>>
>> I'm not feeling very generous today. I'm wondering what selinux bug
>> I have found now. Without selinux everything is fine on FC5.
>>
>> Any chance of a search through that patchset to see which patch selinux
>> trips on?
>>
>
> This one. "PATCH 4/7] proc: Make the generation of the self symlink table
> driven."
Thanks. I have reproduced it and I can see what is different. There
is a call of security_task_to_inode that was added to the /proc/self
inode creation.
The following patch works around the problem, by preserving the
current behavior of security label assignment. I have yet to work out
why having a different security label causes failure for a world
accessible symlink.
I am starting to suspect that security_task_to_inode is a fundamentally
flawed concept, as I can get around it by opening a file before the security
label changes, and still have access to it. Which in proc is a bad
thing. But there are already checks on the paths that have sensitive
data so I'm not certain what the point of security_task_to_inode.
I have a bunch more digging to do to understand what is really going
on and if any of it makes sense.
Currently it looks like the good fix will be to just delete security_task_to_inode.
But I won't generate the patch for that until I dig into this farther.
---
security/selinux/hooks.c | 13 ++++++++++++-
1 files changed, 12 insertions(+), 1 deletions(-)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 180b26b..59bfd3c 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -2868,7 +2868,18 @@ static void selinux_task_to_inode(struct
struct task_security_struct *tsec = p->security;
struct inode_security_struct *isec = inode->i_security;
- isec->sid = tsec->sid;
+ if (S_ISLNK(inode->i_mode)) {
+ struct superblock_security_struct *sbsec;
+ sbsec = inode->i_sb->s_security;
+ if (!sbsec->initialized) {
+ /* Defer initialization */
+ printk(KERN_EMERG "%s sb not initialized\n", __func__);
+ return;
+ }
+ isec->sid = sbsec->sid;
+ } else {
+ isec->sid = tsec->sid;
+ }
isec->initialized = 1;
return;
}
^ permalink raw reply related [flat|nested] 18+ messages in thread
* Re: [PATCH 4/7] proc: Make the generation of the self symlink table driven.
2006-08-19 8:06 ` Andrew Morton
2006-08-19 9:07 ` Eric W. Biederman
@ 2006-08-19 9:54 ` Eric W. Biederman
1 sibling, 0 replies; 18+ messages in thread
From: Eric W. Biederman @ 2006-08-19 9:54 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-kernel, containers
Andrew Morton <akpm@osdl.org> writes:
> On Tue, 15 Aug 2006 12:05:27 -0600
> "Eric W. Biederman" <ebiederm@xmission.com> wrote:
>
>> By not rolling our own inode we get a little more code reuse,
>> and things get a little simpler and we don't have special
>> cases to contend with later.
>
> On a standard FC5 install (which has selinux enabled) things get very ugly.
>
> udev: MAKEDEV: mkdir: file exists
>
> followed by a stream of udev errors of various sorts and then an infinite
> loop of auditd complaints about klogd and "/" and tmpfs. Nothing makes it
> to logs because klogd itself is failing.
Anyone know what I need to do to enable selinux so I can reproduce
this. The kernel thinks it's running but sestatus -v says it's
disabled.
I have a recently installed FC5 system.
Eric
^ permalink raw reply [flat|nested] 18+ messages in thread
* [PATCH 5/7] proc: Factor out an instantiate method from every lookup method.
2006-08-15 18:00 The rest of my proc cleanup Eric W. Biederman
` (3 preceding siblings ...)
2006-08-15 18:05 ` [PATCH 4/7] proc: Make the generation of the self symlink table driven Eric W. Biederman
@ 2006-08-15 18:05 ` Eric W. Biederman
2006-08-16 14:52 ` Jan Engelhardt
2006-08-15 18:05 ` [PATCH 6/7] proc: Remove the hard coded inode numbers Eric W. Biederman
` (2 subsequent siblings)
7 siblings, 1 reply; 18+ messages in thread
From: Eric W. Biederman @ 2006-08-15 18:05 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-kernel, containers, Eric W. Biederman
To remove the hard coded proc inode numbers it is necessary to be able
to create the proc inodes during readdir. The instantiate methods are
the subset of lookup that is needed to accomplish that.
This first step just splits the lookup methods into 2 functions.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
fs/proc/base.c | 214 +++++++++++++++++++++++++++++++++-----------------------
1 files changed, 125 insertions(+), 89 deletions(-)
diff --git a/fs/proc/base.c b/fs/proc/base.c
index 96e22d7..bb6a631 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1253,21 +1253,15 @@ static struct dentry_operations tid_fd_d
.d_delete = pid_delete_dentry,
};
-/* SMP-safe */
-static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
+static struct dentry *proc_fd_instantiate(struct inode *dir,
+ struct dentry *dentry, struct task_struct *task, void *ptr)
{
- struct task_struct *task = get_proc_task(dir);
- unsigned fd = name_to_int(dentry);
- struct dentry *result = ERR_PTR(-ENOENT);
- struct file * file;
- struct files_struct * files;
- struct inode *inode;
- struct proc_inode *ei;
-
- if (!task)
- goto out_no_task;
- if (fd == ~0U)
- goto out;
+ unsigned fd = *(unsigned *)ptr;
+ struct file *file;
+ struct files_struct *files;
+ struct inode *inode;
+ struct proc_inode *ei;
+ struct dentry *error = ERR_PTR(-ENOENT);
inode = proc_pid_make_inode(dir->i_sb, task, PROC_TID_FD_DIR+fd);
if (!inode)
@@ -1276,7 +1270,7 @@ static struct dentry *proc_lookupfd(stru
ei->fd = fd;
files = get_files_struct(task);
if (!files)
- goto out_unlock;
+ goto out_iput;
inode->i_mode = S_IFLNK;
/*
@@ -1286,13 +1280,14 @@ static struct dentry *proc_lookupfd(stru
spin_lock(&files->file_lock);
file = fcheck_files(files, fd);
if (!file)
- goto out_unlock2;
+ goto out_unlock;
if (file->f_mode & 1)
inode->i_mode |= S_IRUSR | S_IXUSR;
if (file->f_mode & 2)
inode->i_mode |= S_IWUSR | S_IXUSR;
spin_unlock(&files->file_lock);
put_files_struct(files);
+
inode->i_op = &proc_pid_link_inode_operations;
inode->i_size = 64;
ei->op.proc_get_link = proc_fd_link;
@@ -1300,20 +1295,37 @@ static struct dentry *proc_lookupfd(stru
d_add(dentry, inode);
/* Close the race of the process dying before we return the dentry */
if (tid_fd_revalidate(dentry, NULL))
- result = NULL;
-out:
- put_task_struct(task);
-out_no_task:
- return result;
+ error = NULL;
-out_unlock2:
+ out:
+ return error;
+out_unlock:
spin_unlock(&files->file_lock);
put_files_struct(files);
-out_unlock:
+out_iput:
iput(inode);
goto out;
}
+/* SMP-safe */
+static struct dentry *proc_lookupfd(struct inode * dir, struct dentry * dentry, struct nameidata *nd)
+{
+ struct task_struct *task = get_proc_task(dir);
+ unsigned fd = name_to_int(dentry);
+ struct dentry *result = ERR_PTR(-ENOENT);
+
+ if (!task)
+ goto out_no_task;
+ if (fd == ~0U)
+ goto out;
+
+ result = proc_fd_instantiate(dir, dentry, task, &fd);
+out:
+ put_task_struct(task);
+out_no_task:
+ return result;
+}
+
static int proc_readfd(struct file * filp, void * dirent, filldir_t filldir)
{
struct dentry *dentry = filp->f_dentry;
@@ -1394,6 +1406,36 @@ static struct inode_operations proc_fd_i
.setattr = proc_setattr,
};
+static struct dentry *proc_pident_instantiate(struct inode *dir,
+ struct dentry *dentry, struct task_struct *task, void *ptr)
+{
+ struct pid_entry *p = ptr;
+ struct inode *inode;
+ struct proc_inode *ei;
+ struct dentry *error = ERR_PTR(-EINVAL);
+
+ inode = proc_pid_make_inode(dir->i_sb, task, p->type);
+ if (!inode)
+ goto out;
+
+ ei = PROC_I(inode);
+ inode->i_mode = p->mode;
+ if (S_ISDIR(inode->i_mode))
+ inode->i_nlink = 2; /* Use getattr to fix if necessary */
+ if (p->iop)
+ inode->i_op = p->iop;
+ if (p->fop)
+ inode->i_fop = p->fop;
+ ei->op = p->op;
+ dentry->d_op = &pid_dentry_operations;
+ d_add(dentry, inode);
+ /* Close the race of the process dying before we return the dentry */
+ if (pid_revalidate(dentry, NULL))
+ error = NULL;
+out:
+ return error;
+}
+
/* SMP-safe */
static struct dentry *proc_pident_lookup(struct inode *dir,
struct dentry *dentry,
@@ -1403,7 +1445,6 @@ static struct dentry *proc_pident_lookup
struct dentry *error;
struct task_struct *task = get_proc_task(dir);
struct pid_entry *p;
- struct proc_inode *ei;
error = ERR_PTR(-ENOENT);
inode = NULL;
@@ -1424,25 +1465,7 @@ static struct dentry *proc_pident_lookup
if (!p->name)
goto out;
- error = ERR_PTR(-EINVAL);
- inode = proc_pid_make_inode(dir->i_sb, task, p->type);
- if (!inode)
- goto out;
-
- ei = PROC_I(inode);
- inode->i_mode = p->mode;
- if (S_ISDIR(inode->i_mode))
- inode->i_nlink = 2; /* Use getattr to fix if necessary */
- if (p->iop)
- inode->i_op = p->iop;
- if (p->fop)
- inode->i_fop = p->fop;
- ei->op = p->op;
- dentry->d_op = &pid_dentry_operations;
- d_add(dentry, inode);
- /* Close the race of the process dying before we return the dentry */
- if (pid_revalidate(dentry, NULL))
- error = NULL;
+ error = proc_pident_instantiate(dir, dentry, task, p);
out:
put_task_struct(task);
out_no_task:
@@ -1819,12 +1842,40 @@ out:
return;
}
+struct dentry *proc_pid_instantiate(struct inode *dir,
+ struct dentry * dentry, struct task_struct *task, void *ptr)
+{
+ struct dentry *error = ERR_PTR(-ENOENT);
+ struct inode *inode;
+
+ inode = proc_pid_make_inode(dir->i_sb, task, PROC_TGID_INO);
+ if (!inode)
+ goto out;
+
+ inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
+ inode->i_op = &proc_tgid_base_inode_operations;
+ inode->i_fop = &proc_tgid_base_operations;
+ inode->i_flags|=S_IMMUTABLE;
+ inode->i_nlink = 4;
+#ifdef CONFIG_SECURITY
+ inode->i_nlink += 1;
+#endif
+
+ dentry->d_op = &pid_dentry_operations;
+
+ d_add(dentry, inode);
+ /* Close the race of the process dying before we return the dentry */
+ if (pid_revalidate(dentry, NULL))
+ error = NULL;
+out:
+ return error;
+}
+
/* SMP-safe */
struct dentry *proc_pid_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
{
struct dentry *result = ERR_PTR(-ENOENT);
struct task_struct *task;
- struct inode *inode;
unsigned tgid;
result = proc_pident_lookup(dir, dentry, proc_base_stuff);
@@ -1843,28 +1894,7 @@ struct dentry *proc_pid_lookup(struct in
if (!task)
goto out;
- inode = proc_pid_make_inode(dir->i_sb, task, PROC_TGID_INO);
- if (!inode)
- goto out_put_task;
-
- inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
- inode->i_op = &proc_tgid_base_inode_operations;
- inode->i_fop = &proc_tgid_base_operations;
- inode->i_flags|=S_IMMUTABLE;
-#ifdef CONFIG_SECURITY
- inode->i_nlink = 5;
-#else
- inode->i_nlink = 4;
-#endif
-
- dentry->d_op = &pid_dentry_operations;
-
- d_add(dentry, inode);
- /* Close the race of the process dying before we return the dentry */
- if (pid_revalidate(dentry, NULL))
- result = NULL;
-
-out_put_task:
+ result = proc_pid_instantiate(dir, dentry, task, NULL);
put_task_struct(task);
out:
return result;
@@ -2046,13 +2076,40 @@ static struct inode_operations proc_tid_
.setattr = proc_setattr,
};
+static struct dentry *proc_task_instantiate(struct inode *dir,
+ struct dentry *dentry, struct task_struct *task, void *ptr)
+{
+ struct dentry *error = ERR_PTR(-ENOENT);
+ struct inode *inode;
+ inode = proc_pid_make_inode(dir->i_sb, task, PROC_TID_INO);
+
+ if (!inode)
+ goto out;
+ inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
+ inode->i_op = &proc_tid_base_inode_operations;
+ inode->i_fop = &proc_tid_base_operations;
+ inode->i_flags|=S_IMMUTABLE;
+ inode->i_nlink = 3;
+#ifdef CONFIG_SECURITY
+ inode->i_nlink += 1;
+#endif
+
+ dentry->d_op = &pid_dentry_operations;
+
+ d_add(dentry, inode);
+ /* Close the race of the process dying before we return the dentry */
+ if (pid_revalidate(dentry, NULL))
+ error = NULL;
+out:
+ return error;
+}
+
/* SMP-safe */
static struct dentry *proc_task_lookup(struct inode *dir, struct dentry * dentry, struct nameidata *nd)
{
struct dentry *result = ERR_PTR(-ENOENT);
struct task_struct *task;
struct task_struct *leader = get_proc_task(dir);
- struct inode *inode;
unsigned tid;
if (!leader)
@@ -2072,28 +2129,7 @@ static struct dentry *proc_task_lookup(s
if (leader->tgid != task->tgid)
goto out_drop_task;
- inode = proc_pid_make_inode(dir->i_sb, task, PROC_TID_INO);
-
-
- if (!inode)
- goto out_drop_task;
- inode->i_mode = S_IFDIR|S_IRUGO|S_IXUGO;
- inode->i_op = &proc_tid_base_inode_operations;
- inode->i_fop = &proc_tid_base_operations;
- inode->i_flags|=S_IMMUTABLE;
-#ifdef CONFIG_SECURITY
- inode->i_nlink = 4;
-#else
- inode->i_nlink = 3;
-#endif
-
- dentry->d_op = &pid_dentry_operations;
-
- d_add(dentry, inode);
- /* Close the race of the process dying before we return the dentry */
- if (pid_revalidate(dentry, NULL))
- result = NULL;
-
+ result = proc_task_instantiate(dir, dentry, task, NULL);
out_drop_task:
put_task_struct(task);
out:
--
1.4.2.rc3.g7e18e-dirty
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH 6/7] proc: Remove the hard coded inode numbers.
2006-08-15 18:00 The rest of my proc cleanup Eric W. Biederman
` (4 preceding siblings ...)
2006-08-15 18:05 ` [PATCH 5/7] proc: Factor out an instantiate method from every lookup method Eric W. Biederman
@ 2006-08-15 18:05 ` Eric W. Biederman
2006-08-15 18:05 ` [PATCH 7/7] proc: Merge proc_tid_attr and proc_tgid_attr Eric W. Biederman
2006-08-15 18:33 ` The rest of my proc cleanup Paul Jackson
7 siblings, 0 replies; 18+ messages in thread
From: Eric W. Biederman @ 2006-08-15 18:05 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-kernel, containers, Eric W. Biederman
The hard coded inode numbers in proc currently limit it's
maintainability, it's flexibility, and what can be done with
the rest of system. /proc limits pid-max to 32768 on 32 bit
systems it limits fd-max to 32768 on all systems, and placing
the pid in the inode number really gets in the way of implementing
multiple pid namespaces.
Ever since people started adding to the middle of the file type
enumeration we haven't been maintaing the historical inode numbers,
all we have really succeeded in doing is keeping the pid in the proc
inode number. The pid is already available in the directory name
so no information is lost removing it from the inode number.
So if something in user space cares if we remove the inode number
from the /proc inode it is almost certainly broken.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
fs/proc/base.c | 376 +++++++++++++++++++++++++-------------------------------
1 files changed, 167 insertions(+), 209 deletions(-)
diff --git a/fs/proc/base.c b/fs/proc/base.c
index bb6a631..f657210 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -84,114 +84,11 @@ #include "internal.h"
* 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 @@ #define NOD(TYPE, NAME, MODE, IOP, FOP,
.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 } )
@@ -1042,7 +938,7 @@ static int task_dumpable(struct task_str
}
-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;
@@ -1056,7 +952,6 @@ static struct inode *proc_pid_make_inode
/* 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;
/*
@@ -1159,6 +1054,50 @@ static struct dentry_operations pid_dent
/* 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;
@@ -1263,7 +1202,7 @@ static struct dentry *proc_fd_instantiat
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);
@@ -1326,6 +1265,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;
@@ -1333,7 +1281,6 @@ static int proc_readfd(struct file * fil
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;
@@ -1363,22 +1310,12 @@ static int proc_readfd(struct file * fil
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;
}
@@ -1414,7 +1351,7 @@ static struct dentry *proc_pident_instan
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;
@@ -1472,6 +1409,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)
@@ -1487,11 +1431,10 @@ static int proc_pident_readdir(struct fi
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:
@@ -1516,8 +1459,7 @@ static int proc_pident_readdir(struct fi
}
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++;
@@ -1526,6 +1468,8 @@ static int proc_pident_readdir(struct fi
ret = 1;
out:
+ put_task_struct(task);
+out_no_task:
return ret;
}
@@ -1605,21 +1549,21 @@ static struct file_operations proc_pid_a
};
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),
{}
};
@@ -1702,46 +1646,46 @@ static struct file_operations proc_task_
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
{}
};
@@ -1769,7 +1713,7 @@ static struct inode_operations proc_tgid
};
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, {}),
{}
};
@@ -1848,7 +1792,7 @@ struct dentry *proc_pid_instantiate(stru
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;
@@ -1967,18 +1911,29 @@ done:
return pos;
}
+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_pident_fill_cache(filp, dirent, filldir, reaper, p) < 0)
goto out;
}
nr -= ARRAY_SIZE(proc_base_stuff) - 1;
@@ -1991,12 +1946,8 @@ int proc_pid_readdir(struct file * filp,
for (task = first_tgid(tgid, nr);
task;
task = next_tgid(task), filp->f_pos++) {
- int len;
- ino_t ino;
tgid = task->pid;
- 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) {
/* returning this tgid failed, save it as the first
* pid for the next readir call */
filp->f_version = tgid;
@@ -2005,6 +1956,8 @@ int proc_pid_readdir(struct file * filp,
}
}
out:
+ put_task_struct(reaper);
+out_no_task:
return 0;
}
@@ -2012,44 +1965,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
{}
};
@@ -2081,7 +2034,7 @@ static struct dentry *proc_task_instanti
{
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;
@@ -2207,10 +2160,18 @@ static struct task_struct *next_tid(stru
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);
@@ -2247,11 +2208,8 @@ static int proc_task_readdir(struct file
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;
--
1.4.2.rc3.g7e18e-dirty
^ permalink raw reply related [flat|nested] 18+ messages in thread* [PATCH 7/7] proc: Merge proc_tid_attr and proc_tgid_attr
2006-08-15 18:00 The rest of my proc cleanup Eric W. Biederman
` (5 preceding siblings ...)
2006-08-15 18:05 ` [PATCH 6/7] proc: Remove the hard coded inode numbers Eric W. Biederman
@ 2006-08-15 18:05 ` Eric W. Biederman
2006-08-15 18:33 ` The rest of my proc cleanup Paul Jackson
7 siblings, 0 replies; 18+ messages in thread
From: Eric W. Biederman @ 2006-08-15 18:05 UTC (permalink / raw)
To: Andrew Morton; +Cc: linux-kernel, containers, Eric W. Biederman
The implementation is exactly the same and there is currently nothing to
distinguish proc_tid_attr, and proc_tgid_attr. So it is pointless
to have two separate implementations.
Signed-off-by: Eric W. Biederman <ebiederm@xmission.com>
---
fs/proc/base.c | 54 +++++++++++-------------------------------------------
1 files changed, 11 insertions(+), 43 deletions(-)
diff --git a/fs/proc/base.c b/fs/proc/base.c
index f657210..9943527 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -1548,16 +1548,7 @@ static struct file_operations proc_pid_a
.write = proc_pid_attr_write,
};
-static struct pid_entry tgid_attr_stuff[] = {
- 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[] = {
+static struct pid_entry attr_dir_stuff[] = {
REG("current", S_IRUGO|S_IWUGO, pid_attr),
REG("prev", S_IRUGO, pid_attr),
REG("exec", S_IRUGO|S_IWUGO, pid_attr),
@@ -1567,53 +1558,30 @@ static struct pid_entry tid_attr_stuff[]
{}
};
-static int proc_tgid_attr_readdir(struct file * filp,
+static int proc_attr_dir_readdir(struct file * filp,
void * dirent, filldir_t filldir)
{
return proc_pident_readdir(filp,dirent,filldir,
- tgid_attr_stuff,ARRAY_SIZE(tgid_attr_stuff));
+ attr_dir_stuff,ARRAY_SIZE(attr_dir_stuff));
}
-static int proc_tid_attr_readdir(struct file * filp,
- void * dirent, filldir_t filldir)
-{
- return proc_pident_readdir(filp,dirent,filldir,
- tid_attr_stuff,ARRAY_SIZE(tid_attr_stuff));
-}
-
-static struct file_operations proc_tgid_attr_operations = {
- .read = generic_read_dir,
- .readdir = proc_tgid_attr_readdir,
-};
-
-static struct file_operations proc_tid_attr_operations = {
+static struct file_operations proc_attr_dir_operations = {
.read = generic_read_dir,
- .readdir = proc_tid_attr_readdir,
+ .readdir = proc_attr_dir_readdir,
};
-static struct dentry *proc_tgid_attr_lookup(struct inode *dir,
+static struct dentry *proc_attr_dir_lookup(struct inode *dir,
struct dentry *dentry, struct nameidata *nd)
{
- return proc_pident_lookup(dir, dentry, tgid_attr_stuff);
+ return proc_pident_lookup(dir, dentry, attr_dir_stuff);
}
-static struct dentry *proc_tid_attr_lookup(struct inode *dir,
- struct dentry *dentry, struct nameidata *nd)
-{
- return proc_pident_lookup(dir, dentry, tid_attr_stuff);
-}
-
-static struct inode_operations proc_tgid_attr_inode_operations = {
- .lookup = proc_tgid_attr_lookup,
+static struct inode_operations proc_attr_dir_inode_operations = {
+ .lookup = proc_attr_dir_lookup,
.getattr = pid_getattr,
.setattr = proc_setattr,
};
-static struct inode_operations proc_tid_attr_inode_operations = {
- .lookup = proc_tid_attr_lookup,
- .getattr = pid_getattr,
- .setattr = proc_setattr,
-};
#endif
/*
@@ -1671,7 +1639,7 @@ #ifdef CONFIG_MMU
REG("smaps", S_IRUGO, smaps),
#endif
#ifdef CONFIG_SECURITY
- DIR("attr", S_IRUGO|S_IXUGO, tgid_attr),
+ DIR("attr", S_IRUGO|S_IXUGO, attr_dir),
#endif
#ifdef CONFIG_KALLSYMS
INF("wchan", S_IRUGO, pid_wchan),
@@ -1988,7 +1956,7 @@ #ifdef CONFIG_MMU
REG("smaps", S_IRUGO, smaps),
#endif
#ifdef CONFIG_SECURITY
- DIR("attr", S_IRUGO|S_IXUGO, tid_attr),
+ DIR("attr", S_IRUGO|S_IXUGO, attr_dir),
#endif
#ifdef CONFIG_KALLSYMS
INF("wchan", S_IRUGO, pid_wchan),
--
1.4.2.rc3.g7e18e-dirty
^ permalink raw reply related [flat|nested] 18+ messages in thread* Re: The rest of my proc cleanup.
2006-08-15 18:00 The rest of my proc cleanup Eric W. Biederman
` (6 preceding siblings ...)
2006-08-15 18:05 ` [PATCH 7/7] proc: Merge proc_tid_attr and proc_tgid_attr Eric W. Biederman
@ 2006-08-15 18:33 ` Paul Jackson
7 siblings, 0 replies; 18+ messages in thread
From: Paul Jackson @ 2006-08-15 18:33 UTC (permalink / raw)
To: Eric W. Biederman; +Cc: akpm, linux-kernel, containers
These patches seem ok to me:
1) in their trivial impact on cpusets, and
2) as a good cleanup.
Perhaps others wiser (more seniority in the school of
hard knocks) will see problems with them. I don't.
Thanks.
--
I won't rest till it's the best ...
Programmer, Linux Scalability
Paul Jackson <pj@sgi.com> 1.925.600.0401
^ permalink raw reply [flat|nested] 18+ messages in thread