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