]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - fs/proc/base.c
Merge branches 'pm-core', 'pm-qos', 'pm-domains' and 'pm-opp'
[linux.git] / fs / proc / base.c
index ca651ac00660889a86fcd5c27d4a29aa709d5a53..b1f7d30e96c27aa5d3e2a9abe0052e123087a448 100644 (file)
@@ -47,7 +47,7 @@
  *  Overall revision about smaps.
  */
 
-#include <asm/uaccess.h>
+#include <linux/uaccess.h>
 
 #include <linux/errno.h>
 #include <linux/time.h>
  *     in /proc for a task before it execs a suid executable.
  */
 
+static u8 nlink_tid;
+static u8 nlink_tgid;
+
 struct pid_entry {
        const char *name;
-       int len;
+       unsigned int len;
        umode_t mode;
        const struct inode_operations *iop;
        const struct file_operations *fop;
@@ -139,13 +142,13 @@ struct pid_entry {
  * Count the number of hardlinks for the pid_entry table, excluding the .
  * and .. links.
  */
-static unsigned int pid_entry_count_dirs(const struct pid_entry *entries,
+static unsigned int __init pid_entry_nlink(const struct pid_entry *entries,
        unsigned int n)
 {
        unsigned int i;
        unsigned int count;
 
-       count = 0;
+       count = 2;
        for (i = 0; i < n; ++i) {
                if (S_ISDIR(entries[i].mode))
                        ++count;
@@ -1243,7 +1246,7 @@ static const struct file_operations proc_oom_score_adj_operations = {
 };
 
 #ifdef CONFIG_AUDITSYSCALL
-#define TMPBUFLEN 21
+#define TMPBUFLEN 11
 static ssize_t proc_loginuid_read(struct file * file, char __user * buf,
                                  size_t count, loff_t *ppos)
 {
@@ -1664,7 +1667,8 @@ const struct inode_operations proc_pid_link_inode_operations = {
 
 /* building an inode */
 
-struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *task)
+struct inode *proc_pid_make_inode(struct super_block * sb,
+                                 struct task_struct *task, umode_t mode)
 {
        struct inode * inode;
        struct proc_inode *ei;
@@ -1678,6 +1682,7 @@ struct inode *proc_pid_make_inode(struct super_block * sb, struct task_struct *t
 
        /* Common stuff */
        ei = PROC_I(inode);
+       inode->i_mode = mode;
        inode->i_ino = get_next_ino();
        inode->i_mtime = inode->i_atime = inode->i_ctime = current_time(inode);
        inode->i_op = &proc_def_inode_operations;
@@ -1967,7 +1972,7 @@ static int map_files_get_link(struct dentry *dentry, struct path *path)
 
 struct map_files_info {
        fmode_t         mode;
-       unsigned long   len;
+       unsigned int    len;
        unsigned char   name[4*sizeof(long)+2]; /* max: %lx-%lx\0 */
 };
 
@@ -2004,7 +2009,9 @@ proc_map_files_instantiate(struct inode *dir, struct dentry *dentry,
        struct proc_inode *ei;
        struct inode *inode;
 
-       inode = proc_pid_make_inode(dir->i_sb, task);
+       inode = proc_pid_make_inode(dir->i_sb, task, S_IFLNK |
+                                   ((mode & FMODE_READ ) ? S_IRUSR : 0) |
+                                   ((mode & FMODE_WRITE) ? S_IWUSR : 0));
        if (!inode)
                return -ENOENT;
 
@@ -2013,12 +2020,6 @@ proc_map_files_instantiate(struct inode *dir, struct dentry *dentry,
 
        inode->i_op = &proc_map_files_link_inode_operations;
        inode->i_size = 64;
-       inode->i_mode = S_IFLNK;
-
-       if (mode & FMODE_READ)
-               inode->i_mode |= S_IRUSR;
-       if (mode & FMODE_WRITE)
-               inode->i_mode |= S_IWUSR;
 
        d_set_d_op(dentry, &tid_map_files_dentry_operations);
        d_add(dentry, inode);
@@ -2178,7 +2179,7 @@ static const struct file_operations proc_map_files_operations = {
        .llseek         = generic_file_llseek,
 };
 
-#ifdef CONFIG_CHECKPOINT_RESTORE
+#if defined(CONFIG_CHECKPOINT_RESTORE) && defined(CONFIG_POSIX_TIMERS)
 struct timers_private {
        struct pid *pid;
        struct task_struct *task;
@@ -2372,12 +2373,11 @@ static int proc_pident_instantiate(struct inode *dir,
        struct inode *inode;
        struct proc_inode *ei;
 
-       inode = proc_pid_make_inode(dir->i_sb, task);
+       inode = proc_pid_make_inode(dir->i_sb, task, p->mode);
        if (!inode)
                goto out;
 
        ei = PROC_I(inode);
-       inode->i_mode = p->mode;
        if (S_ISDIR(inode->i_mode))
                set_nlink(inode, 2);    /* Use getattr to fix if necessary */
        if (p->iop)
@@ -2412,14 +2412,14 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
         * Yes, it does not scale. And it should not. Don't add
         * new entries into /proc/<tgid>/ without very good reasons.
         */
-       last = &ents[nents - 1];
-       for (p = ents; p <= last; p++) {
+       last = &ents[nents];
+       for (p = ents; p < last; p++) {
                if (p->len != dentry->d_name.len)
                        continue;
                if (!memcmp(dentry->d_name.name, p->name, p->len))
                        break;
        }
-       if (p > last)
+       if (p >= last)
                goto out;
 
        error = proc_pident_instantiate(dir, dentry, task, p);
@@ -2444,7 +2444,7 @@ static int proc_pident_readdir(struct file *file, struct dir_context *ctx,
        if (ctx->pos >= nents + 2)
                goto out;
 
-       for (p = ents + (ctx->pos - 2); p <= ents + nents - 1; p++) {
+       for (p = ents + (ctx->pos - 2); p < ents + nents; p++) {
                if (!proc_fill_cache(file, ctx, p->name, p->len,
                                proc_pident_instantiate, task, p))
                        break;
@@ -2936,7 +2936,7 @@ static const struct pid_entry tgid_base_stuff[] = {
        REG("projid_map", S_IRUGO|S_IWUSR, proc_projid_map_operations),
        REG("setgroups",  S_IRUGO|S_IWUSR, proc_setgroups_operations),
 #endif
-#ifdef CONFIG_CHECKPOINT_RESTORE
+#if defined(CONFIG_CHECKPOINT_RESTORE) && defined(CONFIG_POSIX_TIMERS)
        REG("timers",     S_IRUGO, proc_timers_operations),
 #endif
        REG("timerslack_ns", S_IRUGO|S_IWUGO, proc_pid_set_timerslack_ns_operations),
@@ -3059,17 +3059,15 @@ static int proc_pid_instantiate(struct inode *dir,
 {
        struct inode *inode;
 
-       inode = proc_pid_make_inode(dir->i_sb, task);
+       inode = proc_pid_make_inode(dir->i_sb, task, S_IFDIR | S_IRUGO | S_IXUGO);
        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;
 
-       set_nlink(inode, 2 + pid_entry_count_dirs(tgid_base_stuff,
-                                                 ARRAY_SIZE(tgid_base_stuff)));
+       set_nlink(inode, nlink_tgid);
 
        d_set_d_op(dentry, &pid_dentry_operations);
 
@@ -3181,6 +3179,8 @@ int proc_pid_readdir(struct file *file, struct dir_context *ctx)
             iter.tgid += 1, iter = next_tgid(ns, iter)) {
                char name[PROC_NUMBUF];
                int len;
+
+               cond_resched();
                if (!has_pid_permissions(ns, iter.task, 2))
                        continue;
 
@@ -3352,17 +3352,15 @@ static int proc_task_instantiate(struct inode *dir,
        struct dentry *dentry, struct task_struct *task, const void *ptr)
 {
        struct inode *inode;
-       inode = proc_pid_make_inode(dir->i_sb, task);
+       inode = proc_pid_make_inode(dir->i_sb, task, S_IFDIR | S_IRUGO | S_IXUGO);
 
        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;
 
-       set_nlink(inode, 2 + pid_entry_count_dirs(tid_base_stuff,
-                                                 ARRAY_SIZE(tid_base_stuff)));
+       set_nlink(inode, nlink_tid);
 
        d_set_d_op(dentry, &pid_dentry_operations);
 
@@ -3552,3 +3550,9 @@ static const struct file_operations proc_task_operations = {
        .iterate_shared = proc_task_readdir,
        .llseek         = generic_file_llseek,
 };
+
+void __init set_proc_pid_nlink(void)
+{
+       nlink_tid = pid_entry_nlink(tid_base_stuff, ARRAY_SIZE(tid_base_stuff));
+       nlink_tgid = pid_entry_nlink(tgid_base_stuff, ARRAY_SIZE(tgid_base_stuff));
+}