Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[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>

authored by

Martin Hicks and committed by
Linus Torvalds
c07e02db e070ad49

+44 -8
+22 -2
drivers/base/node.c
··· 39 39 int n; 40 40 int nid = dev->id; 41 41 struct sysinfo i; 42 + struct page_state ps; 42 43 unsigned long inactive; 43 44 unsigned long active; 44 45 unsigned long free; 45 46 46 47 si_meminfo_node(&i, nid); 48 + get_page_state_node(&ps, nid); 47 49 __get_zone_counts(&active, &inactive, &free, NODE_DATA(nid)); 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; 48 60 49 61 n = sprintf(buf, "\n" 50 62 "Node %d MemTotal: %8lu kB\n" ··· 67 55 "Node %d HighTotal: %8lu kB\n" 68 56 "Node %d HighFree: %8lu kB\n" 69 57 "Node %d LowTotal: %8lu kB\n" 70 - "Node %d LowFree: %8lu kB\n", 58 + "Node %d LowFree: %8lu kB\n" 59 + "Node %d Dirty: %8lu kB\n" 60 + "Node %d Writeback: %8lu kB\n" 61 + "Node %d Mapped: %8lu kB\n" 62 + "Node %d Slab: %8lu kB\n", 71 63 nid, K(i.totalram), 72 64 nid, K(i.freeram), 73 65 nid, K(i.totalram - i.freeram), ··· 80 64 nid, K(i.totalhigh), 81 65 nid, K(i.freehigh), 82 66 nid, K(i.totalram - i.totalhigh), 83 - nid, K(i.freeram - i.freehigh)); 67 + nid, K(i.freeram - i.freehigh), 68 + nid, K(ps.nr_dirty), 69 + nid, K(ps.nr_writeback), 70 + nid, K(ps.nr_mapped), 71 + nid, K(ps.nr_slab)); 84 72 n += hugetlb_report_node_meminfo(nid, buf + n); 85 73 return n; 86 74 }
+1
include/linux/page-flags.h
··· 134 134 }; 135 135 136 136 extern void get_page_state(struct page_state *ret); 137 + extern void get_page_state_node(struct page_state *ret, int node); 137 138 extern void get_full_page_state(struct page_state *ret); 138 139 extern unsigned long __read_page_state(unsigned long offset); 139 140 extern void __mod_page_state(unsigned long offset, unsigned long delta);
+21 -6
mm/page_alloc.c
··· 1130 1130 DEFINE_PER_CPU(long, nr_pagecache_local) = 0; 1131 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 1135 int cpu = 0; 1136 1136 1137 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 1141 while (cpu < NR_CPUS) { 1141 1142 unsigned long *in, *out, off; 1142 1143 1143 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 1148 if (cpu < NR_CPUS) 1148 1149 prefetch(&per_cpu(page_states, cpu)); ··· 1154 1153 } 1155 1154 } 1156 1155 1157 - void get_page_state(struct page_state *ret) 1156 + void get_page_state_node(struct page_state *ret, int node) 1158 1157 { 1159 1158 int nr; 1159 + cpumask_t mask = node_to_cpumask(node); 1160 1160 1161 1161 nr = offsetof(struct page_state, GET_PAGE_STATE_LAST); 1162 1162 nr /= sizeof(unsigned long); 1163 1163 1164 - __get_page_state(ret, nr + 1); 1164 + __get_page_state(ret, nr+1, &mask); 1165 + } 1166 + 1167 + void get_page_state(struct page_state *ret) 1168 + { 1169 + int nr; 1170 + cpumask_t mask = CPU_MASK_ALL; 1171 + 1172 + nr = offsetof(struct page_state, GET_PAGE_STATE_LAST); 1173 + nr /= sizeof(unsigned long); 1174 + 1175 + __get_page_state(ret, nr + 1, &mask); 1165 1176 } 1166 1177 1167 1178 void get_full_page_state(struct page_state *ret) 1168 1179 { 1169 - __get_page_state(ret, sizeof(*ret) / sizeof(unsigned long)); 1180 + cpumask_t mask = CPU_MASK_ALL; 1181 + 1182 + __get_page_state(ret, sizeof(*ret) / sizeof(unsigned long), &mask); 1170 1183 } 1171 1184 1172 1185 unsigned long __read_page_state(unsigned long offset)