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 --- 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) { _