diff options
Diffstat (limited to 'fs/proc')
-rw-r--r-- | fs/proc/base.c | 12 | ||||
-rw-r--r-- | fs/proc/internal.h | 9 | ||||
-rw-r--r-- | fs/proc/task_mmu.c | 210 | ||||
-rw-r--r-- | fs/proc/task_nommu.c | 69 |
4 files changed, 239 insertions, 61 deletions
diff --git a/fs/proc/base.c b/fs/proc/base.c index 965d4bde3a3b..3b42c1418f31 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c | |||
@@ -2989,9 +2989,9 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
2989 | INF("cmdline", S_IRUGO, proc_pid_cmdline), | 2989 | INF("cmdline", S_IRUGO, proc_pid_cmdline), |
2990 | ONE("stat", S_IRUGO, proc_tgid_stat), | 2990 | ONE("stat", S_IRUGO, proc_tgid_stat), |
2991 | ONE("statm", S_IRUGO, proc_pid_statm), | 2991 | ONE("statm", S_IRUGO, proc_pid_statm), |
2992 | REG("maps", S_IRUGO, proc_maps_operations), | 2992 | REG("maps", S_IRUGO, proc_pid_maps_operations), |
2993 | #ifdef CONFIG_NUMA | 2993 | #ifdef CONFIG_NUMA |
2994 | REG("numa_maps", S_IRUGO, proc_numa_maps_operations), | 2994 | REG("numa_maps", S_IRUGO, proc_pid_numa_maps_operations), |
2995 | #endif | 2995 | #endif |
2996 | REG("mem", S_IRUSR|S_IWUSR, proc_mem_operations), | 2996 | REG("mem", S_IRUSR|S_IWUSR, proc_mem_operations), |
2997 | LNK("cwd", proc_cwd_link), | 2997 | LNK("cwd", proc_cwd_link), |
@@ -3002,7 +3002,7 @@ static const struct pid_entry tgid_base_stuff[] = { | |||
3002 | REG("mountstats", S_IRUSR, proc_mountstats_operations), | 3002 | REG("mountstats", S_IRUSR, proc_mountstats_operations), |
3003 | #ifdef CONFIG_PROC_PAGE_MONITOR | 3003 | #ifdef CONFIG_PROC_PAGE_MONITOR |
3004 | REG("clear_refs", S_IWUSR, proc_clear_refs_operations), | 3004 | REG("clear_refs", S_IWUSR, proc_clear_refs_operations), |
3005 | REG("smaps", S_IRUGO, proc_smaps_operations), | 3005 | REG("smaps", S_IRUGO, proc_pid_smaps_operations), |
3006 | REG("pagemap", S_IRUGO, proc_pagemap_operations), | 3006 | REG("pagemap", S_IRUGO, proc_pagemap_operations), |
3007 | #endif | 3007 | #endif |
3008 | #ifdef CONFIG_SECURITY | 3008 | #ifdef CONFIG_SECURITY |
@@ -3348,9 +3348,9 @@ static const struct pid_entry tid_base_stuff[] = { | |||
3348 | INF("cmdline", S_IRUGO, proc_pid_cmdline), | 3348 | INF("cmdline", S_IRUGO, proc_pid_cmdline), |
3349 | ONE("stat", S_IRUGO, proc_tid_stat), | 3349 | ONE("stat", S_IRUGO, proc_tid_stat), |
3350 | ONE("statm", S_IRUGO, proc_pid_statm), | 3350 | ONE("statm", S_IRUGO, proc_pid_statm), |
3351 | REG("maps", S_IRUGO, proc_maps_operations), | 3351 | REG("maps", S_IRUGO, proc_tid_maps_operations), |
3352 | #ifdef CONFIG_NUMA | 3352 | #ifdef CONFIG_NUMA |
3353 | REG("numa_maps", S_IRUGO, proc_numa_maps_operations), | 3353 | REG("numa_maps", S_IRUGO, proc_tid_numa_maps_operations), |
3354 | #endif | 3354 | #endif |
3355 | REG("mem", S_IRUSR|S_IWUSR, proc_mem_operations), | 3355 | REG("mem", S_IRUSR|S_IWUSR, proc_mem_operations), |
3356 | LNK("cwd", proc_cwd_link), | 3356 | LNK("cwd", proc_cwd_link), |
@@ -3360,7 +3360,7 @@ static const struct pid_entry tid_base_stuff[] = { | |||
3360 | REG("mountinfo", S_IRUGO, proc_mountinfo_operations), | 3360 | REG("mountinfo", S_IRUGO, proc_mountinfo_operations), |
3361 | #ifdef CONFIG_PROC_PAGE_MONITOR | 3361 | #ifdef CONFIG_PROC_PAGE_MONITOR |
3362 | REG("clear_refs", S_IWUSR, proc_clear_refs_operations), | 3362 | REG("clear_refs", S_IWUSR, proc_clear_refs_operations), |
3363 | REG("smaps", S_IRUGO, proc_smaps_operations), | 3363 | REG("smaps", S_IRUGO, proc_tid_smaps_operations), |
3364 | REG("pagemap", S_IRUGO, proc_pagemap_operations), | 3364 | REG("pagemap", S_IRUGO, proc_pagemap_operations), |
3365 | #endif | 3365 | #endif |
3366 | #ifdef CONFIG_SECURITY | 3366 | #ifdef CONFIG_SECURITY |
diff --git a/fs/proc/internal.h b/fs/proc/internal.h index 292577531ad1..c44efe19798f 100644 --- a/fs/proc/internal.h +++ b/fs/proc/internal.h | |||
@@ -53,9 +53,12 @@ extern int proc_pid_statm(struct seq_file *m, struct pid_namespace *ns, | |||
53 | struct pid *pid, struct task_struct *task); | 53 | struct pid *pid, struct task_struct *task); |
54 | extern loff_t mem_lseek(struct file *file, loff_t offset, int orig); | 54 | extern loff_t mem_lseek(struct file *file, loff_t offset, int orig); |
55 | 55 | ||
56 | extern const struct file_operations proc_maps_operations; | 56 | extern const struct file_operations proc_pid_maps_operations; |
57 | extern const struct file_operations proc_numa_maps_operations; | 57 | extern const struct file_operations proc_tid_maps_operations; |
58 | extern const struct file_operations proc_smaps_operations; | 58 | extern const struct file_operations proc_pid_numa_maps_operations; |
59 | extern const struct file_operations proc_tid_numa_maps_operations; | ||
60 | extern const struct file_operations proc_pid_smaps_operations; | ||
61 | extern const struct file_operations proc_tid_smaps_operations; | ||
59 | extern const struct file_operations proc_clear_refs_operations; | 62 | extern const struct file_operations proc_clear_refs_operations; |
60 | extern const struct file_operations proc_pagemap_operations; | 63 | extern const struct file_operations proc_pagemap_operations; |
61 | extern const struct file_operations proc_net_operations; | 64 | extern const struct file_operations proc_net_operations; |
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c index c7e3a163295c..9694cc283511 100644 --- a/fs/proc/task_mmu.c +++ b/fs/proc/task_mmu.c | |||
@@ -209,16 +209,20 @@ static int do_maps_open(struct inode *inode, struct file *file, | |||
209 | return ret; | 209 | return ret; |
210 | } | 210 | } |
211 | 211 | ||
212 | static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma) | 212 | static void |
213 | show_map_vma(struct seq_file *m, struct vm_area_struct *vma, int is_pid) | ||
213 | { | 214 | { |
214 | struct mm_struct *mm = vma->vm_mm; | 215 | struct mm_struct *mm = vma->vm_mm; |
215 | struct file *file = vma->vm_file; | 216 | struct file *file = vma->vm_file; |
217 | struct proc_maps_private *priv = m->private; | ||
218 | struct task_struct *task = priv->task; | ||
216 | vm_flags_t flags = vma->vm_flags; | 219 | vm_flags_t flags = vma->vm_flags; |
217 | unsigned long ino = 0; | 220 | unsigned long ino = 0; |
218 | unsigned long long pgoff = 0; | 221 | unsigned long long pgoff = 0; |
219 | unsigned long start, end; | 222 | unsigned long start, end; |
220 | dev_t dev = 0; | 223 | dev_t dev = 0; |
221 | int len; | 224 | int len; |
225 | const char *name = NULL; | ||
222 | 226 | ||
223 | if (file) { | 227 | if (file) { |
224 | struct inode *inode = vma->vm_file->f_path.dentry->d_inode; | 228 | struct inode *inode = vma->vm_file->f_path.dentry->d_inode; |
@@ -252,36 +256,57 @@ static void show_map_vma(struct seq_file *m, struct vm_area_struct *vma) | |||
252 | if (file) { | 256 | if (file) { |
253 | pad_len_spaces(m, len); | 257 | pad_len_spaces(m, len); |
254 | seq_path(m, &file->f_path, "\n"); | 258 | seq_path(m, &file->f_path, "\n"); |
255 | } else { | 259 | goto done; |
256 | const char *name = arch_vma_name(vma); | 260 | } |
257 | if (!name) { | 261 | |
258 | if (mm) { | 262 | name = arch_vma_name(vma); |
259 | if (vma->vm_start <= mm->brk && | 263 | if (!name) { |
260 | vma->vm_end >= mm->start_brk) { | 264 | pid_t tid; |
261 | name = "[heap]"; | 265 | |
262 | } else if (vma->vm_start <= mm->start_stack && | 266 | if (!mm) { |
263 | vma->vm_end >= mm->start_stack) { | 267 | name = "[vdso]"; |
264 | name = "[stack]"; | 268 | goto done; |
265 | } | 269 | } |
270 | |||
271 | if (vma->vm_start <= mm->brk && | ||
272 | vma->vm_end >= mm->start_brk) { | ||
273 | name = "[heap]"; | ||
274 | goto done; | ||
275 | } | ||
276 | |||
277 | tid = vm_is_stack(task, vma, is_pid); | ||
278 | |||
279 | if (tid != 0) { | ||
280 | /* | ||
281 | * Thread stack in /proc/PID/task/TID/maps or | ||
282 | * the main process stack. | ||
283 | */ | ||
284 | if (!is_pid || (vma->vm_start <= mm->start_stack && | ||
285 | vma->vm_end >= mm->start_stack)) { | ||
286 | name = "[stack]"; | ||
266 | } else { | 287 | } else { |
267 | name = "[vdso]"; | 288 | /* Thread stack in /proc/PID/maps */ |
289 | pad_len_spaces(m, len); | ||
290 | seq_printf(m, "[stack:%d]", tid); | ||
268 | } | 291 | } |
269 | } | 292 | } |
270 | if (name) { | 293 | } |
271 | pad_len_spaces(m, len); | 294 | |
272 | seq_puts(m, name); | 295 | done: |
273 | } | 296 | if (name) { |
297 | pad_len_spaces(m, len); | ||
298 | seq_puts(m, name); | ||
274 | } | 299 | } |
275 | seq_putc(m, '\n'); | 300 | seq_putc(m, '\n'); |
276 | } | 301 | } |
277 | 302 | ||
278 | static int show_map(struct seq_file *m, void *v) | 303 | static int show_map(struct seq_file *m, void *v, int is_pid) |
279 | { | 304 | { |
280 | struct vm_area_struct *vma = v; | 305 | struct vm_area_struct *vma = v; |
281 | struct proc_maps_private *priv = m->private; | 306 | struct proc_maps_private *priv = m->private; |
282 | struct task_struct *task = priv->task; | 307 | struct task_struct *task = priv->task; |
283 | 308 | ||
284 | show_map_vma(m, vma); | 309 | show_map_vma(m, vma, is_pid); |
285 | 310 | ||
286 | if (m->count < m->size) /* vma is copied successfully */ | 311 | if (m->count < m->size) /* vma is copied successfully */ |
287 | m->version = (vma != get_gate_vma(task->mm)) | 312 | m->version = (vma != get_gate_vma(task->mm)) |
@@ -289,20 +314,49 @@ static int show_map(struct seq_file *m, void *v) | |||
289 | return 0; | 314 | return 0; |
290 | } | 315 | } |
291 | 316 | ||
317 | static int show_pid_map(struct seq_file *m, void *v) | ||
318 | { | ||
319 | return show_map(m, v, 1); | ||
320 | } | ||
321 | |||
322 | static int show_tid_map(struct seq_file *m, void *v) | ||
323 | { | ||
324 | return show_map(m, v, 0); | ||
325 | } | ||
326 | |||
292 | static const struct seq_operations proc_pid_maps_op = { | 327 | static const struct seq_operations proc_pid_maps_op = { |
293 | .start = m_start, | 328 | .start = m_start, |
294 | .next = m_next, | 329 | .next = m_next, |
295 | .stop = m_stop, | 330 | .stop = m_stop, |
296 | .show = show_map | 331 | .show = show_pid_map |
332 | }; | ||
333 | |||
334 | static const struct seq_operations proc_tid_maps_op = { | ||
335 | .start = m_start, | ||
336 | .next = m_next, | ||
337 | .stop = m_stop, | ||
338 | .show = show_tid_map | ||
297 | }; | 339 | }; |
298 | 340 | ||
299 | static int maps_open(struct inode *inode, struct file *file) | 341 | static int pid_maps_open(struct inode *inode, struct file *file) |
300 | { | 342 | { |
301 | return do_maps_open(inode, file, &proc_pid_maps_op); | 343 | return do_maps_open(inode, file, &proc_pid_maps_op); |
302 | } | 344 | } |
303 | 345 | ||
304 | const struct file_operations proc_maps_operations = { | 346 | static int tid_maps_open(struct inode *inode, struct file *file) |
305 | .open = maps_open, | 347 | { |
348 | return do_maps_open(inode, file, &proc_tid_maps_op); | ||
349 | } | ||
350 | |||
351 | const struct file_operations proc_pid_maps_operations = { | ||
352 | .open = pid_maps_open, | ||
353 | .read = seq_read, | ||
354 | .llseek = seq_lseek, | ||
355 | .release = seq_release_private, | ||
356 | }; | ||
357 | |||
358 | const struct file_operations proc_tid_maps_operations = { | ||
359 | .open = tid_maps_open, | ||
306 | .read = seq_read, | 360 | .read = seq_read, |
307 | .llseek = seq_lseek, | 361 | .llseek = seq_lseek, |
308 | .release = seq_release_private, | 362 | .release = seq_release_private, |
@@ -416,7 +470,7 @@ static int smaps_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end, | |||
416 | return 0; | 470 | return 0; |
417 | } | 471 | } |
418 | 472 | ||
419 | static int show_smap(struct seq_file *m, void *v) | 473 | static int show_smap(struct seq_file *m, void *v, int is_pid) |
420 | { | 474 | { |
421 | struct proc_maps_private *priv = m->private; | 475 | struct proc_maps_private *priv = m->private; |
422 | struct task_struct *task = priv->task; | 476 | struct task_struct *task = priv->task; |
@@ -434,7 +488,7 @@ static int show_smap(struct seq_file *m, void *v) | |||
434 | if (vma->vm_mm && !is_vm_hugetlb_page(vma)) | 488 | if (vma->vm_mm && !is_vm_hugetlb_page(vma)) |
435 | walk_page_range(vma->vm_start, vma->vm_end, &smaps_walk); | 489 | walk_page_range(vma->vm_start, vma->vm_end, &smaps_walk); |
436 | 490 | ||
437 | show_map_vma(m, vma); | 491 | show_map_vma(m, vma, is_pid); |
438 | 492 | ||
439 | seq_printf(m, | 493 | seq_printf(m, |
440 | "Size: %8lu kB\n" | 494 | "Size: %8lu kB\n" |
@@ -473,20 +527,49 @@ static int show_smap(struct seq_file *m, void *v) | |||
473 | return 0; | 527 | return 0; |
474 | } | 528 | } |
475 | 529 | ||
530 | static int show_pid_smap(struct seq_file *m, void *v) | ||
531 | { | ||
532 | return show_smap(m, v, 1); | ||
533 | } | ||
534 | |||
535 | static int show_tid_smap(struct seq_file *m, void *v) | ||
536 | { | ||
537 | return show_smap(m, v, 0); | ||
538 | } | ||
539 | |||
476 | static const struct seq_operations proc_pid_smaps_op = { | 540 | static const struct seq_operations proc_pid_smaps_op = { |
477 | .start = m_start, | 541 | .start = m_start, |
478 | .next = m_next, | 542 | .next = m_next, |
479 | .stop = m_stop, | 543 | .stop = m_stop, |
480 | .show = show_smap | 544 | .show = show_pid_smap |
545 | }; | ||
546 | |||
547 | static const struct seq_operations proc_tid_smaps_op = { | ||
548 | .start = m_start, | ||
549 | .next = m_next, | ||
550 | .stop = m_stop, | ||
551 | .show = show_tid_smap | ||
481 | }; | 552 | }; |
482 | 553 | ||
483 | static int smaps_open(struct inode *inode, struct file *file) | 554 | static int pid_smaps_open(struct inode *inode, struct file *file) |
484 | { | 555 | { |
485 | return do_maps_open(inode, file, &proc_pid_smaps_op); | 556 | return do_maps_open(inode, file, &proc_pid_smaps_op); |
486 | } | 557 | } |
487 | 558 | ||
488 | const struct file_operations proc_smaps_operations = { | 559 | static int tid_smaps_open(struct inode *inode, struct file *file) |
489 | .open = smaps_open, | 560 | { |
561 | return do_maps_open(inode, file, &proc_tid_smaps_op); | ||
562 | } | ||
563 | |||
564 | const struct file_operations proc_pid_smaps_operations = { | ||
565 | .open = pid_smaps_open, | ||
566 | .read = seq_read, | ||
567 | .llseek = seq_lseek, | ||
568 | .release = seq_release_private, | ||
569 | }; | ||
570 | |||
571 | const struct file_operations proc_tid_smaps_operations = { | ||
572 | .open = tid_smaps_open, | ||
490 | .read = seq_read, | 573 | .read = seq_read, |
491 | .llseek = seq_lseek, | 574 | .llseek = seq_lseek, |
492 | .release = seq_release_private, | 575 | .release = seq_release_private, |
@@ -1039,7 +1122,7 @@ static int gather_hugetbl_stats(pte_t *pte, unsigned long hmask, | |||
1039 | /* | 1122 | /* |
1040 | * Display pages allocated per node and memory policy via /proc. | 1123 | * Display pages allocated per node and memory policy via /proc. |
1041 | */ | 1124 | */ |
1042 | static int show_numa_map(struct seq_file *m, void *v) | 1125 | static int show_numa_map(struct seq_file *m, void *v, int is_pid) |
1043 | { | 1126 | { |
1044 | struct numa_maps_private *numa_priv = m->private; | 1127 | struct numa_maps_private *numa_priv = m->private; |
1045 | struct proc_maps_private *proc_priv = &numa_priv->proc_maps; | 1128 | struct proc_maps_private *proc_priv = &numa_priv->proc_maps; |
@@ -1076,9 +1159,19 @@ static int show_numa_map(struct seq_file *m, void *v) | |||
1076 | seq_path(m, &file->f_path, "\n\t= "); | 1159 | seq_path(m, &file->f_path, "\n\t= "); |
1077 | } else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) { | 1160 | } else if (vma->vm_start <= mm->brk && vma->vm_end >= mm->start_brk) { |
1078 | seq_printf(m, " heap"); | 1161 | seq_printf(m, " heap"); |
1079 | } else if (vma->vm_start <= mm->start_stack && | 1162 | } else { |
1080 | vma->vm_end >= mm->start_stack) { | 1163 | pid_t tid = vm_is_stack(proc_priv->task, vma, is_pid); |
1081 | seq_printf(m, " stack"); | 1164 | if (tid != 0) { |
1165 | /* | ||
1166 | * Thread stack in /proc/PID/task/TID/maps or | ||
1167 | * the main process stack. | ||
1168 | */ | ||
1169 | if (!is_pid || (vma->vm_start <= mm->start_stack && | ||
1170 | vma->vm_end >= mm->start_stack)) | ||
1171 | seq_printf(m, " stack"); | ||
1172 | else | ||
1173 | seq_printf(m, " stack:%d", tid); | ||
1174 | } | ||
1082 | } | 1175 | } |
1083 | 1176 | ||
1084 | if (is_vm_hugetlb_page(vma)) | 1177 | if (is_vm_hugetlb_page(vma)) |
@@ -1121,21 +1214,39 @@ out: | |||
1121 | return 0; | 1214 | return 0; |
1122 | } | 1215 | } |
1123 | 1216 | ||
1217 | static int show_pid_numa_map(struct seq_file *m, void *v) | ||
1218 | { | ||
1219 | return show_numa_map(m, v, 1); | ||
1220 | } | ||
1221 | |||
1222 | static int show_tid_numa_map(struct seq_file *m, void *v) | ||
1223 | { | ||
1224 | return show_numa_map(m, v, 0); | ||
1225 | } | ||
1226 | |||
1124 | static const struct seq_operations proc_pid_numa_maps_op = { | 1227 | static const struct seq_operations proc_pid_numa_maps_op = { |
1125 | .start = m_start, | 1228 | .start = m_start, |
1126 | .next = m_next, | 1229 | .next = m_next, |
1127 | .stop = m_stop, | 1230 | .stop = m_stop, |
1128 | .show = show_numa_map, | 1231 | .show = show_pid_numa_map, |
1129 | }; | 1232 | }; |
1130 | 1233 | ||
1131 | static int numa_maps_open(struct inode *inode, struct file *file) | 1234 | static const struct seq_operations proc_tid_numa_maps_op = { |
1235 | .start = m_start, | ||
1236 | .next = m_next, | ||
1237 | .stop = m_stop, | ||
1238 | .show = show_tid_numa_map, | ||
1239 | }; | ||
1240 | |||
1241 | static int numa_maps_open(struct inode *inode, struct file *file, | ||
1242 | const struct seq_operations *ops) | ||
1132 | { | 1243 | { |
1133 | struct numa_maps_private *priv; | 1244 | struct numa_maps_private *priv; |
1134 | int ret = -ENOMEM; | 1245 | int ret = -ENOMEM; |
1135 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | 1246 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
1136 | if (priv) { | 1247 | if (priv) { |
1137 | priv->proc_maps.pid = proc_pid(inode); | 1248 | priv->proc_maps.pid = proc_pid(inode); |
1138 | ret = seq_open(file, &proc_pid_numa_maps_op); | 1249 | ret = seq_open(file, ops); |
1139 | if (!ret) { | 1250 | if (!ret) { |
1140 | struct seq_file *m = file->private_data; | 1251 | struct seq_file *m = file->private_data; |
1141 | m->private = priv; | 1252 | m->private = priv; |
@@ -1146,8 +1257,25 @@ static int numa_maps_open(struct inode *inode, struct file *file) | |||
1146 | return ret; | 1257 | return ret; |
1147 | } | 1258 | } |
1148 | 1259 | ||
1149 | const struct file_operations proc_numa_maps_operations = { | 1260 | static int pid_numa_maps_open(struct inode *inode, struct file *file) |
1150 | .open = numa_maps_open, | 1261 | { |
1262 | return numa_maps_open(inode, file, &proc_pid_numa_maps_op); | ||
1263 | } | ||
1264 | |||
1265 | static int tid_numa_maps_open(struct inode *inode, struct file *file) | ||
1266 | { | ||
1267 | return numa_maps_open(inode, file, &proc_tid_numa_maps_op); | ||
1268 | } | ||
1269 | |||
1270 | const struct file_operations proc_pid_numa_maps_operations = { | ||
1271 | .open = pid_numa_maps_open, | ||
1272 | .read = seq_read, | ||
1273 | .llseek = seq_lseek, | ||
1274 | .release = seq_release_private, | ||
1275 | }; | ||
1276 | |||
1277 | const struct file_operations proc_tid_numa_maps_operations = { | ||
1278 | .open = tid_numa_maps_open, | ||
1151 | .read = seq_read, | 1279 | .read = seq_read, |
1152 | .llseek = seq_lseek, | 1280 | .llseek = seq_lseek, |
1153 | .release = seq_release_private, | 1281 | .release = seq_release_private, |
diff --git a/fs/proc/task_nommu.c b/fs/proc/task_nommu.c index 980de547c070..74fe164d1b23 100644 --- a/fs/proc/task_nommu.c +++ b/fs/proc/task_nommu.c | |||
@@ -134,9 +134,11 @@ static void pad_len_spaces(struct seq_file *m, int len) | |||
134 | /* | 134 | /* |
135 | * display a single VMA to a sequenced file | 135 | * display a single VMA to a sequenced file |
136 | */ | 136 | */ |
137 | static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma) | 137 | static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma, |
138 | int is_pid) | ||
138 | { | 139 | { |
139 | struct mm_struct *mm = vma->vm_mm; | 140 | struct mm_struct *mm = vma->vm_mm; |
141 | struct proc_maps_private *priv = m->private; | ||
140 | unsigned long ino = 0; | 142 | unsigned long ino = 0; |
141 | struct file *file; | 143 | struct file *file; |
142 | dev_t dev = 0; | 144 | dev_t dev = 0; |
@@ -168,10 +170,19 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma) | |||
168 | pad_len_spaces(m, len); | 170 | pad_len_spaces(m, len); |
169 | seq_path(m, &file->f_path, ""); | 171 | seq_path(m, &file->f_path, ""); |
170 | } else if (mm) { | 172 | } else if (mm) { |
171 | if (vma->vm_start <= mm->start_stack && | 173 | pid_t tid = vm_is_stack(priv->task, vma, is_pid); |
172 | vma->vm_end >= mm->start_stack) { | 174 | |
175 | if (tid != 0) { | ||
173 | pad_len_spaces(m, len); | 176 | pad_len_spaces(m, len); |
174 | seq_puts(m, "[stack]"); | 177 | /* |
178 | * Thread stack in /proc/PID/task/TID/maps or | ||
179 | * the main process stack. | ||
180 | */ | ||
181 | if (!is_pid || (vma->vm_start <= mm->start_stack && | ||
182 | vma->vm_end >= mm->start_stack)) | ||
183 | seq_printf(m, "[stack]"); | ||
184 | else | ||
185 | seq_printf(m, "[stack:%d]", tid); | ||
175 | } | 186 | } |
176 | } | 187 | } |
177 | 188 | ||
@@ -182,11 +193,22 @@ static int nommu_vma_show(struct seq_file *m, struct vm_area_struct *vma) | |||
182 | /* | 193 | /* |
183 | * display mapping lines for a particular process's /proc/pid/maps | 194 | * display mapping lines for a particular process's /proc/pid/maps |
184 | */ | 195 | */ |
185 | static int show_map(struct seq_file *m, void *_p) | 196 | static int show_map(struct seq_file *m, void *_p, int is_pid) |
186 | { | 197 | { |
187 | struct rb_node *p = _p; | 198 | struct rb_node *p = _p; |
188 | 199 | ||
189 | return nommu_vma_show(m, rb_entry(p, struct vm_area_struct, vm_rb)); | 200 | return nommu_vma_show(m, rb_entry(p, struct vm_area_struct, vm_rb), |
201 | is_pid); | ||
202 | } | ||
203 | |||
204 | static int show_pid_map(struct seq_file *m, void *_p) | ||
205 | { | ||
206 | return show_map(m, _p, 1); | ||
207 | } | ||
208 | |||
209 | static int show_tid_map(struct seq_file *m, void *_p) | ||
210 | { | ||
211 | return show_map(m, _p, 0); | ||
190 | } | 212 | } |
191 | 213 | ||
192 | static void *m_start(struct seq_file *m, loff_t *pos) | 214 | static void *m_start(struct seq_file *m, loff_t *pos) |
@@ -240,10 +262,18 @@ static const struct seq_operations proc_pid_maps_ops = { | |||
240 | .start = m_start, | 262 | .start = m_start, |
241 | .next = m_next, | 263 | .next = m_next, |
242 | .stop = m_stop, | 264 | .stop = m_stop, |
243 | .show = show_map | 265 | .show = show_pid_map |
266 | }; | ||
267 | |||
268 | static const struct seq_operations proc_tid_maps_ops = { | ||
269 | .start = m_start, | ||
270 | .next = m_next, | ||
271 | .stop = m_stop, | ||
272 | .show = show_tid_map | ||
244 | }; | 273 | }; |
245 | 274 | ||
246 | static int maps_open(struct inode *inode, struct file *file) | 275 | static int maps_open(struct inode *inode, struct file *file, |
276 | const struct seq_operations *ops) | ||
247 | { | 277 | { |
248 | struct proc_maps_private *priv; | 278 | struct proc_maps_private *priv; |
249 | int ret = -ENOMEM; | 279 | int ret = -ENOMEM; |
@@ -251,7 +281,7 @@ static int maps_open(struct inode *inode, struct file *file) | |||
251 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); | 281 | priv = kzalloc(sizeof(*priv), GFP_KERNEL); |
252 | if (priv) { | 282 | if (priv) { |
253 | priv->pid = proc_pid(inode); | 283 | priv->pid = proc_pid(inode); |
254 | ret = seq_open(file, &proc_pid_maps_ops); | 284 | ret = seq_open(file, ops); |
255 | if (!ret) { | 285 | if (!ret) { |
256 | struct seq_file *m = file->private_data; | 286 | struct seq_file *m = file->private_data; |
257 | m->private = priv; | 287 | m->private = priv; |
@@ -262,8 +292,25 @@ static int maps_open(struct inode *inode, struct file *file) | |||
262 | return ret; | 292 | return ret; |
263 | } | 293 | } |
264 | 294 | ||
265 | const struct file_operations proc_maps_operations = { | 295 | static int pid_maps_open(struct inode *inode, struct file *file) |
266 | .open = maps_open, | 296 | { |
297 | return maps_open(inode, file, &proc_pid_maps_ops); | ||
298 | } | ||
299 | |||
300 | static int tid_maps_open(struct inode *inode, struct file *file) | ||
301 | { | ||
302 | return maps_open(inode, file, &proc_tid_maps_ops); | ||
303 | } | ||
304 | |||
305 | const struct file_operations proc_pid_maps_operations = { | ||
306 | .open = pid_maps_open, | ||
307 | .read = seq_read, | ||
308 | .llseek = seq_lseek, | ||
309 | .release = seq_release_private, | ||
310 | }; | ||
311 | |||
312 | const struct file_operations proc_tid_maps_operations = { | ||
313 | .open = tid_maps_open, | ||
267 | .read = seq_read, | 314 | .read = seq_read, |
268 | .llseek = seq_lseek, | 315 | .llseek = seq_lseek, |
269 | .release = seq_release_private, | 316 | .release = seq_release_private, |