struct per_cpu_pageset {
struct per_cpu_pages pcp[2]; /* 0: hot. 1: cold */
+#ifdef CONFIG_NUMA
+ unsigned long numa_hit; /* allocated in intended node */
+ unsigned long numa_miss; /* allocated in non intended node */
+ unsigned long numa_foreign; /* was intended here, hit elsewhere */
+ unsigned long interleave_hit; /* interleaver prefered this zone */
+ unsigned long local_node; /* allocation from local node */
+ unsigned long other_node; /* allocation from other node */
+#endif
} ____cacheline_aligned_in_smp;
#define ZONE_DMA 0
}
#endif /* CONFIG_PM */
+static void zone_statistics(struct zonelist *zonelist, struct zone *z)
+{
+#ifdef CONFIG_NUMA
+ unsigned long flags;
+ int cpu;
+ pg_data_t *pg = z->zone_pgdat;
+ pg_data_t *orig = zonelist->zones[0]->zone_pgdat;
+ struct per_cpu_pageset *p;
+
+ local_irq_save(flags);
+ cpu = smp_processor_id();
+ p = &z->pageset[cpu];
+ if (pg == orig) {
+ z->pageset[cpu].numa_hit++;
+ } else {
+ p->numa_miss++;
+ zonelist->zones[0]->pageset[cpu].numa_foreign++;
+ }
+ if (pg == NODE_DATA(numa_node_id()))
+ p->local_node++;
+ else
+ p->other_node++;
+ local_irq_restore(flags);
+#endif
+}
+
/*
* Free a 0-order page
*/
if (z->free_pages >= min ||
(!wait && z->free_pages >= z->pages_high)) {
page = buffered_rmqueue(z, order, gfp_mask);
- if (page)
+ if (page) {
+ zone_statistics(zonelist, z);
goto got_pg;
+ }
}
}
if (z->free_pages >= min ||
(!wait && z->free_pages >= z->pages_high)) {
page = buffered_rmqueue(z, order, gfp_mask);
- if (page)
+ if (page) {
+ zone_statistics(zonelist, z);
goto got_pg;
+ }
}
}
struct zone *z = zones[i];
page = buffered_rmqueue(z, order, gfp_mask);
- if (page)
+ if (page) {
+ zone_statistics(zonelist, z);
goto got_pg;
+ }
}
goto nopage;
}
if (z->free_pages >= min ||
(!wait && z->free_pages >= z->pages_high)) {
page = buffered_rmqueue(z, order, gfp_mask);
- if (page)
+ if (page) {
+ zone_statistics(zonelist, z);
goto got_pg;
+ }
}
}