]> err.no Git - linux-2.6/blob - fs/proc/task_nommu.c
Merge branch 'release' of git://git.kernel.org/pub/scm/linux/kernel/git/lenb/linux...
[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 /*
107  * display mapping lines for a particular process's /proc/pid/maps
108  */
109 static int show_map(struct seq_file *m, void *_vml)
110 {
111         struct vm_list_struct *vml = _vml;
112         struct proc_maps_private *priv = m->private;
113         struct task_struct *task = priv->task;
114
115         if (maps_protect && !ptrace_may_attach(task))
116                 return -EACCES;
117
118         return nommu_vma_show(m, vml->vma);
119 }
120
121 static void *m_start(struct seq_file *m, loff_t *pos)
122 {
123         struct proc_maps_private *priv = m->private;
124         struct vm_list_struct *vml;
125         struct mm_struct *mm;
126         loff_t n = *pos;
127
128         /* pin the task and mm whilst we play with them */
129         priv->task = get_pid_task(priv->pid, PIDTYPE_PID);
130         if (!priv->task)
131                 return NULL;
132
133         mm = mm_for_maps(priv->task);
134         if (!mm) {
135                 put_task_struct(priv->task);
136                 priv->task = NULL;
137                 return NULL;
138         }
139
140         /* start from the Nth VMA */
141         for (vml = mm->context.vmlist; vml; vml = vml->next)
142                 if (n-- == 0)
143                         return vml;
144         return NULL;
145 }
146
147 static void m_stop(struct seq_file *m, void *_vml)
148 {
149         struct proc_maps_private *priv = m->private;
150
151         if (priv->task) {
152                 struct mm_struct *mm = priv->task->mm;
153                 up_read(&mm->mmap_sem);
154                 mmput(mm);
155                 put_task_struct(priv->task);
156         }
157 }
158
159 static void *m_next(struct seq_file *m, void *_vml, loff_t *pos)
160 {
161         struct vm_list_struct *vml = _vml;
162
163         (*pos)++;
164         return vml ? vml->next : NULL;
165 }
166
167 static const struct seq_operations proc_pid_maps_ops = {
168         .start  = m_start,
169         .next   = m_next,
170         .stop   = m_stop,
171         .show   = show_map
172 };
173
174 static int maps_open(struct inode *inode, struct file *file)
175 {
176         struct proc_maps_private *priv;
177         int ret = -ENOMEM;
178
179         priv = kzalloc(sizeof(*priv), GFP_KERNEL);
180         if (priv) {
181                 priv->pid = proc_pid(inode);
182                 ret = seq_open(file, &proc_pid_maps_ops);
183                 if (!ret) {
184                         struct seq_file *m = file->private_data;
185                         m->private = priv;
186                 } else {
187                         kfree(priv);
188                 }
189         }
190         return ret;
191 }
192
193 const struct file_operations proc_maps_operations = {
194         .open           = maps_open,
195         .read           = seq_read,
196         .llseek         = seq_lseek,
197         .release        = seq_release_private,
198 };
199