diff options
Diffstat (limited to 'drivers/base/node.c')
-rw-r--r-- | drivers/base/node.c | 135 |
1 files changed, 91 insertions, 44 deletions
diff --git a/drivers/base/node.c b/drivers/base/node.c index c80c3aeed004..001e6f6b9c1b 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/cpumask.h> | 11 | #include <linux/cpumask.h> |
12 | #include <linux/topology.h> | 12 | #include <linux/topology.h> |
13 | #include <linux/nodemask.h> | 13 | #include <linux/nodemask.h> |
14 | #include <linux/cpu.h> | ||
14 | 15 | ||
15 | static struct sysdev_class node_class = { | 16 | static struct sysdev_class node_class = { |
16 | set_kset_name("node"), | 17 | set_kset_name("node"), |
@@ -39,24 +40,13 @@ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf) | |||
39 | int n; | 40 | int n; |
40 | int nid = dev->id; | 41 | int nid = dev->id; |
41 | struct sysinfo i; | 42 | struct sysinfo i; |
42 | struct page_state ps; | ||
43 | unsigned long inactive; | 43 | unsigned long inactive; |
44 | unsigned long active; | 44 | unsigned long active; |
45 | unsigned long free; | 45 | unsigned long free; |
46 | 46 | ||
47 | si_meminfo_node(&i, nid); | 47 | si_meminfo_node(&i, nid); |
48 | get_page_state_node(&ps, nid); | ||
49 | __get_zone_counts(&active, &inactive, &free, NODE_DATA(nid)); | 48 | __get_zone_counts(&active, &inactive, &free, NODE_DATA(nid)); |
50 | 49 | ||
51 | /* Check for negative values in these approximate counters */ | ||
52 | if ((long)ps.nr_dirty < 0) | ||
53 | ps.nr_dirty = 0; | ||
54 | if ((long)ps.nr_writeback < 0) | ||
55 | ps.nr_writeback = 0; | ||
56 | if ((long)ps.nr_mapped < 0) | ||
57 | ps.nr_mapped = 0; | ||
58 | if ((long)ps.nr_slab < 0) | ||
59 | ps.nr_slab = 0; | ||
60 | 50 | ||
61 | n = sprintf(buf, "\n" | 51 | n = sprintf(buf, "\n" |
62 | "Node %d MemTotal: %8lu kB\n" | 52 | "Node %d MemTotal: %8lu kB\n" |
@@ -64,27 +54,46 @@ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf) | |||
64 | "Node %d MemUsed: %8lu kB\n" | 54 | "Node %d MemUsed: %8lu kB\n" |
65 | "Node %d Active: %8lu kB\n" | 55 | "Node %d Active: %8lu kB\n" |
66 | "Node %d Inactive: %8lu kB\n" | 56 | "Node %d Inactive: %8lu kB\n" |
57 | #ifdef CONFIG_HIGHMEM | ||
67 | "Node %d HighTotal: %8lu kB\n" | 58 | "Node %d HighTotal: %8lu kB\n" |
68 | "Node %d HighFree: %8lu kB\n" | 59 | "Node %d HighFree: %8lu kB\n" |
69 | "Node %d LowTotal: %8lu kB\n" | 60 | "Node %d LowTotal: %8lu kB\n" |
70 | "Node %d LowFree: %8lu kB\n" | 61 | "Node %d LowFree: %8lu kB\n" |
62 | #endif | ||
71 | "Node %d Dirty: %8lu kB\n" | 63 | "Node %d Dirty: %8lu kB\n" |
72 | "Node %d Writeback: %8lu kB\n" | 64 | "Node %d Writeback: %8lu kB\n" |
65 | "Node %d FilePages: %8lu kB\n" | ||
73 | "Node %d Mapped: %8lu kB\n" | 66 | "Node %d Mapped: %8lu kB\n" |
74 | "Node %d Slab: %8lu kB\n", | 67 | "Node %d AnonPages: %8lu kB\n" |
68 | "Node %d PageTables: %8lu kB\n" | ||
69 | "Node %d NFS_Unstable: %8lu kB\n" | ||
70 | "Node %d Bounce: %8lu kB\n" | ||
71 | "Node %d Slab: %8lu kB\n" | ||
72 | "Node %d SReclaimable: %8lu kB\n" | ||
73 | "Node %d SUnreclaim: %8lu kB\n", | ||
75 | nid, K(i.totalram), | 74 | nid, K(i.totalram), |
76 | nid, K(i.freeram), | 75 | nid, K(i.freeram), |
77 | nid, K(i.totalram - i.freeram), | 76 | nid, K(i.totalram - i.freeram), |
78 | nid, K(active), | 77 | nid, K(active), |
79 | nid, K(inactive), | 78 | nid, K(inactive), |
79 | #ifdef CONFIG_HIGHMEM | ||
80 | nid, K(i.totalhigh), | 80 | nid, K(i.totalhigh), |
81 | nid, K(i.freehigh), | 81 | nid, K(i.freehigh), |
82 | nid, K(i.totalram - i.totalhigh), | 82 | nid, K(i.totalram - i.totalhigh), |
83 | nid, K(i.freeram - i.freehigh), | 83 | nid, K(i.freeram - i.freehigh), |
84 | nid, K(ps.nr_dirty), | 84 | #endif |
85 | nid, K(ps.nr_writeback), | 85 | nid, K(node_page_state(nid, NR_FILE_DIRTY)), |
86 | nid, K(ps.nr_mapped), | 86 | nid, K(node_page_state(nid, NR_WRITEBACK)), |
87 | nid, K(ps.nr_slab)); | 87 | nid, K(node_page_state(nid, NR_FILE_PAGES)), |
88 | nid, K(node_page_state(nid, NR_FILE_MAPPED)), | ||
89 | nid, K(node_page_state(nid, NR_ANON_PAGES)), | ||
90 | nid, K(node_page_state(nid, NR_PAGETABLE)), | ||
91 | nid, K(node_page_state(nid, NR_UNSTABLE_NFS)), | ||
92 | nid, K(node_page_state(nid, NR_BOUNCE)), | ||
93 | nid, K(node_page_state(nid, NR_SLAB_RECLAIMABLE) + | ||
94 | node_page_state(nid, NR_SLAB_UNRECLAIMABLE)), | ||
95 | nid, K(node_page_state(nid, NR_SLAB_RECLAIMABLE)), | ||
96 | nid, K(node_page_state(nid, NR_SLAB_UNRECLAIMABLE))); | ||
88 | n += hugetlb_report_node_meminfo(nid, buf + n); | 97 | n += hugetlb_report_node_meminfo(nid, buf + n); |
89 | return n; | 98 | return n; |
90 | } | 99 | } |
@@ -94,28 +103,6 @@ static SYSDEV_ATTR(meminfo, S_IRUGO, node_read_meminfo, NULL); | |||
94 | 103 | ||
95 | static ssize_t node_read_numastat(struct sys_device * dev, char * buf) | 104 | static ssize_t node_read_numastat(struct sys_device * dev, char * buf) |
96 | { | 105 | { |
97 | unsigned long numa_hit, numa_miss, interleave_hit, numa_foreign; | ||
98 | unsigned long local_node, other_node; | ||
99 | int i, cpu; | ||
100 | pg_data_t *pg = NODE_DATA(dev->id); | ||
101 | numa_hit = 0; | ||
102 | numa_miss = 0; | ||
103 | interleave_hit = 0; | ||
104 | numa_foreign = 0; | ||
105 | local_node = 0; | ||
106 | other_node = 0; | ||
107 | for (i = 0; i < MAX_NR_ZONES; i++) { | ||
108 | struct zone *z = &pg->node_zones[i]; | ||
109 | for_each_online_cpu(cpu) { | ||
110 | struct per_cpu_pageset *ps = zone_pcp(z,cpu); | ||
111 | numa_hit += ps->numa_hit; | ||
112 | numa_miss += ps->numa_miss; | ||
113 | numa_foreign += ps->numa_foreign; | ||
114 | interleave_hit += ps->interleave_hit; | ||
115 | local_node += ps->local_node; | ||
116 | other_node += ps->other_node; | ||
117 | } | ||
118 | } | ||
119 | return sprintf(buf, | 106 | return sprintf(buf, |
120 | "numa_hit %lu\n" | 107 | "numa_hit %lu\n" |
121 | "numa_miss %lu\n" | 108 | "numa_miss %lu\n" |
@@ -123,12 +110,12 @@ static ssize_t node_read_numastat(struct sys_device * dev, char * buf) | |||
123 | "interleave_hit %lu\n" | 110 | "interleave_hit %lu\n" |
124 | "local_node %lu\n" | 111 | "local_node %lu\n" |
125 | "other_node %lu\n", | 112 | "other_node %lu\n", |
126 | numa_hit, | 113 | node_page_state(dev->id, NUMA_HIT), |
127 | numa_miss, | 114 | node_page_state(dev->id, NUMA_MISS), |
128 | numa_foreign, | 115 | node_page_state(dev->id, NUMA_FOREIGN), |
129 | interleave_hit, | 116 | node_page_state(dev->id, NUMA_INTERLEAVE_HIT), |
130 | local_node, | 117 | node_page_state(dev->id, NUMA_LOCAL), |
131 | other_node); | 118 | node_page_state(dev->id, NUMA_OTHER)); |
132 | } | 119 | } |
133 | static SYSDEV_ATTR(numastat, S_IRUGO, node_read_numastat, NULL); | 120 | static SYSDEV_ATTR(numastat, S_IRUGO, node_read_numastat, NULL); |
134 | 121 | ||
@@ -190,6 +177,66 @@ void unregister_node(struct node *node) | |||
190 | sysdev_unregister(&node->sysdev); | 177 | sysdev_unregister(&node->sysdev); |
191 | } | 178 | } |
192 | 179 | ||
180 | struct node node_devices[MAX_NUMNODES]; | ||
181 | |||
182 | /* | ||
183 | * register cpu under node | ||
184 | */ | ||
185 | int register_cpu_under_node(unsigned int cpu, unsigned int nid) | ||
186 | { | ||
187 | if (node_online(nid)) { | ||
188 | struct sys_device *obj = get_cpu_sysdev(cpu); | ||
189 | if (!obj) | ||
190 | return 0; | ||
191 | return sysfs_create_link(&node_devices[nid].sysdev.kobj, | ||
192 | &obj->kobj, | ||
193 | kobject_name(&obj->kobj)); | ||
194 | } | ||
195 | |||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | int unregister_cpu_under_node(unsigned int cpu, unsigned int nid) | ||
200 | { | ||
201 | if (node_online(nid)) { | ||
202 | struct sys_device *obj = get_cpu_sysdev(cpu); | ||
203 | if (obj) | ||
204 | sysfs_remove_link(&node_devices[nid].sysdev.kobj, | ||
205 | kobject_name(&obj->kobj)); | ||
206 | } | ||
207 | return 0; | ||
208 | } | ||
209 | |||
210 | int register_one_node(int nid) | ||
211 | { | ||
212 | int error = 0; | ||
213 | int cpu; | ||
214 | |||
215 | if (node_online(nid)) { | ||
216 | int p_node = parent_node(nid); | ||
217 | struct node *parent = NULL; | ||
218 | |||
219 | if (p_node != nid) | ||
220 | parent = &node_devices[p_node]; | ||
221 | |||
222 | error = register_node(&node_devices[nid], nid, parent); | ||
223 | |||
224 | /* link cpu under this node */ | ||
225 | for_each_present_cpu(cpu) { | ||
226 | if (cpu_to_node(cpu) == nid) | ||
227 | register_cpu_under_node(cpu, nid); | ||
228 | } | ||
229 | } | ||
230 | |||
231 | return error; | ||
232 | |||
233 | } | ||
234 | |||
235 | void unregister_one_node(int nid) | ||
236 | { | ||
237 | unregister_node(&node_devices[nid]); | ||
238 | } | ||
239 | |||
193 | static int __init register_node_type(void) | 240 | static int __init register_node_type(void) |
194 | { | 241 | { |
195 | return sysdev_class_register(&node_class); | 242 | return sysdev_class_register(&node_class); |