linux/fs/proc/task_nommu.c
<<
>>
Prefs
   1
   2#include <linux/mm.h>
   3#include <linux/file.h>
   4#include <linux/fdtable.h>
   5#include <linux/mount.h>
   6#include <linux/ptrace.h>
   7#include <linux/seq_file.h>
   8#include "internal.h"
   9
  10/*
  11 * Logic: we've got two memory sums for each process, "shared", and
  12 * "non-shared". Shared memory may get counted more then once, for
  13 * each process that owns it. Non-shared memory is counted
  14 * accurately.
  15 */
  16void task_mem(struct seq_file *m, struct mm_struct *mm)
  17{
  18        struct vm_list_struct *vml;
  19        unsigned long bytes = 0, sbytes = 0, slack = 0;
  20        
  21        down_read(&mm->mmap_sem);
  22        for (vml = mm->context.vmlist; vml; vml = vml->next) {
  23                if (!vml->vma)
  24                        continue;
  25
  26                bytes += kobjsize(vml);
  27                if (atomic_read(&mm->mm_count) > 1 ||
  28                    atomic_read(&vml->vma->vm_usage) > 1
  29                    ) {
  30                        sbytes += kobjsize((void *) vml->vma->vm_start);
  31                        sbytes += kobjsize(vml->vma);
  32                } else {
  33                        bytes += kobjsize((void *) vml->vma->vm_start);
  34                        bytes += kobjsize(vml->vma);
  35                        slack += kobjsize((void *) vml->vma->vm_start) -
  36                                (vml->vma->vm_end - vml->vma->vm_start);
  37                }
  38        }
  39
  40        if (atomic_read(&mm->mm_count) > 1)
  41                sbytes += kobjsize(mm);
  42        else
  43                bytes += kobjsize(mm);
  44        
  45        if (current->fs && atomic_read(&current->fs->count) > 1)
  46                sbytes += kobjsize(current->fs);
  47        else
  48                bytes += kobjsize(current->fs);
  49
  50        if (current->files && atomic_read(&current->files->count) > 1)
  51                sbytes += kobjsize(current->files);
  52        else
  53                bytes += kobjsize(current->files);
  54
  55        if (current->sighand && atomic_read(&current->sighand->count) > 1)
  56                sbytes += kobjsize(current->sighand);
  57        else
  58                bytes += kobjsize(current->sighand);
  59
  60        bytes += kobjsize(current); /* includes kernel stack */
  61
  62        seq_printf(m,
  63                "Mem:\t%8lu bytes\n"
  64                "Slack:\t%8lu bytes\n"
  65                "Shared:\t%8lu bytes\n",
  66                bytes, slack, sbytes);
  67
  68        up_read(&mm->mmap_sem);
  69}
  70
  71unsigned long task_vsize(struct mm_struct *mm)
  72{
  73        struct vm_list_struct *tbp;
  74        unsigned long vsize = 0;
  75
  76        down_read(&mm->mmap_sem);
  77        for (tbp = mm->context.vmlist; tbp; tbp = tbp->next) {
  78                if (tbp->vma)
  79                        vsize += kobjsize((void *) tbp->vma->vm_start);
  80        }
  81        up_read(&mm->mmap_sem);
  82        return vsize;
  83}
  84
  85int task_statm(struct mm_struct *mm, int *shared, int *text,
  86               int *data, int *resident)
  87{
  88        struct vm_list_struct *tbp;
  89        int size = kobjsize(mm);
  90
  91        down_read(&mm->mmap_sem);
  92        for (tbp = mm->context.vmlist; tbp; tbp = tbp->next) {
  93                size += kobjsize(tbp);
  94                if (tbp->vma) {
  95                        size += kobjsize(tbp->vma);
  96                        size += kobjsize((void *) tbp->vma->vm_start);
  97                }
  98        }
  99
 100        size += (*text = mm->end_code - mm->start_code);
 101        size += (*data = mm->start_stack - mm->start_data);
 102        up_read(&mm->mmap_sem);
 103        *resident = size;
 104        return size;
 105}
 106
 107/*
 108 * display mapping lines for a particular process's /proc/pid/maps
 109 */
 110static int show_map(struct seq_file *m, void *_vml)
 111{
 112        struct vm_list_struct *vml = _vml;
 113
 114        return nommu_vma_show(m, vml->vma);
 115}
 116
 117static void *m_start(struct seq_file *m, loff_t *pos)
 118{
 119        struct proc_maps_private *priv = m->private;
 120        struct vm_list_struct *vml;
 121        struct mm_struct *mm;
 122        loff_t n = *pos;
 123
 124        /* pin the task and mm whilst we play with them */
 125        priv->task = get_pid_task(priv->pid, PIDTYPE_PID);
 126        if (!priv->task)
 127                return NULL;
 128
 129        mm = mm_for_maps(priv->task);
 130        if (!mm) {
 131                put_task_struct(priv->task);
 132                priv->task = NULL;
 133                return NULL;
 134        }
 135
 136        /* start from the Nth VMA */
 137        for (vml = mm->context.vmlist; vml; vml = vml->next)
 138                if (n-- == 0)
 139                        return vml;
 140        return NULL;
 141}
 142
 143static void m_stop(struct seq_file *m, void *_vml)
 144{
 145        struct proc_maps_private *priv = m->private;
 146
 147        if (priv->task) {
 148                struct mm_struct *mm = priv->task->mm;
 149                up_read(&mm->mmap_sem);
 150                mmput(mm);
 151                put_task_struct(priv->task);
 152        }
 153}
 154
 155static void *m_next(struct seq_file *m, void *_vml, loff_t *pos)
 156{
 157        struct vm_list_struct *vml = _vml;
 158
 159        (*pos)++;
 160        return vml ? vml->next : NULL;
 161}
 162
 163static const struct seq_operations proc_pid_maps_ops = {
 164        .start  = m_start,
 165        .next   = m_next,
 166        .stop   = m_stop,
 167        .show   = show_map
 168};
 169
 170static int maps_open(struct inode *inode, struct file *file)
 171{
 172        struct proc_maps_private *priv;
 173        int ret = -ENOMEM;
 174
 175        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 176        if (priv) {
 177                priv->pid = proc_pid(inode);
 178                ret = seq_open(file, &proc_pid_maps_ops);
 179                if (!ret) {
 180                        struct seq_file *m = file->private_data;
 181                        m->private = priv;
 182                } else {
 183                        kfree(priv);
 184                }
 185        }
 186        return ret;
 187}
 188
 189const struct file_operations proc_maps_operations = {
 190        .open           = maps_open,
 191        .read           = seq_read,
 192        .llseek         = seq_lseek,
 193        .release        = seq_release_private,
 194};
 195
 196
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.