patch-2_6_7-vs1_9_1_12
[linux-2.6.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_file)
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 static int show_map(struct seq_file *m, void *v)
80 {
81         struct vm_area_struct *map = v;
82         struct file *file = map->vm_file;
83         int flags = map->vm_flags;
84         unsigned long ino = 0;
85         dev_t dev = 0;
86         int len;
87
88         if (file) {
89                 struct inode *inode = map->vm_file->f_dentry->d_inode;
90                 dev = inode->i_sb->s_dev;
91                 ino = inode->i_ino;
92         }
93
94         seq_printf(m, "%08lx-%08lx %c%c%c%c %08lx %02x:%02x %lu %n",
95                         map->vm_start,
96                         map->vm_end,
97                         flags & VM_READ ? 'r' : '-',
98                         flags & VM_WRITE ? 'w' : '-',
99                         flags & VM_EXEC ? 'x' : '-',
100                         flags & VM_MAYSHARE ? 's' : 'p',
101                         map->vm_pgoff << PAGE_SHIFT,
102                         MAJOR(dev), MINOR(dev), ino, &len);
103
104         if (map->vm_file) {
105                 len = 25 + sizeof(void*) * 6 - len;
106                 if (len < 1)
107                         len = 1;
108                 seq_printf(m, "%*c", len, ' ');
109                 seq_path(m, file->f_vfsmnt, file->f_dentry, "");
110         }
111         seq_putc(m, '\n');
112         return 0;
113 }
114
115 static void *m_start(struct seq_file *m, loff_t *pos)
116 {
117         struct task_struct *task = m->private;
118         struct mm_struct *mm = get_task_mm(task);
119         struct vm_area_struct * map;
120         loff_t l = *pos;
121
122         if (!mm)
123                 return NULL;
124
125         down_read(&mm->mmap_sem);
126         map = mm->mmap;
127         while (l-- && map)
128                 map = map->vm_next;
129         if (!map) {
130                 up_read(&mm->mmap_sem);
131                 mmput(mm);
132                 if (l == -1)
133                         map = get_gate_vma(task);
134         }
135         return map;
136 }
137
138 static void m_stop(struct seq_file *m, void *v)
139 {
140         struct task_struct *task = m->private;
141         struct vm_area_struct *map = v;
142         if (map && map != get_gate_vma(task)) {
143                 struct mm_struct *mm = map->vm_mm;
144                 up_read(&mm->mmap_sem);
145                 mmput(mm);
146         }
147 }
148
149 static void *m_next(struct seq_file *m, void *v, loff_t *pos)
150 {
151         struct task_struct *task = m->private;
152         struct vm_area_struct *map = v;
153         (*pos)++;
154         if (map->vm_next)
155                 return map->vm_next;
156         m_stop(m, v);
157         if (map != get_gate_vma(task))
158                 return get_gate_vma(task);
159         return NULL;
160 }
161
162 struct seq_operations proc_pid_maps_op = {
163         .start  = m_start,
164         .next   = m_next,
165         .stop   = m_stop,
166         .show   = show_map
167 };