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/fs_struct.h>
   6#include <linux/mount.h>
   7#include <linux/ptrace.h>
   8#include <linux/seq_file.h>
   9#include "internal.h"
  10
  11/*
  12 * Logic: we've got two memory sums for each process, "shared", and
  13 * "non-shared". Shared memory may get counted more than once, for
  14 * each process that owns it. Non-shared memory is counted
  15 * accurately.
  16 */
  17void task_mem(struct seq_file *m, struct mm_struct *mm)
  18{
  19        struct vm_area_struct *vma;
  20        struct vm_region *region;
  21        struct rb_node *p;
  22        unsigned long bytes = 0, sbytes = 0, slack = 0, size;
  23        
  24        down_read(&mm->mmap_sem);
  25        for (p = rb_first(&mm->mm_rb); p; p = rb_next(p)) {
  26                vma = rb_entry(p, struct vm_area_struct, vm_rb);
  27
  28                bytes += kobjsize(vma);
  29
  30                region = vma->vm_region;
  31                if (region) {
  32                        size = kobjsize(region);
  33                        size += region->vm_end - region->vm_start;
  34                } else {
  35                        size = vma->vm_end - vma->vm_start;
  36                }
  37
  38                if (atomic_read(&mm->mm_count) > 1 ||
  39                    vma->vm_flags & VM_MAYSHARE) {
  40                        sbytes += size;
  41                } else {
  42                        bytes += size;
  43                        if (region)
  44                                slack = region->vm_end - vma->vm_end;
  45                }
  46        }
  47
  48        if (atomic_read(&mm->mm_count) > 1)
  49                sbytes += kobjsize(mm);
  50        else
  51                bytes += kobjsize(mm);
  52        
  53        if (current->fs && current->fs->users > 1)
  54                sbytes += kobjsize(current->fs);
  55        else
  56                bytes += kobjsize(current->fs);
  57
  58        if (current->files && atomic_read(&current->files->count) > 1)
  59                sbytes += kobjsize(current->files);
  60        else
  61                bytes += kobjsize(current->files);
  62
  63        if (current->sighand && atomic_read(&current->sighand->count) > 1)
  64                sbytes += kobjsize(current->sighand);
  65        else
  66                bytes += kobjsize(current->sighand);
  67
  68        bytes += kobjsize(current); /* includes kernel stack */
  69
  70        seq_printf(m,
  71                "Mem:\t%8lu bytes\n"
  72                "Slack:\t%8lu bytes\n"
  73                "Shared:\t%8lu bytes\n",
  74                bytes, slack, sbytes);
  75
  76        up_read(&mm->mmap_sem);
  77}
  78
  79unsigned long task_vsize(struct mm_struct *mm)
  80{
  81        struct vm_area_struct *vma;
  82        struct rb_node *p;
  83        unsigned long vsize = 0;
  84
  85        down_read(&mm->mmap_sem);
  86        for (p = rb_first(&mm->mm_rb); p; p = rb_next(p)) {
  87                vma = rb_entry(p, struct vm_area_struct, vm_rb);
  88                vsize += vma->vm_end - vma->vm_start;
  89        }
  90        up_read(&mm->mmap_sem);
  91        return vsize;
  92}
  93
  94int task_statm(struct mm_struct *mm, int *shared, int *text,
  95               int *data, int *resident)
  96{
  97        struct vm_area_struct *vma;
  98        struct vm_region *region;
  99        struct rb_node *p;
 100        int size = kobjsize(mm);
 101
 102        down_read(&mm->mmap_sem);
 103        for (p = rb_first(&mm->mm_rb); p; p = rb_next(p)) {
 104                vma = rb_entry(p, struct vm_area_struct, vm_rb);
 105                size += kobjsize(vma);
 106                region = vma->vm_region;
 107                if (region) {
 108                        size += kobjsize(region);
 109                        size += region->vm_end - region->vm_start;
 110                }
 111        }
 112
 113        size += (*text = mm->end_code - mm->start_code);
 114        size += (*data = mm->start_stack - mm->start_data);
 115        up_read(&mm->mmap_sem);
 116        *resident = size;
 117        return size;
 118}
 119
 120/*
 121 * display a single VMA to a sequenced file
 122 */
 123static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma)
 124{
 125        unsigned long ino = 0;
 126        struct file *file;
 127        dev_t dev = 0;
 128        int flags, len;
 129        unsigned long long pgoff = 0;
 130
 131        flags = vma->vm_flags;
 132        file = vma->vm_file;
 133
 134        if (file) {
 135                struct inode *inode = vma->vm_file->f_path.dentry->d_inode;
 136                dev = inode->i_sb->s_dev;
 137                ino = inode->i_ino;
 138                pgoff = (loff_t)vma->vm_pgoff << PAGE_SHIFT;
 139        }
 140
 141        seq_printf(m,
 142                   "%08lx-%08lx %c%c%c%c %08llx %02x:%02x %lu %n",
 143                   vma->vm_start,
 144                   vma->vm_end,
 145                   flags & VM_READ ? 'r' : '-',
 146                   flags & VM_WRITE ? 'w' : '-',
 147                   flags & VM_EXEC ? 'x' : '-',
 148                   flags & VM_MAYSHARE ? flags & VM_SHARED ? 'S' : 's' : 'p',
 149                   pgoff,
 150                   MAJOR(dev), MINOR(dev), ino, &len);
 151
 152        if (file) {
 153                len = 25 + sizeof(void *) * 6 - len;
 154                if (len < 1)
 155                        len = 1;
 156                seq_printf(m, "%*c", len, ' ');
 157                seq_path(m, &file->f_path, "");
 158        }
 159
 160        seq_putc(m, '\n');
 161        return 0;
 162}
 163
 164/*
 165 * display mapping lines for a particular process's /proc/pid/maps
 166 */
 167static int show_map(struct seq_file *m, void *_p)
 168{
 169        struct rb_node *p = _p;
 170
 171        return nommu_vma_show(m, rb_entry(p, struct vm_area_struct, vm_rb));
 172}
 173
 174static void *m_start(struct seq_file *m, loff_t *pos)
 175{
 176        struct proc_maps_private *priv = m->private;
 177        struct mm_struct *mm;
 178        struct rb_node *p;
 179        loff_t n = *pos;
 180
 181        /* pin the task and mm whilst we play with them */
 182        priv->task = get_pid_task(priv->pid, PIDTYPE_PID);
 183        if (!priv->task)
 184                return NULL;
 185
 186        mm = mm_for_maps(priv->task);
 187        if (!mm) {
 188                put_task_struct(priv->task);
 189                priv->task = NULL;
 190                return NULL;
 191        }
 192        down_read(&mm->mmap_sem);
 193
 194        /* start from the Nth VMA */
 195        for (p = rb_first(&mm->mm_rb); p; p = rb_next(p))
 196                if (n-- == 0)
 197                        return p;
 198        return NULL;
 199}
 200
 201static void m_stop(struct seq_file *m, void *_vml)
 202{
 203        struct proc_maps_private *priv = m->private;
 204
 205        if (priv->task) {
 206                struct mm_struct *mm = priv->task->mm;
 207                up_read(&mm->mmap_sem);
 208                mmput(mm);
 209                put_task_struct(priv->task);
 210        }
 211}
 212
 213static void *m_next(struct seq_file *m, void *_p, loff_t *pos)
 214{
 215        struct rb_node *p = _p;
 216
 217        (*pos)++;
 218        return p ? rb_next(p) : NULL;
 219}
 220
 221static const struct seq_operations proc_pid_maps_ops = {
 222        .start  = m_start,
 223        .next   = m_next,
 224        .stop   = m_stop,
 225        .show   = show_map
 226};
 227
 228static int maps_open(struct inode *inode, struct file *file)
 229{
 230        struct proc_maps_private *priv;
 231        int ret = -ENOMEM;
 232
 233        priv = kzalloc(sizeof(*priv), GFP_KERNEL);
 234        if (priv) {
 235                priv->pid = proc_pid(inode);
 236                ret = seq_open(file, &proc_pid_maps_ops);
 237                if (!ret) {
 238                        struct seq_file *m = file->private_data;
 239                        m->private = priv;
 240                } else {
 241                        kfree(priv);
 242                }
 243        }
 244        return ret;
 245}
 246
 247const struct file_operations proc_maps_operations = {
 248        .open           = maps_open,
 249        .read           = seq_read,
 250        .llseek         = seq_lseek,
 251        .release        = seq_release_private,
 252};
 253
 254
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.