diff options
-rw-r--r-- | Documentation/filesystems/proc.txt | 9 | ||||
-rw-r--r-- | fs/proc/task_mmu.c | 66 | ||||
-rw-r--r-- | fs/proc/task_nommu.c | 49 | ||||
-rw-r--r-- | include/linux/mm.h | 3 | ||||
-rw-r--r-- | mm/util.c | 27 |
5 files changed, 48 insertions, 106 deletions
diff --git a/Documentation/filesystems/proc.txt b/Documentation/filesystems/proc.txt index fde9fd06fa98..eaebf27539f5 100644 --- a/Documentation/filesystems/proc.txt +++ b/Documentation/filesystems/proc.txt | |||
@@ -356,7 +356,7 @@ address perms offset dev inode pathname | |||
356 | a7cb1000-a7cb2000 ---p 00000000 00:00 0 | 356 | a7cb1000-a7cb2000 ---p 00000000 00:00 0 |
357 | a7cb2000-a7eb2000 rw-p 00000000 00:00 0 | 357 | a7cb2000-a7eb2000 rw-p 00000000 00:00 0 |
358 | a7eb2000-a7eb3000 ---p 00000000 00:00 0 | 358 | a7eb2000-a7eb3000 ---p 00000000 00:00 0 |
359 | a7eb3000-a7ed5000 rw-p 00000000 00:00 0 [stack:1001] | 359 | a7eb3000-a7ed5000 rw-p 00000000 00:00 0 |
360 | a7ed5000-a8008000 r-xp 00000000 03:00 4222 /lib/libc.so.6 | 360 | a7ed5000-a8008000 r-xp 00000000 03:00 4222 /lib/libc.so.6 |
361 | a8008000-a800a000 r--p 00133000 03:00 4222 /lib/libc.so.6 | 361 | a8008000-a800a000 r--p 00133000 03:00 4222 /lib/libc.so.6 |
362 | a800a000-a800b000 rw-p 00135000 03:00 4222 /lib/libc.so.6 | 362 | a800a000-a800b000 rw-p 00135000 03:00 4222 /lib/libc.so.6 |
@@ -388,7 +388,6 @@ is not associated with a file: | |||
388 | 388 | ||
389 | [heap] = the heap of the program | 389 | [heap] = the heap of the program |
390 | [stack] = the stack of the main process | 390 | [stack] = the stack of the main process |
391 | [stack:1001] = the stack of the thread with tid 1001 | ||
392 | [vdso] = the "virtual dynamic shared object", | 391 | [vdso] = the "virtual dynamic shared object", |
393 | the kernel system call handler | 392 | the kernel system call handler |
394 | 393 | ||
@@ -396,10 +395,8 @@ is not associated with a file: | |||
396 | 395 | ||
397 | The /proc/PID/task/TID/maps is a view of the virtual memory from the viewpoint | 396 | The /proc/PID/task/TID/maps is a view of the virtual memory from the viewpoint |
398 | of the individual tasks of a process. In this file you will see a mapping marked | 397 | of the individual tasks of a process. In this file you will see a mapping marked |
399 | as [stack] if that task sees it as a stack. This is a key difference from the | 398 | as [stack] if that task sees it as a stack. Hence, for the example above, the |
400 | content of /proc/PID/maps, where you will see all mappings that are being used | 399 | task-level map, i.e. /proc/PID/task/TID/maps for thread 1001 will look like this: |
401 | as stack by all of those tasks. Hence, for the example above, the task-level | ||
402 | map, i.e. /proc/PID/task/TID/maps for thread 1001 will look like this: | ||
403 | 400 | ||
404 | 08048000-08049000 r-xp 00000000 03:00 8312 /opt/test | 401 | 08048000-08049000 r-xp 00000000 03:00 8312 /opt/test |
405 | 08049000-0804a000 rw-p 00001000 03:00 8312 /opt/test | 402 | 08049000-0804a000 rw-p 00001000 03:00 8312 /opt/test |
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index 4a0c31f904a6..fa95ab2d3674 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c | |||
@@ -259,23 +259,29 @@ static int do_maps_open(struct inode *inode, struct file *file, | |||
259 | sizeof(struct proc_maps_private)); | 259 | sizeof(struct proc_maps_private)); |
260 | } | 260 | } |
261 | 261 | ||
262 | static pid_t pid_of_stack(struct proc_maps_private *priv, | 262 | /* |
263 | struct vm_area_struct *vma, bool is_pid) | 263 | * Indicate if the VMA is a stack for the given task; for |
264 | * /proc/PID/maps that is the stack of the main task. | ||
265 | */ | ||
266 | static int is_stack(struct proc_maps_private *priv, | ||
267 | struct vm_area_struct *vma, int is_pid) | ||
264 | { | 268 | { |
265 | struct inode *inode = priv->inode; | 269 | int stack = 0; |
266 | struct task_struct *task; | 270 | |
267 | pid_t ret = 0; | 271 | if (is_pid) { |
272 | stack = vma->vm_start <= vma->vm_mm->start_stack && | ||
273 | vma->vm_end >= vma->vm_mm->start_stack; | ||
274 | } else { | ||
275 | struct inode *inode = priv->inode; | ||
276 | struct task_struct *task; | ||
268 | 277 | ||
269 | rcu_read_lock(); | 278 | rcu_read_lock(); |
270 | task = pid_task(proc_pid(inode), PIDTYPE_PID); | 279 | task = pid_task(proc_pid(inode), PIDTYPE_PID); |
271 | if (task) { | ||
272 | task = task_of_stack(task, vma, is_pid); | ||
273 | if (task) | 280 | if (task) |
274 | ret = task_pid_nr_ns(task, inode->i_sb->s_fs_info); | 281 | stack = vma_is_stack_for_task(vma, task); |
282 | rcu_read_unlock(); | ||
275 | } | 283 | } |
276 | rcu_read_unlock(); | 284 | return stack; |
277 | |||
278 | return ret; | ||
279 | } | 285 | } |
280 | 286 | ||
281 | static void | 287 | static void |
@@ -335,8 +341,6 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid) | |||
335 | 341 | ||
336 | name = arch_vma_name(vma); | 342 | name = arch_vma_name(vma); |
337 | if (!name) { | 343 | if (!name) { |
338 | pid_t tid; | ||
339 | |||
340 | if (!mm) { | 344 | if (!mm) { |
341 | name = "[vdso]"; | 345 | name = "[vdso]"; |
342 | goto done; | 346 | goto done; |
@@ -348,21 +352,8 @@ show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid) | |||
348 | goto done; | 352 | goto done; |
349 | } | 353 | } |
350 | 354 | ||
351 | tid = pid_of_stack(priv, vma, is_pid); | 355 | if (is_stack(priv, vma, is_pid)) |
352 | if (tid != 0) { | 356 | name = "[stack]"; |
353 | /* | ||
354 | * Thread stack in /proc/PID/task/TID/maps or | ||
355 | * the main process stack. | ||
356 | */ | ||
357 | if (!is_pid || (vma->vm_start <= mm->start_stack && | ||
358 | vma->vm_end >= mm->start_stack)) { | ||
359 | name = "[stack]"; | ||
360 | } else { | ||
361 | /* Thread stack in /proc/PID/maps */ | ||
362 | seq_pad(m, ' '); | ||
363 | seq_printf(m, "[stack:%d]", tid); | ||
364 | } | ||
365 | } | ||
366 | } | 357 | } |
367 | 358 | ||
368 | done: | 359 | done: |
@@ -1618,19 +1609,8 @@ static int show_numa_map(struct seq_file *m, void *v, int is_pid) | |||
1618 | seq_file_path(m, file, "\n\t= "); | 1609 | seq_file_path(m, file, "\n\t= "); |
1619 | } else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) { | 1610 | } else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) { |
1620 | seq_puts(m, " heap"); | 1611 | seq_puts(m, " heap"); |
1621 | } else { | 1612 | } else if (is_stack(proc_priv, vma, is_pid)) { |
1622 | pid_t tid = pid_of_stack(proc_priv, vma, is_pid); | 1613 | seq_puts(m, " stack"); |
1623 | if (tid != 0) { | ||
1624 | /* | ||
1625 | * Thread stack in /proc/PID/task/TID/maps or | ||
1626 | * the main process stack. | ||
1627 | */ | ||
1628 | if (!is_pid || (vma->vm_start <= mm->start_stack && | ||
1629 | vma->vm_end >= mm->start_stack)) | ||
1630 | seq_puts(m, " stack"); | ||
1631 | else | ||
1632 | seq_printf(m, " stack:%d", tid); | ||
1633 | } | ||
1634 | } | 1614 | } |
1635 | 1615 | ||
1636 | if (is_vm_hugetlb_page(vma)) | 1616 | if (is_vm_hugetlb_page(vma)) |
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c index e0d64c92e4f6..faacb0c0d857 100644 --- a/fs/proc/task_nommu.c +++ b/fs/proc/task_nommu.c | |||
@@ -123,23 +123,26 @@ unsigned long task_statm(struct mm_struct *mm, | |||
123 | return size; | 123 | return size; |
124 | } | 124 | } |
125 | 125 | ||
126 | static pid_t pid_of_stack(struct proc_maps_private *priv, | 126 | static int is_stack(struct proc_maps_private *priv, |
127 | struct vm_area_struct *vma, bool is_pid) | 127 | struct vm_area_struct *vma, int is_pid) |
128 | { | 128 | { |
129 | struct inode *inode = priv->inode; | 129 | struct mm_struct *mm = vma->vm_mm; |
130 | struct task_struct *task; | 130 | int stack = 0; |
131 | pid_t ret = 0; | 131 | |
132 | 132 | if (is_pid) { | |
133 | rcu_read_lock(); | 133 | stack = vma->vm_start <= mm->start_stack && |
134 | task = pid_task(proc_pid(inode), PIDTYPE_PID); | 134 | vma->vm_end >= mm->start_stack; |
135 | if (task) { | 135 | } else { |
136 | task = task_of_stack(task, vma, is_pid); | 136 | struct inode *inode = priv->inode; |
137 | struct task_struct *task; | ||
138 | |||
139 | rcu_read_lock(); | ||
140 | task = pid_task(proc_pid(inode), PIDTYPE_PID); | ||
137 | if (task) | 141 | if (task) |
138 | ret = task_pid_nr_ns(task, inode->i_sb->s_fs_info); | 142 | stack = vma_is_stack_for_task(vma, task); |
143 | rcu_read_unlock(); | ||
139 | } | 144 | } |
140 | rcu_read_unlock(); | 145 | return stack; |
141 | |||
142 | return ret; | ||
143 | } | 146 | } |
144 | 147 | ||
145 | /* | 148 | /* |
@@ -181,21 +184,9 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma, | |||
181 | if (file) { | 184 | if (file) { |
182 | seq_pad(m, ' '); | 185 | seq_pad(m, ' '); |
183 | seq_file_path(m, file, ""); | 186 | seq_file_path(m, file, ""); |
184 | } else if (mm) { | 187 | } else if (mm && is_stack(priv, vma, is_pid)) { |
185 | pid_t tid = pid_of_stack(priv, vma, is_pid); | 188 | seq_pad(m, ' '); |
186 | 189 | seq_printf(m, "[stack]"); | |
187 | if (tid != 0) { | ||
188 | seq_pad(m, ' '); | ||
189 | /* | ||
190 | * Thread stack in /proc/PID/task/TID/maps or | ||
191 | * the main process stack. | ||
192 | */ | ||
193 | if (!is_pid || (vma->vm_start <= mm->start_stack && | ||
194 | vma->vm_end >= mm->start_stack)) | ||
195 | seq_printf(m, "[stack]"); | ||
196 | else | ||
197 | seq_printf(m, "[stack:%d]", tid); | ||
198 | } | ||
199 | } | 190 | } |
200 | 191 | ||
201 | seq_putc(m, '\n'); | 192 | seq_putc(m, '\n'); |
diff --git a/include/linux/mm.h b/include/linux/mm.h index f1cd22f2df1a..0b50d7848e3a 100644 --- a/include/linux/mm.h +++ b/include/linux/mm.h | |||
@@ -1341,8 +1341,7 @@ static inline int stack_guard_page_end(struct vm_area_struct *vma, | |||
1341 | !vma_growsup(vma->vm_next, addr); | 1341 | !vma_growsup(vma->vm_next, addr); |
1342 | } | 1342 | } |
1343 | 1343 | ||
1344 | extern struct task_struct *task_of_stack(struct task_struct *task, | 1344 | int vma_is_stack_for_task(struct vm_area_struct *vma, struct task_struct *t); |
1345 | struct vm_area_struct *vma, bool in_group); | ||
1346 | 1345 | ||
1347 | extern unsigned long move_page_tables(struct vm_area_struct *vma, | 1346 | extern unsigned long move_page_tables(struct vm_area_struct *vma, |
1348 | unsigned long old_addr, struct vm_area_struct *new_vma, | 1347 | unsigned long old_addr, struct vm_area_struct *new_vma, |
@@ -230,36 +230,11 @@ void __vma_link_list(struct mm_struct *mm, struct vm_area_struct *vma, | |||
230 | } | 230 | } |
231 | 231 | ||
232 | /* Check if the vma is being used as a stack by this task */ | 232 | /* Check if the vma is being used as a stack by this task */ |
233 | static int vm_is_stack_for_task(struct task_struct *t, | 233 | int vma_is_stack_for_task(struct vm_area_struct *vma, struct task_struct *t) |
234 | struct vm_area_struct *vma) | ||
235 | { | 234 | { |
236 | return (vma->vm_start <= KSTK_ESP(t) && vma->vm_end >= KSTK_ESP(t)); | 235 | return (vma->vm_start <= KSTK_ESP(t) && vma->vm_end >= KSTK_ESP(t)); |
237 | } | 236 | } |
238 | 237 | ||
239 | /* | ||
240 | * Check if the vma is being used as a stack. | ||
241 | * If is_group is non-zero, check in the entire thread group or else | ||
242 | * just check in the current task. Returns the task_struct of the task | ||
243 | * that the vma is stack for. Must be called under rcu_read_lock(). | ||
244 | */ | ||
245 | struct task_struct *task_of_stack(struct task_struct *task, | ||
246 | struct vm_area_struct *vma, bool in_group) | ||
247 | { | ||
248 | if (vm_is_stack_for_task(task, vma)) | ||
249 | return task; | ||
250 | |||
251 | if (in_group) { | ||
252 | struct task_struct *t; | ||
253 | |||
254 | for_each_thread(task, t) { | ||
255 | if (vm_is_stack_for_task(t, vma)) | ||
256 | return t; | ||
257 | } | ||
258 | } | ||
259 | |||
260 | return NULL; | ||
261 | } | ||
262 | |||
263 | #if defined(CONFIG_MMU) && !defined(HAVE_ARCH_PICK_MMAP_LAYOUT) | 238 | #if defined(CONFIG_MMU) && !defined(HAVE_ARCH_PICK_MMAP_LAYOUT) |
264 | void arch_pick_mmap_layout(struct mm_struct *mm) | 239 | void arch_pick_mmap_layout(struct mm_struct *mm) |
265 | { | 240 | { |