aboutsummaryrefslogtreecommitdiffstats
path: root/fs/proc
diff options
context:
space:
mode:
Diffstat (limited to 'fs/proc')
-rw-r--r--fs/proc/array.c2
-rw-r--r--fs/proc/base.c82
-rw-r--r--fs/proc/generic.c2
-rw-r--r--fs/proc/inode.c17
-rw-r--r--fs/proc/nommu.c1
-rw-r--r--fs/proc/proc_devtree.c57
-rw-r--r--fs/proc/proc_misc.c8
-rw-r--r--fs/proc/task_mmu.c60
8 files changed, 147 insertions, 82 deletions
diff --git a/fs/proc/array.c b/fs/proc/array.c
index d84eecacbeaf..3e1239e4b303 100644
--- a/fs/proc/array.c
+++ b/fs/proc/array.c
@@ -438,7 +438,7 @@ static int do_task_stat(struct task_struct *task, char * buffer, int whole)
438 jiffies_to_clock_t(it_real_value), 438 jiffies_to_clock_t(it_real_value),
439 start_time, 439 start_time,
440 vsize, 440 vsize,
441 mm ? get_mm_counter(mm, rss) : 0, /* you might want to shift this left 3 */ 441 mm ? get_mm_rss(mm) : 0,
442 rsslim, 442 rsslim,
443 mm ? mm->start_code : 0, 443 mm ? mm->start_code : 0,
444 mm ? mm->end_code : 0, 444 mm ? mm->end_code : 0,
diff --git a/fs/proc/base.c b/fs/proc/base.c
index fb34f88a4a74..634355e16986 100644
--- a/fs/proc/base.c
+++ b/fs/proc/base.c
@@ -70,6 +70,7 @@
70#include <linux/seccomp.h> 70#include <linux/seccomp.h>
71#include <linux/cpuset.h> 71#include <linux/cpuset.h>
72#include <linux/audit.h> 72#include <linux/audit.h>
73#include <linux/poll.h>
73#include "internal.h" 74#include "internal.h"
74 75
75/* 76/*
@@ -103,7 +104,9 @@ enum pid_directory_inos {
103 PROC_TGID_NUMA_MAPS, 104 PROC_TGID_NUMA_MAPS,
104 PROC_TGID_MOUNTS, 105 PROC_TGID_MOUNTS,
105 PROC_TGID_WCHAN, 106 PROC_TGID_WCHAN,
107#ifdef CONFIG_MMU
106 PROC_TGID_SMAPS, 108 PROC_TGID_SMAPS,
109#endif
107#ifdef CONFIG_SCHEDSTATS 110#ifdef CONFIG_SCHEDSTATS
108 PROC_TGID_SCHEDSTAT, 111 PROC_TGID_SCHEDSTAT,
109#endif 112#endif
@@ -141,7 +144,9 @@ enum pid_directory_inos {
141 PROC_TID_NUMA_MAPS, 144 PROC_TID_NUMA_MAPS,
142 PROC_TID_MOUNTS, 145 PROC_TID_MOUNTS,
143 PROC_TID_WCHAN, 146 PROC_TID_WCHAN,
147#ifdef CONFIG_MMU
144 PROC_TID_SMAPS, 148 PROC_TID_SMAPS,
149#endif
145#ifdef CONFIG_SCHEDSTATS 150#ifdef CONFIG_SCHEDSTATS
146 PROC_TID_SCHEDSTAT, 151 PROC_TID_SCHEDSTAT,
147#endif 152#endif
@@ -195,7 +200,9 @@ static struct pid_entry tgid_base_stuff[] = {
195 E(PROC_TGID_ROOT, "root", S_IFLNK|S_IRWXUGO), 200 E(PROC_TGID_ROOT, "root", S_IFLNK|S_IRWXUGO),
196 E(PROC_TGID_EXE, "exe", S_IFLNK|S_IRWXUGO), 201 E(PROC_TGID_EXE, "exe", S_IFLNK|S_IRWXUGO),
197 E(PROC_TGID_MOUNTS, "mounts", S_IFREG|S_IRUGO), 202 E(PROC_TGID_MOUNTS, "mounts", S_IFREG|S_IRUGO),
203#ifdef CONFIG_MMU
198 E(PROC_TGID_SMAPS, "smaps", S_IFREG|S_IRUGO), 204 E(PROC_TGID_SMAPS, "smaps", S_IFREG|S_IRUGO),
205#endif
199#ifdef CONFIG_SECURITY 206#ifdef CONFIG_SECURITY
200 E(PROC_TGID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO), 207 E(PROC_TGID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO),
201#endif 208#endif
@@ -235,7 +242,9 @@ static struct pid_entry tid_base_stuff[] = {
235 E(PROC_TID_ROOT, "root", S_IFLNK|S_IRWXUGO), 242 E(PROC_TID_ROOT, "root", S_IFLNK|S_IRWXUGO),
236 E(PROC_TID_EXE, "exe", S_IFLNK|S_IRWXUGO), 243 E(PROC_TID_EXE, "exe", S_IFLNK|S_IRWXUGO),
237 E(PROC_TID_MOUNTS, "mounts", S_IFREG|S_IRUGO), 244 E(PROC_TID_MOUNTS, "mounts", S_IFREG|S_IRUGO),
245#ifdef CONFIG_MMU
238 E(PROC_TID_SMAPS, "smaps", S_IFREG|S_IRUGO), 246 E(PROC_TID_SMAPS, "smaps", S_IFREG|S_IRUGO),
247#endif
239#ifdef CONFIG_SECURITY 248#ifdef CONFIG_SECURITY
240 E(PROC_TID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO), 249 E(PROC_TID_ATTR, "attr", S_IFDIR|S_IRUGO|S_IXUGO),
241#endif 250#endif
@@ -343,7 +352,8 @@ static int proc_root_link(struct inode *inode, struct dentry **dentry, struct vf
343 352
344/* Same as proc_root_link, but this addionally tries to get fs from other 353/* Same as proc_root_link, but this addionally tries to get fs from other
345 * threads in the group */ 354 * threads in the group */
346static int proc_task_root_link(struct inode *inode, struct dentry **dentry, struct vfsmount **mnt) 355static int proc_task_root_link(struct inode *inode, struct dentry **dentry,
356 struct vfsmount **mnt)
347{ 357{
348 struct fs_struct *fs; 358 struct fs_struct *fs;
349 int result = -ENOENT; 359 int result = -ENOENT;
@@ -357,9 +367,10 @@ static int proc_task_root_link(struct inode *inode, struct dentry **dentry, stru
357 } else { 367 } else {
358 /* Try to get fs from other threads */ 368 /* Try to get fs from other threads */
359 task_unlock(leader); 369 task_unlock(leader);
360 struct task_struct *task = leader;
361 read_lock(&tasklist_lock); 370 read_lock(&tasklist_lock);
362 if (pid_alive(task)) { 371 if (pid_alive(leader)) {
372 struct task_struct *task = leader;
373
363 while ((task = next_thread(task)) != leader) { 374 while ((task = next_thread(task)) != leader) {
364 task_lock(task); 375 task_lock(task);
365 fs = task->fs; 376 fs = task->fs;
@@ -628,6 +639,7 @@ static struct file_operations proc_numa_maps_operations = {
628}; 639};
629#endif 640#endif
630 641
642#ifdef CONFIG_MMU
631extern struct seq_operations proc_pid_smaps_op; 643extern struct seq_operations proc_pid_smaps_op;
632static int smaps_open(struct inode *inode, struct file *file) 644static int smaps_open(struct inode *inode, struct file *file)
633{ 645{
@@ -646,28 +658,41 @@ static struct file_operations proc_smaps_operations = {
646 .llseek = seq_lseek, 658 .llseek = seq_lseek,
647 .release = seq_release, 659 .release = seq_release,
648}; 660};
661#endif
649 662
650extern struct seq_operations mounts_op; 663extern struct seq_operations mounts_op;
664struct proc_mounts {
665 struct seq_file m;
666 int event;
667};
668
651static int mounts_open(struct inode *inode, struct file *file) 669static int mounts_open(struct inode *inode, struct file *file)
652{ 670{
653 struct task_struct *task = proc_task(inode); 671 struct task_struct *task = proc_task(inode);
654 int ret = seq_open(file, &mounts_op); 672 struct namespace *namespace;
673 struct proc_mounts *p;
674 int ret = -EINVAL;
655 675
656 if (!ret) { 676 task_lock(task);
657 struct seq_file *m = file->private_data; 677 namespace = task->namespace;
658 struct namespace *namespace; 678 if (namespace)
659 task_lock(task); 679 get_namespace(namespace);
660 namespace = task->namespace; 680 task_unlock(task);
661 if (namespace) 681
662 get_namespace(namespace); 682 if (namespace) {
663 task_unlock(task); 683 ret = -ENOMEM;
664 684 p = kmalloc(sizeof(struct proc_mounts), GFP_KERNEL);
665 if (namespace) 685 if (p) {
666 m->private = namespace; 686 file->private_data = &p->m;
667 else { 687 ret = seq_open(file, &mounts_op);
668 seq_release(inode, file); 688 if (!ret) {
669 ret = -EINVAL; 689 p->m.private = namespace;
690 p->event = namespace->event;
691 return 0;
692 }
693 kfree(p);
670 } 694 }
695 put_namespace(namespace);
671 } 696 }
672 return ret; 697 return ret;
673} 698}
@@ -680,11 +705,30 @@ static int mounts_release(struct inode *inode, struct file *file)
680 return seq_release(inode, file); 705 return seq_release(inode, file);
681} 706}
682 707
708static unsigned mounts_poll(struct file *file, poll_table *wait)
709{
710 struct proc_mounts *p = file->private_data;
711 struct namespace *ns = p->m.private;
712 unsigned res = 0;
713
714 poll_wait(file, &ns->poll, wait);
715
716 spin_lock(&vfsmount_lock);
717 if (p->event != ns->event) {
718 p->event = ns->event;
719 res = POLLERR;
720 }
721 spin_unlock(&vfsmount_lock);
722
723 return res;
724}
725
683static struct file_operations proc_mounts_operations = { 726static struct file_operations proc_mounts_operations = {
684 .open = mounts_open, 727 .open = mounts_open,
685 .read = seq_read, 728 .read = seq_read,
686 .llseek = seq_lseek, 729 .llseek = seq_lseek,
687 .release = mounts_release, 730 .release = mounts_release,
731 .poll = mounts_poll,
688}; 732};
689 733
690#define PROC_BLOCK_SIZE (3*1024) /* 4K page size but our output routines use some slack for overruns */ 734#define PROC_BLOCK_SIZE (3*1024) /* 4K page size but our output routines use some slack for overruns */
@@ -1679,10 +1723,12 @@ static struct dentry *proc_pident_lookup(struct inode *dir,
1679 case PROC_TGID_MOUNTS: 1723 case PROC_TGID_MOUNTS:
1680 inode->i_fop = &proc_mounts_operations; 1724 inode->i_fop = &proc_mounts_operations;
1681 break; 1725 break;
1726#ifdef CONFIG_MMU
1682 case PROC_TID_SMAPS: 1727 case PROC_TID_SMAPS:
1683 case PROC_TGID_SMAPS: 1728 case PROC_TGID_SMAPS:
1684 inode->i_fop = &proc_smaps_operations; 1729 inode->i_fop = &proc_smaps_operations;
1685 break; 1730 break;
1731#endif
1686#ifdef CONFIG_SECURITY 1732#ifdef CONFIG_SECURITY
1687 case PROC_TID_ATTR: 1733 case PROC_TID_ATTR:
1688 inode->i_nlink = 2; 1734 inode->i_nlink = 2;
diff --git a/fs/proc/generic.c b/fs/proc/generic.c
index 8a8c34461d48..b638fb500743 100644
--- a/fs/proc/generic.c
+++ b/fs/proc/generic.c
@@ -533,7 +533,7 @@ static void proc_kill_inodes(struct proc_dir_entry *de)
533 */ 533 */
534 file_list_lock(); 534 file_list_lock();
535 list_for_each(p, &sb->s_files) { 535 list_for_each(p, &sb->s_files) {
536 struct file * filp = list_entry(p, struct file, f_list); 536 struct file * filp = list_entry(p, struct file, f_u.fu_list);
537 struct dentry * dentry = filp->f_dentry; 537 struct dentry * dentry = filp->f_dentry;
538 struct inode * inode; 538 struct inode * inode;
539 struct file_operations *fops; 539 struct file_operations *fops;
diff --git a/fs/proc/inode.c b/fs/proc/inode.c
index effa6c0c467a..e6a818a93f3d 100644
--- a/fs/proc/inode.c
+++ b/fs/proc/inode.c
@@ -156,10 +156,13 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino,
156 156
157 WARN_ON(de && de->deleted); 157 WARN_ON(de && de->deleted);
158 158
159 if (de != NULL && !try_module_get(de->owner))
160 goto out_mod;
161
159 inode = iget(sb, ino); 162 inode = iget(sb, ino);
160 if (!inode) 163 if (!inode)
161 goto out_fail; 164 goto out_ino;
162 165
163 PROC_I(inode)->pde = de; 166 PROC_I(inode)->pde = de;
164 if (de) { 167 if (de) {
165 if (de->mode) { 168 if (de->mode) {
@@ -171,20 +174,20 @@ struct inode *proc_get_inode(struct super_block *sb, unsigned int ino,
171 inode->i_size = de->size; 174 inode->i_size = de->size;
172 if (de->nlink) 175 if (de->nlink)
173 inode->i_nlink = de->nlink; 176 inode->i_nlink = de->nlink;
174 if (!try_module_get(de->owner))
175 goto out_fail;
176 if (de->proc_iops) 177 if (de->proc_iops)
177 inode->i_op = de->proc_iops; 178 inode->i_op = de->proc_iops;
178 if (de->proc_fops) 179 if (de->proc_fops)
179 inode->i_fop = de->proc_fops; 180 inode->i_fop = de->proc_fops;
180 } 181 }
181 182
182out:
183 return inode; 183 return inode;
184 184
185out_fail: 185out_ino:
186 if (de != NULL)
187 module_put(de->owner);
188out_mod:
186 de_put(de); 189 de_put(de);
187 goto out; 190 return NULL;
188} 191}
189 192
190int proc_fill_super(struct super_block *s, void *data, int silent) 193int proc_fill_super(struct super_block *s, void *data, int silent)
diff --git a/fs/proc/nommu.c b/fs/proc/nommu.c
index f3bf016d5ee3..cff10ab1af63 100644
--- a/fs/proc/nommu.c
+++ b/fs/proc/nommu.c
@@ -91,6 +91,7 @@ static void *nommu_vma_list_start(struct seq_file *m, loff_t *_pos)
91 next = _rb; 91 next = _rb;
92 break; 92 break;
93 } 93 }
94 pos--;
94 } 95 }
95 96
96 return next; 97 return next;
diff --git a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c
index 6fd57f154197..fb117b74809e 100644
--- a/fs/proc/proc_devtree.c
+++ b/fs/proc/proc_devtree.c
@@ -49,6 +49,39 @@ static int property_read_proc(char *page, char **start, off_t off,
49 */ 49 */
50 50
51/* 51/*
52 * Add a property to a node
53 */
54static struct proc_dir_entry *
55__proc_device_tree_add_prop(struct proc_dir_entry *de, struct property *pp)
56{
57 struct proc_dir_entry *ent;
58
59 /*
60 * Unfortunately proc_register puts each new entry
61 * at the beginning of the list. So we rearrange them.
62 */
63 ent = create_proc_read_entry(pp->name,
64 strncmp(pp->name, "security-", 9)
65 ? S_IRUGO : S_IRUSR, de,
66 property_read_proc, pp);
67 if (ent == NULL)
68 return NULL;
69
70 if (!strncmp(pp->name, "security-", 9))
71 ent->size = 0; /* don't leak number of password chars */
72 else
73 ent->size = pp->length;
74
75 return ent;
76}
77
78
79void proc_device_tree_add_prop(struct proc_dir_entry *pde, struct property *prop)
80{
81 __proc_device_tree_add_prop(pde, prop);
82}
83
84/*
52 * Process a node, adding entries for its children and its properties. 85 * Process a node, adding entries for its children and its properties.
53 */ 86 */
54void proc_device_tree_add_node(struct device_node *np, 87void proc_device_tree_add_node(struct device_node *np,
@@ -57,11 +90,9 @@ void proc_device_tree_add_node(struct device_node *np,
57 struct property *pp; 90 struct property *pp;
58 struct proc_dir_entry *ent; 91 struct proc_dir_entry *ent;
59 struct device_node *child; 92 struct device_node *child;
60 struct proc_dir_entry *list = NULL, **lastp;
61 const char *p; 93 const char *p;
62 94
63 set_node_proc_entry(np, de); 95 set_node_proc_entry(np, de);
64 lastp = &list;
65 for (child = NULL; (child = of_get_next_child(np, child));) { 96 for (child = NULL; (child = of_get_next_child(np, child));) {
66 p = strrchr(child->full_name, '/'); 97 p = strrchr(child->full_name, '/');
67 if (!p) 98 if (!p)
@@ -71,9 +102,6 @@ void proc_device_tree_add_node(struct device_node *np,
71 ent = proc_mkdir(p, de); 102 ent = proc_mkdir(p, de);
72 if (ent == 0) 103 if (ent == 0)
73 break; 104 break;
74 *lastp = ent;
75 ent->next = NULL;
76 lastp = &ent->next;
77 proc_device_tree_add_node(child, ent); 105 proc_device_tree_add_node(child, ent);
78 } 106 }
79 of_node_put(child); 107 of_node_put(child);
@@ -84,7 +112,7 @@ void proc_device_tree_add_node(struct device_node *np,
84 * properties are quite unimportant for us though, thus we 112 * properties are quite unimportant for us though, thus we
85 * simply "skip" them here, but we do have to check. 113 * simply "skip" them here, but we do have to check.
86 */ 114 */
87 for (ent = list; ent != NULL; ent = ent->next) 115 for (ent = de->subdir; ent != NULL; ent = ent->next)
88 if (!strcmp(ent->name, pp->name)) 116 if (!strcmp(ent->name, pp->name))
89 break; 117 break;
90 if (ent != NULL) { 118 if (ent != NULL) {
@@ -94,25 +122,10 @@ void proc_device_tree_add_node(struct device_node *np,
94 continue; 122 continue;
95 } 123 }
96 124
97 /* 125 ent = __proc_device_tree_add_prop(de, pp);
98 * Unfortunately proc_register puts each new entry
99 * at the beginning of the list. So we rearrange them.
100 */
101 ent = create_proc_read_entry(pp->name,
102 strncmp(pp->name, "security-", 9)
103 ? S_IRUGO : S_IRUSR, de,
104 property_read_proc, pp);
105 if (ent == 0) 126 if (ent == 0)
106 break; 127 break;
107 if (!strncmp(pp->name, "security-", 9))
108 ent->size = 0; /* don't leak number of password chars */
109 else
110 ent->size = pp->length;
111 ent->next = NULL;
112 *lastp = ent;
113 lastp = &ent->next;
114 } 128 }
115 de->subdir = list;
116} 129}
117 130
118/* 131/*
diff --git a/fs/proc/proc_misc.c b/fs/proc/proc_misc.c
index a3453555a94e..5b6b0b6038a7 100644
--- a/fs/proc/proc_misc.c
+++ b/fs/proc/proc_misc.c
@@ -629,12 +629,4 @@ void __init proc_misc_init(void)
629 if (entry) 629 if (entry)
630 entry->proc_fops = &proc_sysrq_trigger_operations; 630 entry->proc_fops = &proc_sysrq_trigger_operations;
631#endif 631#endif
632#ifdef CONFIG_PPC32
633 {
634 extern struct file_operations ppc_htab_operations;
635 entry = create_proc_entry("ppc_htab", S_IRUGO|S_IWUSR, NULL);
636 if (entry)
637 entry->proc_fops = &ppc_htab_operations;
638 }
639#endif
640} 632}
diff --git a/fs/proc/task_mmu.c b/fs/proc/task_mmu.c
index c7ef3e48e35b..50bd5a8f0446 100644
--- a/fs/proc/task_mmu.c
+++ b/fs/proc/task_mmu.c
@@ -14,22 +14,41 @@
14char *task_mem(struct mm_struct *mm, char *buffer) 14char *task_mem(struct mm_struct *mm, char *buffer)
15{ 15{
16 unsigned long data, text, lib; 16 unsigned long data, text, lib;
17 unsigned long hiwater_vm, total_vm, hiwater_rss, total_rss;
18
19 /*
20 * Note: to minimize their overhead, mm maintains hiwater_vm and
21 * hiwater_rss only when about to *lower* total_vm or rss. Any
22 * collector of these hiwater stats must therefore get total_vm
23 * and rss too, which will usually be the higher. Barriers? not
24 * worth the effort, such snapshots can always be inconsistent.
25 */
26 hiwater_vm = total_vm = mm->total_vm;
27 if (hiwater_vm < mm->hiwater_vm)
28 hiwater_vm = mm->hiwater_vm;
29 hiwater_rss = total_rss = get_mm_rss(mm);
30 if (hiwater_rss < mm->hiwater_rss)
31 hiwater_rss = mm->hiwater_rss;
17 32
18 data = mm->total_vm - mm->shared_vm - mm->stack_vm; 33 data = mm->total_vm - mm->shared_vm - mm->stack_vm;
19 text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK)) >> 10; 34 text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK)) >> 10;
20 lib = (mm->exec_vm << (PAGE_SHIFT-10)) - text; 35 lib = (mm->exec_vm << (PAGE_SHIFT-10)) - text;
21 buffer += sprintf(buffer, 36 buffer += sprintf(buffer,
37 "VmPeak:\t%8lu kB\n"
22 "VmSize:\t%8lu kB\n" 38 "VmSize:\t%8lu kB\n"
23 "VmLck:\t%8lu kB\n" 39 "VmLck:\t%8lu kB\n"
40 "VmHWM:\t%8lu kB\n"
24 "VmRSS:\t%8lu kB\n" 41 "VmRSS:\t%8lu kB\n"
25 "VmData:\t%8lu kB\n" 42 "VmData:\t%8lu kB\n"
26 "VmStk:\t%8lu kB\n" 43 "VmStk:\t%8lu kB\n"
27 "VmExe:\t%8lu kB\n" 44 "VmExe:\t%8lu kB\n"
28 "VmLib:\t%8lu kB\n" 45 "VmLib:\t%8lu kB\n"
29 "VmPTE:\t%8lu kB\n", 46 "VmPTE:\t%8lu kB\n",
30 (mm->total_vm - mm->reserved_vm) << (PAGE_SHIFT-10), 47 hiwater_vm << (PAGE_SHIFT-10),
48 (total_vm - mm->reserved_vm) << (PAGE_SHIFT-10),
31 mm->locked_vm << (PAGE_SHIFT-10), 49 mm->locked_vm << (PAGE_SHIFT-10),
32 get_mm_counter(mm, rss) << (PAGE_SHIFT-10), 50 hiwater_rss << (PAGE_SHIFT-10),
51 total_rss << (PAGE_SHIFT-10),
33 data << (PAGE_SHIFT-10), 52 data << (PAGE_SHIFT-10),
34 mm->stack_vm << (PAGE_SHIFT-10), text, lib, 53 mm->stack_vm << (PAGE_SHIFT-10), text, lib,
35 (PTRS_PER_PTE*sizeof(pte_t)*mm->nr_ptes) >> 10); 54 (PTRS_PER_PTE*sizeof(pte_t)*mm->nr_ptes) >> 10);
@@ -44,13 +63,11 @@ unsigned long task_vsize(struct mm_struct *mm)
44int task_statm(struct mm_struct *mm, int *shared, int *text, 63int task_statm(struct mm_struct *mm, int *shared, int *text,
45 int *data, int *resident) 64 int *data, int *resident)
46{ 65{
47 int rss = get_mm_counter(mm, rss); 66 *shared = get_mm_counter(mm, file_rss);
48
49 *shared = rss - get_mm_counter(mm, anon_rss);
50 *text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK)) 67 *text = (PAGE_ALIGN(mm->end_code) - (mm->start_code & PAGE_MASK))
51 >> PAGE_SHIFT; 68 >> PAGE_SHIFT;
52 *data = mm->total_vm - mm->shared_vm; 69 *data = mm->total_vm - mm->shared_vm;
53 *resident = rss; 70 *resident = *shared + get_mm_counter(mm, anon_rss);
54 return mm->total_vm; 71 return mm->total_vm;
55} 72}
56 73
@@ -178,7 +195,7 @@ static int show_map_internal(struct seq_file *m, void *v, struct mem_size_stats
178 195
179static int show_map(struct seq_file *m, void *v) 196static int show_map(struct seq_file *m, void *v)
180{ 197{
181 return show_map_internal(m, v, 0); 198 return show_map_internal(m, v, NULL);
182} 199}
183 200
184static void smaps_pte_range(struct vm_area_struct *vma, pmd_t *pmd, 201static void smaps_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
@@ -186,13 +203,14 @@ static void smaps_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
186 struct mem_size_stats *mss) 203 struct mem_size_stats *mss)
187{ 204{
188 pte_t *pte, ptent; 205 pte_t *pte, ptent;
206 spinlock_t *ptl;
189 unsigned long pfn; 207 unsigned long pfn;
190 struct page *page; 208 struct page *page;
191 209
192 pte = pte_offset_map(pmd, addr); 210 pte = pte_offset_map_lock(vma->vm_mm, pmd, addr, &ptl);
193 do { 211 do {
194 ptent = *pte; 212 ptent = *pte;
195 if (pte_none(ptent) || !pte_present(ptent)) 213 if (!pte_present(ptent))
196 continue; 214 continue;
197 215
198 mss->resident += PAGE_SIZE; 216 mss->resident += PAGE_SIZE;
@@ -213,8 +231,8 @@ static void smaps_pte_range(struct vm_area_struct *vma, pmd_t *pmd,
213 mss->private_clean += PAGE_SIZE; 231 mss->private_clean += PAGE_SIZE;
214 } 232 }
215 } while (pte++, addr += PAGE_SIZE, addr != end); 233 } while (pte++, addr += PAGE_SIZE, addr != end);
216 pte_unmap(pte - 1); 234 pte_unmap_unlock(pte - 1, ptl);
217 cond_resched_lock(&vma->vm_mm->page_table_lock); 235 cond_resched();
218} 236}
219 237
220static inline void smaps_pmd_range(struct vm_area_struct *vma, pud_t *pud, 238static inline void smaps_pmd_range(struct vm_area_struct *vma, pud_t *pud,
@@ -268,17 +286,11 @@ static inline void smaps_pgd_range(struct vm_area_struct *vma,
268static int show_smap(struct seq_file *m, void *v) 286static int show_smap(struct seq_file *m, void *v)
269{ 287{
270 struct vm_area_struct *vma = v; 288 struct vm_area_struct *vma = v;
271 struct mm_struct *mm = vma->vm_mm;
272 struct mem_size_stats mss; 289 struct mem_size_stats mss;
273 290
274 memset(&mss, 0, sizeof mss); 291 memset(&mss, 0, sizeof mss);
275 292 if (vma->vm_mm)
276 if (mm) {
277 spin_lock(&mm->page_table_lock);
278 smaps_pgd_range(vma, vma->vm_start, vma->vm_end, &mss); 293 smaps_pgd_range(vma, vma->vm_start, vma->vm_end, &mss);
279 spin_unlock(&mm->page_table_lock);
280 }
281
282 return show_map_internal(m, v, &mss); 294 return show_map_internal(m, v, &mss);
283} 295}
284 296
@@ -390,12 +402,11 @@ struct numa_maps {
390/* 402/*
391 * Calculate numa node maps for a vma 403 * Calculate numa node maps for a vma
392 */ 404 */
393static struct numa_maps *get_numa_maps(const struct vm_area_struct *vma) 405static struct numa_maps *get_numa_maps(struct vm_area_struct *vma)
394{ 406{
407 int i;
395 struct page *page; 408 struct page *page;
396 unsigned long vaddr; 409 unsigned long vaddr;
397 struct mm_struct *mm = vma->vm_mm;
398 int i;
399 struct numa_maps *md = kmalloc(sizeof(struct numa_maps), GFP_KERNEL); 410 struct numa_maps *md = kmalloc(sizeof(struct numa_maps), GFP_KERNEL);
400 411
401 if (!md) 412 if (!md)
@@ -407,9 +418,8 @@ static struct numa_maps *get_numa_maps(const struct vm_area_struct *vma)
407 for_each_node(i) 418 for_each_node(i)
408 md->node[i] =0; 419 md->node[i] =0;
409 420
410 spin_lock(&mm->page_table_lock);
411 for (vaddr = vma->vm_start; vaddr < vma->vm_end; vaddr += PAGE_SIZE) { 421 for (vaddr = vma->vm_start; vaddr < vma->vm_end; vaddr += PAGE_SIZE) {
412 page = follow_page(mm, vaddr, 0); 422 page = follow_page(vma, vaddr, 0);
413 if (page) { 423 if (page) {
414 int count = page_mapcount(page); 424 int count = page_mapcount(page);
415 425
@@ -422,8 +432,8 @@ static struct numa_maps *get_numa_maps(const struct vm_area_struct *vma)
422 md->anon++; 432 md->anon++;
423 md->node[page_to_nid(page)]++; 433 md->node[page_to_nid(page)]++;
424 } 434 }
435 cond_resched();
425 } 436 }
426 spin_unlock(&mm->page_table_lock);
427 return md; 437 return md;
428} 438}
429 439
@@ -469,7 +479,7 @@ static int show_numa_map(struct seq_file *m, void *v)
469 seq_printf(m, " interleave={"); 479 seq_printf(m, " interleave={");
470 first = 1; 480 first = 1;
471 for_each_node(n) { 481 for_each_node(n) {
472 if (test_bit(n, pol->v.nodes)) { 482 if (node_isset(n, pol->v.nodes)) {
473 if (!first) 483 if (!first)
474 seq_putc(m,','); 484 seq_putc(m,',');
475 else 485 else