struct page_state is large (148 bytes) and we put them on the stack in awkward
code paths (page reclaim...)

So implement a simple read_page_state() which can be used to pluck out a
single member from the all-cpus page_state accumulators.

Signed-off-by: Andrew Morton <akpm@osdl.org>
---

 25-akpm/include/linux/page-flags.h |    4 ++++
 25-akpm/mm/page_alloc.c            |   19 +++++++++++++++++++
 2 files changed, 23 insertions(+)

diff -puN include/linux/page-flags.h~read_page_state include/linux/page-flags.h
--- 25/include/linux/page-flags.h~read_page_state	2004-06-08 17:36:32.171143208 -0700
+++ 25-akpm/include/linux/page-flags.h	2004-06-08 17:36:32.176142448 -0700
@@ -139,6 +139,10 @@ DECLARE_PER_CPU(struct page_state, page_
 
 extern void get_page_state(struct page_state *ret);
 extern void get_full_page_state(struct page_state *ret);
+extern unsigned long __read_page_state(unsigned offset);
+
+#define read_page_state(member) \
+	__read_page_state(offsetof(struct page_state, member))
 
 #define mod_page_state(member, delta)					\
 	do {								\
diff -puN mm/page_alloc.c~read_page_state mm/page_alloc.c
--- 25/mm/page_alloc.c~read_page_state	2004-06-08 17:36:32.173142904 -0700
+++ 25-akpm/mm/page_alloc.c	2004-06-08 18:17:09.013686832 -0700
@@ -947,6 +947,25 @@ void get_full_page_state(struct page_sta
 	__get_page_state(ret, sizeof(*ret) / sizeof(unsigned long));
 }
 
+unsigned long __read_page_state(unsigned offset)
+{
+	unsigned long ret = 0;
+	int cpu = 0;
+
+	offset /= sizeof(unsigned long);
+
+	for (cpu = 0; cpu < NR_CPUS; cpu++) {
+		unsigned long *in;
+
+		if (!cpu_possible(cpu))
+			continue;
+
+		in = (unsigned long *)&per_cpu(page_states, cpu);
+		ret += in[offset];
+	}
+	return ret;
+}
+
 void get_zone_counts(unsigned long *active,
 		unsigned long *inactive, unsigned long *free)
 {
_