e69eac7d9a1a4c704b00348336163a84267eee54
[linux-flexiantxendom0-3.2.10.git] / fs / proc / task_mmu.c
1 #include <linux/mm.h>
2 #include <linux/hugetlb.h>
3 #include <linux/seq_file.h>
4 #include <asm/elf.h>
5 #include <asm/uaccess.h>
6
7 char *task_mem(struct mm_struct *mm, char *buffer)
8 {
9         unsigned long data = 0, stack = 0, exec = 0, lib = 0;
10         struct vm_area_struct *vma;
11
12         down_read(&mm->mmap_sem);
13         for (vma = mm->mmap; vma; vma = vma->vm_next) {
14                 unsigned long len = (vma->vm_end - vma->vm_start) >> 10;
15                 if (!vma->vm_file) {
16                         data += len;
17                         if (vma->vm_flags & VM_GROWSDOWN)
18                                 stack += len;
19                         continue;
20                 }
21                 if (vma->vm_flags & VM_WRITE)
22                         continue;
23                 if (vma->vm_flags & VM_EXEC) {
24                         exec += len;
25                         if (vma->vm_flags & VM_EXECUTABLE)
26                                 continue;
27                         lib += len;
28                 }
29         }
30         buffer += sprintf(buffer,
31                 "VmSize:\t%8lu kB\n"
32                 "VmLck:\t%8lu kB\n"
33                 "VmRSS:\t%8lu kB\n"
34                 "VmData:\t%8lu kB\n"
35                 "VmStk:\t%8lu kB\n"
36                 "VmExe:\t%8lu kB\n"
37                 "VmLib:\t%8lu kB\n",
38                 mm->total_vm << (PAGE_SHIFT-10),
39                 mm->locked_vm << (PAGE_SHIFT-10),
40                 mm->rss << (PAGE_SHIFT-10),
41                 data - stack, stack,
42                 exec - lib, lib);
43         up_read(&mm->mmap_sem);
44         return buffer;
45 }
46
47 unsigned long task_vsize(struct mm_struct *mm)
48 {
49         return PAGE_SIZE * mm->total_vm;
50 }
51
52 int task_statm(struct mm_struct *mm, int *shared, int *text,
53                int *data, int *resident)
54 {
55         struct vm_area_struct *vma;
56         int size = 0;
57
58         *resident = mm->rss;
59         for (vma = mm->mmap; vma; vma = vma->vm_next) {
60                 int pages = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT;
61
62                 size += pages;
63                 if (is_vm_hugetlb_page(vma)) {
64                         if (!(vma->vm_flags & VM_DONTCOPY))
65                                 *shared += pages;
66                         continue;
67                 }
68                 if (vma->vm_flags & VM_SHARED || !list_empty(&vma->shared))
69                         *shared += pages;
70                 if (vma->vm_flags & VM_EXECUTABLE)
71                         *text += pages;
72                 else
73                         *data += pages;
74         }
75
76         return size;
77 }
78
79 #ifdef AT_SYSINFO_EHDR
80
81 static struct vm_area_struct gate_vmarea = {
82         /* Do _not_ mark this area as readable, cuz not the entire range may be readable
83            (e.g., due to execute-only pages or holes) and the tools that read
84            /proc/PID/maps should read the interesting bits from the gate-DSO file
85            instead.  */
86         .vm_start = FIXADDR_USER_START,
87         .vm_end = FIXADDR_USER_END
88 };
89
90 # define gate_map()     &gate_vmarea
91 #else
92 # define gate_map()     NULL
93 #endif
94
95 static int show_map(struct seq_file *m, void *v)
96 {
97         struct vm_area_struct *map = v;
98         struct file *file = map->vm_file;
99         int flags = map->vm_flags;
100         unsigned long ino = 0;
101         dev_t dev = 0;
102         int len;
103
104         if (file) {
105                 struct inode *inode = map->vm_file->f_dentry->d_inode;
106                 dev = inode->i_sb->s_dev;
107                 ino = inode->i_ino;
108         }
109
110         seq_printf(m, "%08lx-%08lx %c%c%c%c %08lx %02x:%02x %lu %n",
111                         map->vm_start,
112                         map->vm_end,
113                         flags & VM_READ ? 'r' : '-',
114                         flags & VM_WRITE ? 'w' : '-',
115                         flags & VM_EXEC ? 'x' : '-',
116                         flags & VM_MAYSHARE ? 's' : 'p',
117                         map->vm_pgoff << PAGE_SHIFT,
118                         MAJOR(dev), MINOR(dev), ino, &len);
119
120         if (map->vm_file) {
121                 len = 25 + sizeof(void*) * 6 - len;
122                 if (len < 1)
123                         len = 1;
124                 seq_printf(m, "%*c", len, ' ');
125                 seq_path(m, file->f_vfsmnt, file->f_dentry, " \t\n\\");
126         }
127         seq_putc(m, '\n');
128         return 0;
129 }
130
131 static void *m_start(struct seq_file *m, loff_t *pos)
132 {
133         struct task_struct *task = m->private;
134         struct mm_struct *mm = get_task_mm(task);
135         struct vm_area_struct * map;
136         loff_t l = *pos;
137
138         if (!mm)
139                 return NULL;
140
141         down_read(&mm->mmap_sem);
142         map = mm->mmap;
143         while (l-- && map)
144                 map = map->vm_next;
145         if (!map) {
146                 up_read(&mm->mmap_sem);
147                 mmput(mm);
148                 if (l == -1)
149                         map = gate_map();
150         }
151         return map;
152 }
153
154 static void m_stop(struct seq_file *m, void *v)
155 {
156         struct vm_area_struct *map = v;
157         if (map && map != gate_map()) {
158                 struct mm_struct *mm = map->vm_mm;
159                 up_read(&mm->mmap_sem);
160                 mmput(mm);
161         }
162 }
163
164 static void *m_next(struct seq_file *m, void *v, loff_t *pos)
165 {
166         struct vm_area_struct *map = v;
167         (*pos)++;
168         if (map->vm_next)
169                 return map->vm_next;
170         m_stop(m, v);
171         if (map != gate_map())
172                 return gate_map();
173         return NULL;
174 }
175
176 struct seq_operations proc_pid_maps_op = {
177         .start  = m_start,
178         .next   = m_next,
179         .stop   = m_stop,
180         .show   = show_map
181 };