procfs: mark thread stack correctly in proc/<pid>/maps
[cascardo/linux.git] / fs / proc / task_mmu.c
index c7e3a16..9694cc2 100644 (file)
@@ -209,16 +209,20 @@ static int do_maps_open(struct inode *inode, struct file *file,
        return ret;
 }
 
-static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
+static void
+show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid)
 {
        struct mm_struct *mm = vma->vm_mm;
        struct file *file = vma->vm_file;
+       struct proc_maps_private *priv = m->private;
+       struct task_struct *task = priv->task;
        vm_flags_t flags = vma->vm_flags;
        unsigned long ino = 0;
        unsigned long long pgoff = 0;
        unsigned long start, end;
        dev_t dev = 0;
        int len;
+       const char *name = NULL;
 
        if (file) {
                struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
@@ -252,36 +256,57 @@ static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma)
        if (file) {
                pad_len_spaces(m, len);
                seq_path(m, &file->f_path, "\n");
-       } else {
-               const char *name = arch_vma_name(vma);
-               if (!name) {
-                       if (mm) {
-                               if (vma->vm_start <= mm->brk &&
-                                               vma->vm_end >= mm->start_brk) {
-                                       name = "[heap]";
-                               } else if (vma->vm_start <= mm->start_stack &&
-                                          vma->vm_end >= mm->start_stack) {
-                                       name = "[stack]";
-                               }
+               goto done;
+       }
+
+       name = arch_vma_name(vma);
+       if (!name) {
+               pid_t tid;
+
+               if (!mm) {
+                       name = "[vdso]";
+                       goto done;
+               }
+
+               if (vma->vm_start <= mm->brk &&
+                   vma->vm_end >= mm->start_brk) {
+                       name = "[heap]";
+                       goto done;
+               }
+
+               tid = vm_is_stack(task, vma, is_pid);
+
+               if (tid != 0) {
+                       /*
+                        * Thread stack in /proc/PID/task/TID/maps or
+                        * the main process stack.
+                        */
+                       if (!is_pid || (vma->vm_start <= mm->start_stack &&
+                           vma->vm_end >= mm->start_stack)) {
+                               name = "[stack]";
                        } else {
-                               name = "[vdso]";
+                               /* Thread stack in /proc/PID/maps */
+                               pad_len_spaces(m, len);
+                               seq_printf(m, "[stack:%d]", tid);
                        }
                }
-               if (name) {
-                       pad_len_spaces(m, len);
-                       seq_puts(m, name);
-               }
+       }
+
+done:
+       if (name) {
+               pad_len_spaces(m, len);
+               seq_puts(m, name);
        }
        seq_putc(m, '\n');
 }
 
-static int show_map(struct seq_file *m, void *v)
+static int show_map(struct seq_file *m, void *v, int is_pid)
 {
        struct vm_area_struct *vma = v;
        struct proc_maps_private *priv = m->private;
        struct task_struct *task = priv->task;
 
-       show_map_vma(m, vma);
+       show_map_vma(m, vma, is_pid);
 
        if (m->count < m->size)  /* vma is copied successfully */
                m->version = (vma != get_gate_vma(task->mm))
@@ -289,20 +314,49 @@ static int show_map(struct seq_file *m, void *v)
        return 0;
 }
 
+static int show_pid_map(struct seq_file *m, void *v)
+{
+       return show_map(m, v, 1);
+}
+
+static int show_tid_map(struct seq_file *m, void *v)
+{
+       return show_map(m, v, 0);
+}
+
 static const struct seq_operations proc_pid_maps_op = {
        .start  = m_start,
        .next   = m_next,
        .stop   = m_stop,
-       .show   = show_map
+       .show   = show_pid_map
+};
+
+static const struct seq_operations proc_tid_maps_op = {
+       .start  = m_start,
+       .next   = m_next,
+       .stop   = m_stop,
+       .show   = show_tid_map
 };
 
-static int maps_open(struct inode *inode, struct file *file)
+static int pid_maps_open(struct inode *inode, struct file *file)
 {
        return do_maps_open(inode, file, &proc_pid_maps_op);
 }
 
-const struct file_operations proc_maps_operations = {
-       .open           = maps_open,
+static int tid_maps_open(struct inode *inode, struct file *file)
+{
+       return do_maps_open(inode, file, &proc_tid_maps_op);
+}
+
+const struct file_operations proc_pid_maps_operations = {
+       .open           = pid_maps_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release_private,
+};
+
+const struct file_operations proc_tid_maps_operations = {
+       .open           = tid_maps_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
        .release        = seq_release_private,
@@ -416,7 +470,7 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
        return 0;
 }
 
-static int show_smap(struct seq_file *m, void *v)
+static int show_smap(struct seq_file *m, void *v, int is_pid)
 {
        struct proc_maps_private *priv = m->private;
        struct task_struct *task = priv->task;
@@ -434,7 +488,7 @@ static int show_smap(struct seq_file *m, void *v)
        if (vma->vm_mm && !is_vm_hugetlb_page(vma))
                walk_page_range(vma->vm_start, vma->vm_end, &smaps_walk);
 
-       show_map_vma(m, vma);
+       show_map_vma(m, vma, is_pid);
 
        seq_printf(m,
                   "Size:           %8lu kB\n"
@@ -473,20 +527,49 @@ static int show_smap(struct seq_file *m, void *v)
        return 0;
 }
 
+static int show_pid_smap(struct seq_file *m, void *v)
+{
+       return show_smap(m, v, 1);
+}
+
+static int show_tid_smap(struct seq_file *m, void *v)
+{
+       return show_smap(m, v, 0);
+}
+
 static const struct seq_operations proc_pid_smaps_op = {
        .start  = m_start,
        .next   = m_next,
        .stop   = m_stop,
-       .show   = show_smap
+       .show   = show_pid_smap
+};
+
+static const struct seq_operations proc_tid_smaps_op = {
+       .start  = m_start,
+       .next   = m_next,
+       .stop   = m_stop,
+       .show   = show_tid_smap
 };
 
-static int smaps_open(struct inode *inode, struct file *file)
+static int pid_smaps_open(struct inode *inode, struct file *file)
 {
        return do_maps_open(inode, file, &proc_pid_smaps_op);
 }
 
-const struct file_operations proc_smaps_operations = {
-       .open           = smaps_open,
+static int tid_smaps_open(struct inode *inode, struct file *file)
+{
+       return do_maps_open(inode, file, &proc_tid_smaps_op);
+}
+
+const struct file_operations proc_pid_smaps_operations = {
+       .open           = pid_smaps_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release_private,
+};
+
+const struct file_operations proc_tid_smaps_operations = {
+       .open           = tid_smaps_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
        .release        = seq_release_private,
@@ -1039,7 +1122,7 @@ static int gather_hugetbl_stats(pte_t *pte, unsigned long hmask,
 /*
  * Display pages allocated per node and memory policy via /proc.
  */
-static int show_numa_map(struct seq_file *m, void *v)
+static int show_numa_map(struct seq_file *m, void *v, int is_pid)
 {
        struct numa_maps_private *numa_priv = m->private;
        struct proc_maps_private *proc_priv = &numa_priv->proc_maps;
@@ -1076,9 +1159,19 @@ static int show_numa_map(struct seq_file *m, void *v)
                seq_path(m, &file->f_path, "\n\t= ");
        } else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) {
                seq_printf(m, " heap");
-       } else if (vma->vm_start <= mm->start_stack &&
-                       vma->vm_end >= mm->start_stack) {
-               seq_printf(m, " stack");
+       } else {
+               pid_t tid = vm_is_stack(proc_priv->task, vma, is_pid);
+               if (tid != 0) {
+                       /*
+                        * Thread stack in /proc/PID/task/TID/maps or
+                        * the main process stack.
+                        */
+                       if (!is_pid || (vma->vm_start <= mm->start_stack &&
+                           vma->vm_end >= mm->start_stack))
+                               seq_printf(m, " stack");
+                       else
+                               seq_printf(m, " stack:%d", tid);
+               }
        }
 
        if (is_vm_hugetlb_page(vma))
@@ -1121,21 +1214,39 @@ out:
        return 0;
 }
 
+static int show_pid_numa_map(struct seq_file *m, void *v)
+{
+       return show_numa_map(m, v, 1);
+}
+
+static int show_tid_numa_map(struct seq_file *m, void *v)
+{
+       return show_numa_map(m, v, 0);
+}
+
 static const struct seq_operations proc_pid_numa_maps_op = {
-        .start  = m_start,
-        .next   = m_next,
-        .stop   = m_stop,
-        .show   = show_numa_map,
+       .start  = m_start,
+       .next   = m_next,
+       .stop   = m_stop,
+       .show   = show_pid_numa_map,
 };
 
-static int numa_maps_open(struct inode *inode, struct file *file)
+static const struct seq_operations proc_tid_numa_maps_op = {
+       .start  = m_start,
+       .next   = m_next,
+       .stop   = m_stop,
+       .show   = show_tid_numa_map,
+};
+
+static int numa_maps_open(struct inode *inode, struct file *file,
+                         const struct seq_operations *ops)
 {
        struct numa_maps_private *priv;
        int ret = -ENOMEM;
        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
        if (priv) {
                priv->proc_maps.pid = proc_pid(inode);
-               ret = seq_open(file, &proc_pid_numa_maps_op);
+               ret = seq_open(file, ops);
                if (!ret) {
                        struct seq_file *m = file->private_data;
                        m->private = priv;
@@ -1146,8 +1257,25 @@ static int numa_maps_open(struct inode *inode, struct file *file)
        return ret;
 }
 
-const struct file_operations proc_numa_maps_operations = {
-       .open           = numa_maps_open,
+static int pid_numa_maps_open(struct inode *inode, struct file *file)
+{
+       return numa_maps_open(inode, file, &proc_pid_numa_maps_op);
+}
+
+static int tid_numa_maps_open(struct inode *inode, struct file *file)
+{
+       return numa_maps_open(inode, file, &proc_tid_numa_maps_op);
+}
+
+const struct file_operations proc_pid_numa_maps_operations = {
+       .open           = pid_numa_maps_open,
+       .read           = seq_read,
+       .llseek         = seq_lseek,
+       .release        = seq_release_private,
+};
+
+const struct file_operations proc_tid_numa_maps_operations = {
+       .open           = tid_numa_maps_open,
        .read           = seq_read,
        .llseek         = seq_lseek,
        .release        = seq_release_private,