diff options
author | Martin Hicks <mort@sgi.com> | 2005-09-03 18:55:11 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@evo.osdl.org> | 2005-09-05 03:05:49 -0400 |
commit | c07e02db76940c75fc92f2f2c9adcdbb09ed70d0 (patch) | |
tree | 9d777784fd5e3658d8db5b01a965d4fc568ceb93 | |
parent | e070ad49f31155d872d8e96cab2142840993e3c0 (diff) |
[PATCH] VM: add page_state info to per-node meminfo
Add page_state info to the per-node meminfo file in sysfs. This is mostly
just for informational purposes.
The lack of this information was brought up recently during a discussion
regarding pagecache clearing, and I put this patch together to test out one
of the suggestions.
It seems like interesting info to have, so I'm submitting the patch.
Signed-off-by: Martin Hicks <mort@sgi.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r-- | drivers/base/node.c | 24 | ||||
-rw-r--r-- | include/linux/page-flags.h | 1 | ||||
-rw-r--r-- | mm/page_alloc.c | 25 |
3 files changed, 43 insertions, 7 deletions
diff --git a/drivers/base/node.c b/drivers/base/node.c index 904b27caf69..16c513aa4d4 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c | |||
@@ -39,13 +39,25 @@ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf) | |||
39 | int n; | 39 | int n; |
40 | int nid = dev->id; | 40 | int nid = dev->id; |
41 | struct sysinfo i; | 41 | struct sysinfo i; |
42 | struct page_state ps; | ||
42 | unsigned long inactive; | 43 | unsigned long inactive; |
43 | unsigned long active; | 44 | unsigned long active; |
44 | unsigned long free; | 45 | unsigned long free; |
45 | 46 | ||
46 | si_meminfo_node(&i, nid); | 47 | si_meminfo_node(&i, nid); |
48 | get_page_state_node(&ps, nid); | ||
47 | __get_zone_counts(&active, &inactive, &free, NODE_DATA(nid)); | 49 | __get_zone_counts(&active, &inactive, &free, NODE_DATA(nid)); |
48 | 50 | ||
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 | |||
49 | n = sprintf(buf, "\n" | 61 | n = sprintf(buf, "\n" |
50 | "Node %d MemTotal: %8lu kB\n" | 62 | "Node %d MemTotal: %8lu kB\n" |
51 | "Node %d MemFree: %8lu kB\n" | 63 | "Node %d MemFree: %8lu kB\n" |
@@ -55,7 +67,11 @@ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf) | |||
55 | "Node %d HighTotal: %8lu kB\n" | 67 | "Node %d HighTotal: %8lu kB\n" |
56 | "Node %d HighFree: %8lu kB\n" | 68 | "Node %d HighFree: %8lu kB\n" |
57 | "Node %d LowTotal: %8lu kB\n" | 69 | "Node %d LowTotal: %8lu kB\n" |
58 | "Node %d LowFree: %8lu kB\n", | 70 | "Node %d LowFree: %8lu kB\n" |
71 | "Node %d Dirty: %8lu kB\n" | ||
72 | "Node %d Writeback: %8lu kB\n" | ||
73 | "Node %d Mapped: %8lu kB\n" | ||
74 | "Node %d Slab: %8lu kB\n", | ||
59 | nid, K(i.totalram), | 75 | nid, K(i.totalram), |
60 | nid, K(i.freeram), | 76 | nid, K(i.freeram), |
61 | nid, K(i.totalram - i.freeram), | 77 | nid, K(i.totalram - i.freeram), |
@@ -64,7 +80,11 @@ static ssize_t node_read_meminfo(struct sys_device * dev, char * buf) | |||
64 | nid, K(i.totalhigh), | 80 | nid, K(i.totalhigh), |
65 | nid, K(i.freehigh), | 81 | nid, K(i.freehigh), |
66 | nid, K(i.totalram - i.totalhigh), | 82 | nid, K(i.totalram - i.totalhigh), |
67 | nid, K(i.freeram - i.freehigh)); | 83 | nid, K(i.freeram - i.freehigh), |
84 | nid, K(ps.nr_dirty), | ||
85 | nid, K(ps.nr_writeback), | ||
86 | nid, K(ps.nr_mapped), | ||
87 | nid, K(ps.nr_slab)); | ||
68 | n += hugetlb_report_node_meminfo(nid, buf + n); | 88 | n += hugetlb_report_node_meminfo(nid, buf + n); |
69 | return n; | 89 | return n; |
70 | } | 90 | } |
diff --git a/include/linux/page-flags.h b/include/linux/page-flags.h index 99f7cc49506..f34767c5fc7 100644 --- a/include/linux/page-flags.h +++ b/include/linux/page-flags.h | |||
@@ -134,6 +134,7 @@ struct page_state { | |||
134 | }; | 134 | }; |
135 | 135 | ||
136 | extern void get_page_state(struct page_state *ret); | 136 | extern void get_page_state(struct page_state *ret); |
137 | extern void get_page_state_node(struct page_state *ret, int node); | ||
137 | extern void get_full_page_state(struct page_state *ret); | 138 | extern void get_full_page_state(struct page_state *ret); |
138 | extern unsigned long __read_page_state(unsigned long offset); | 139 | extern unsigned long __read_page_state(unsigned long offset); |
139 | extern void __mod_page_state(unsigned long offset, unsigned long delta); | 140 | extern void __mod_page_state(unsigned long offset, unsigned long delta); |
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index d157dae8c9f..b06a9636d97 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -1130,19 +1130,20 @@ EXPORT_SYMBOL(nr_pagecache); | |||
1130 | DEFINE_PER_CPU(long, nr_pagecache_local) = 0; | 1130 | DEFINE_PER_CPU(long, nr_pagecache_local) = 0; |
1131 | #endif | 1131 | #endif |
1132 | 1132 | ||
1133 | void __get_page_state(struct page_state *ret, int nr) | 1133 | void __get_page_state(struct page_state *ret, int nr, cpumask_t *cpumask) |
1134 | { | 1134 | { |
1135 | int cpu = 0; | 1135 | int cpu = 0; |
1136 | 1136 | ||
1137 | memset(ret, 0, sizeof(*ret)); | 1137 | memset(ret, 0, sizeof(*ret)); |
1138 | cpus_and(*cpumask, *cpumask, cpu_online_map); | ||
1138 | 1139 | ||
1139 | cpu = first_cpu(cpu_online_map); | 1140 | cpu = first_cpu(*cpumask); |
1140 | while (cpu < NR_CPUS) { | 1141 | while (cpu < NR_CPUS) { |
1141 | unsigned long *in, *out, off; | 1142 | unsigned long *in, *out, off; |
1142 | 1143 | ||
1143 | in = (unsigned long *)&per_cpu(page_states, cpu); | 1144 | in = (unsigned long *)&per_cpu(page_states, cpu); |
1144 | 1145 | ||
1145 | cpu = next_cpu(cpu, cpu_online_map); | 1146 | cpu = next_cpu(cpu, *cpumask); |
1146 | 1147 | ||
1147 | if (cpu < NR_CPUS) | 1148 | if (cpu < NR_CPUS) |
1148 | prefetch(&per_cpu(page_states, cpu)); | 1149 | prefetch(&per_cpu(page_states, cpu)); |
@@ -1153,19 +1154,33 @@ void __get_page_state(struct page_state *ret, int nr) | |||
1153 | } | 1154 | } |
1154 | } | 1155 | } |
1155 | 1156 | ||
1157 | void get_page_state_node(struct page_state *ret, int node) | ||
1158 | { | ||
1159 | int nr; | ||
1160 | cpumask_t mask = node_to_cpumask(node); | ||
1161 | |||
1162 | nr = offsetof(struct page_state, GET_PAGE_STATE_LAST); | ||
1163 | nr /= sizeof(unsigned long); | ||
1164 | |||
1165 | __get_page_state(ret, nr+1, &mask); | ||
1166 | } | ||
1167 | |||
1156 | void get_page_state(struct page_state *ret) | 1168 | void get_page_state(struct page_state *ret) |
1157 | { | 1169 | { |
1158 | int nr; | 1170 | int nr; |
1171 | cpumask_t mask = CPU_MASK_ALL; | ||
1159 | 1172 | ||
1160 | nr = offsetof(struct page_state, GET_PAGE_STATE_LAST); | 1173 | nr = offsetof(struct page_state, GET_PAGE_STATE_LAST); |
1161 | nr /= sizeof(unsigned long); | 1174 | nr /= sizeof(unsigned long); |
1162 | 1175 | ||
1163 | __get_page_state(ret, nr + 1); | 1176 | __get_page_state(ret, nr + 1, &mask); |
1164 | } | 1177 | } |
1165 | 1178 | ||
1166 | void get_full_page_state(struct page_state *ret) | 1179 | void get_full_page_state(struct page_state *ret) |
1167 | { | 1180 | { |
1168 | __get_page_state(ret, sizeof(*ret) / sizeof(unsigned long)); | 1181 | cpumask_t mask = CPU_MASK_ALL; |
1182 | |||
1183 | __get_page_state(ret, sizeof(*ret) / sizeof(unsigned long), &mask); | ||
1169 | } | 1184 | } |
1170 | 1185 | ||
1171 | unsigned long __read_page_state(unsigned long offset) | 1186 | unsigned long __read_page_state(unsigned long offset) |