]> git.karo-electronics.de Git - linux-beck.git/blobdiff - fs/proc/array.c
Merge branches 'x86-cleanups-for-linus' and 'x86-cpufeature-for-linus' of git://git...
[linux-beck.git] / fs / proc / array.c
index f9bd395b3473f6f1ca5f0697679d7d469e9fdb7c..c1c207c36caefeb1fcbc8d782504cfcbf1b616d8 100644 (file)
@@ -81,6 +81,7 @@
 #include <linux/pid_namespace.h>
 #include <linux/ptrace.h>
 #include <linux/tracehook.h>
+#include <linux/user_namespace.h>
 
 #include <asm/pgtable.h>
 #include <asm/processor.h>
@@ -161,6 +162,7 @@ static inline const char *get_task_state(struct task_struct *tsk)
 static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
                                struct pid *pid, struct task_struct *p)
 {
+       struct user_namespace *user_ns = current_user_ns();
        struct group_info *group_info;
        int g;
        struct fdtable *fdt = NULL;
@@ -189,8 +191,14 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
                task_tgid_nr_ns(p, ns),
                pid_nr_ns(pid, ns),
                ppid, tpid,
-               cred->uid, cred->euid, cred->suid, cred->fsuid,
-               cred->gid, cred->egid, cred->sgid, cred->fsgid);
+               from_kuid_munged(user_ns, cred->uid),
+               from_kuid_munged(user_ns, cred->euid),
+               from_kuid_munged(user_ns, cred->suid),
+               from_kuid_munged(user_ns, cred->fsuid),
+               from_kgid_munged(user_ns, cred->gid),
+               from_kgid_munged(user_ns, cred->egid),
+               from_kgid_munged(user_ns, cred->sgid),
+               from_kgid_munged(user_ns, cred->fsgid));
 
        task_lock(p);
        if (p->files)
@@ -205,7 +213,8 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
        task_unlock(p);
 
        for (g = 0; g < min(group_info->ngroups, NGROUPS_SMALL); g++)
-               seq_printf(m, "%d ", GROUP_AT(group_info, g));
+               seq_printf(m, "%d ",
+                          from_kgid_munged(user_ns, GROUP_AT(group_info, g)));
        put_cred(cred);
 
        seq_putc(m, '\n');
@@ -361,7 +370,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
                        struct pid *pid, struct task_struct *task, int whole)
 {
        unsigned long vsize, eip, esp, wchan = ~0UL;
-       long priority, nice;
+       int priority, nice;
        int tty_pgrp = -1, tty_nr = 0;
        sigset_t sigign, sigcatch;
        char state;
@@ -483,7 +492,7 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
        seq_put_decimal_ull(m, ' ', 0);
        seq_put_decimal_ull(m, ' ', start_time);
        seq_put_decimal_ull(m, ' ', vsize);
-       seq_put_decimal_ll(m, ' ', mm ? get_mm_rss(mm) : 0);
+       seq_put_decimal_ull(m, ' ', mm ? get_mm_rss(mm) : 0);
        seq_put_decimal_ull(m, ' ', rsslim);
        seq_put_decimal_ull(m, ' ', mm ? (permitted ? mm->start_code : 1) : 0);
        seq_put_decimal_ull(m, ' ', mm ? (permitted ? mm->end_code : 1) : 0);
@@ -508,9 +517,23 @@ static int do_task_stat(struct seq_file *m, struct pid_namespace *ns,
        seq_put_decimal_ull(m, ' ', delayacct_blkio_ticks(task));
        seq_put_decimal_ull(m, ' ', cputime_to_clock_t(gtime));
        seq_put_decimal_ll(m, ' ', cputime_to_clock_t(cgtime));
-       seq_put_decimal_ull(m, ' ', (mm && permitted) ? mm->start_data : 0);
-       seq_put_decimal_ull(m, ' ', (mm && permitted) ? mm->end_data : 0);
-       seq_put_decimal_ull(m, ' ', (mm && permitted) ? mm->start_brk : 0);
+
+       if (mm && permitted) {
+               seq_put_decimal_ull(m, ' ', mm->start_data);
+               seq_put_decimal_ull(m, ' ', mm->end_data);
+               seq_put_decimal_ull(m, ' ', mm->start_brk);
+               seq_put_decimal_ull(m, ' ', mm->arg_start);
+               seq_put_decimal_ull(m, ' ', mm->arg_end);
+               seq_put_decimal_ull(m, ' ', mm->env_start);
+               seq_put_decimal_ull(m, ' ', mm->env_end);
+       } else
+               seq_printf(m, " 0 0 0 0 0 0 0");
+
+       if (permitted)
+               seq_put_decimal_ll(m, ' ', task->exit_code);
+       else
+               seq_put_decimal_ll(m, ' ', 0);
+
        seq_putc(m, '\n');
        if (mm)
                mmput(mm);
@@ -556,3 +579,126 @@ int proc_pid_statm(struct seq_file *m, struct pid_namespace *ns,
 
        return 0;
 }
+
+#ifdef CONFIG_CHECKPOINT_RESTORE
+static struct pid *
+get_children_pid(struct inode *inode, struct pid *pid_prev, loff_t pos)
+{
+       struct task_struct *start, *task;
+       struct pid *pid = NULL;
+
+       read_lock(&tasklist_lock);
+
+       start = pid_task(proc_pid(inode), PIDTYPE_PID);
+       if (!start)
+               goto out;
+
+       /*
+        * Lets try to continue searching first, this gives
+        * us significant speedup on children-rich processes.
+        */
+       if (pid_prev) {
+               task = pid_task(pid_prev, PIDTYPE_PID);
+               if (task && task->real_parent == start &&
+                   !(list_empty(&task->sibling))) {
+                       if (list_is_last(&task->sibling, &start->children))
+                               goto out;
+                       task = list_first_entry(&task->sibling,
+                                               struct task_struct, sibling);
+                       pid = get_pid(task_pid(task));
+                       goto out;
+               }
+       }
+
+       /*
+        * Slow search case.
+        *
+        * We might miss some children here if children
+        * are exited while we were not holding the lock,
+        * but it was never promised to be accurate that
+        * much.
+        *
+        * "Just suppose that the parent sleeps, but N children
+        *  exit after we printed their tids. Now the slow paths
+        *  skips N extra children, we miss N tasks." (c)
+        *
+        * So one need to stop or freeze the leader and all
+        * its children to get a precise result.
+        */
+       list_for_each_entry(task, &start->children, sibling) {
+               if (pos-- == 0) {
+                       pid = get_pid(task_pid(task));
+                       break;
+               }
+       }
+
+out:
+       read_unlock(&tasklist_lock);
+       return pid;
+}
+
+static int children_seq_show(struct seq_file *seq, void *v)
+{
+       struct inode *inode = seq->private;
+       pid_t pid;
+
+       pid = pid_nr_ns(v, inode->i_sb->s_fs_info);
+       return seq_printf(seq, "%d ", pid);
+}
+
+static void *children_seq_start(struct seq_file *seq, loff_t *pos)
+{
+       return get_children_pid(seq->private, NULL, *pos);
+}
+
+static void *children_seq_next(struct seq_file *seq, void *v, loff_t *pos)
+{
+       struct pid *pid;
+
+       pid = get_children_pid(seq->private, v, *pos + 1);
+       put_pid(v);
+
+       ++*pos;
+       return pid;
+}
+
+static void children_seq_stop(struct seq_file *seq, void *v)
+{
+       put_pid(v);
+}
+
+static const struct seq_operations children_seq_ops = {
+       .start  = children_seq_start,
+       .next   = children_seq_next,
+       .stop   = children_seq_stop,
+       .show   = children_seq_show,
+};
+
+static int children_seq_open(struct inode *inode, struct file *file)
+{
+       struct seq_file *m;
+       int ret;
+
+       ret = seq_open(file, &children_seq_ops);
+       if (ret)
+               return ret;
+
+       m = file->private_data;
+       m->private = inode;
+
+       return ret;
+}
+
+int children_seq_release(struct inode *inode, struct file *file)
+{
+       seq_release(inode, file);
+       return 0;
+}
+
+const struct file_operations proc_tid_children_operations = {
+       .open    = children_seq_open,
+       .read    = seq_read,
+       .llseek  = seq_lseek,
+       .release = children_seq_release,
+};
+#endif /* CONFIG_CHECKPOINT_RESTORE */