diff options
-rw-r--r-- | drivers/base/node.c | 34 | ||||
-rw-r--r-- | include/linux/mmzone.h | 17 | ||||
-rw-r--r-- | include/linux/vmstat.h | 10 | ||||
-rw-r--r-- | mm/mempolicy.c | 6 | ||||
-rw-r--r-- | mm/page_alloc.c | 23 | ||||
-rw-r--r-- | mm/vmstat.c | 73 |
6 files changed, 73 insertions, 90 deletions
diff --git a/drivers/base/node.c b/drivers/base/node.c index 772eadac57a7..d7de1753e094 100644 --- a/drivers/base/node.c +++ b/drivers/base/node.c | |||
@@ -94,28 +94,6 @@ static SYSDEV_ATTR(meminfo, S_IRUGO, node_read_meminfo, NULL); | |||
94 | 94 | ||
95 | static ssize_t node_read_numastat(struct sys_device * dev, char * buf) | 95 | static ssize_t node_read_numastat(struct sys_device * dev, char * buf) |
96 | { | 96 | { |
97 | unsigned long numa_hit, numa_miss, interleave_hit, numa_foreign; | ||
98 | unsigned long local_node, other_node; | ||
99 | int i, cpu; | ||
100 | pg_data_t *pg = NODE_DATA(dev->id); | ||
101 | numa_hit = 0; | ||
102 | numa_miss = 0; | ||
103 | interleave_hit = 0; | ||
104 | numa_foreign = 0; | ||
105 | local_node = 0; | ||
106 | other_node = 0; | ||
107 | for (i = 0; i < MAX_NR_ZONES; i++) { | ||
108 | struct zone *z = &pg->node_zones[i]; | ||
109 | for_each_online_cpu(cpu) { | ||
110 | struct per_cpu_pageset *ps = zone_pcp(z,cpu); | ||
111 | numa_hit += ps->numa_hit; | ||
112 | numa_miss += ps->numa_miss; | ||
113 | numa_foreign += ps->numa_foreign; | ||
114 | interleave_hit += ps->interleave_hit; | ||
115 | local_node += ps->local_node; | ||
116 | other_node += ps->other_node; | ||
117 | } | ||
118 | } | ||
119 | return sprintf(buf, | 97 | return sprintf(buf, |
120 | "numa_hit %lu\n" | 98 | "numa_hit %lu\n" |
121 | "numa_miss %lu\n" | 99 | "numa_miss %lu\n" |
@@ -123,12 +101,12 @@ static ssize_t node_read_numastat(struct sys_device * dev, char * buf) | |||
123 | "interleave_hit %lu\n" | 101 | "interleave_hit %lu\n" |
124 | "local_node %lu\n" | 102 | "local_node %lu\n" |
125 | "other_node %lu\n", | 103 | "other_node %lu\n", |
126 | numa_hit, | 104 | node_page_state(dev->id, NUMA_HIT), |
127 | numa_miss, | 105 | node_page_state(dev->id, NUMA_MISS), |
128 | numa_foreign, | 106 | node_page_state(dev->id, NUMA_FOREIGN), |
129 | interleave_hit, | 107 | node_page_state(dev->id, NUMA_INTERLEAVE_HIT), |
130 | local_node, | 108 | node_page_state(dev->id, NUMA_LOCAL), |
131 | other_node); | 109 | node_page_state(dev->id, NUMA_OTHER)); |
132 | } | 110 | } |
133 | static SYSDEV_ATTR(numastat, S_IRUGO, node_read_numastat, NULL); | 111 | static SYSDEV_ATTR(numastat, S_IRUGO, node_read_numastat, NULL); |
134 | 112 | ||
diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h index 2dbeec1d2874..27e748eb72b0 100644 --- a/include/linux/mmzone.h +++ b/include/linux/mmzone.h | |||
@@ -57,6 +57,14 @@ enum zone_stat_item { | |||
57 | NR_WRITEBACK, | 57 | NR_WRITEBACK, |
58 | NR_UNSTABLE_NFS, /* NFS unstable pages */ | 58 | NR_UNSTABLE_NFS, /* NFS unstable pages */ |
59 | NR_BOUNCE, | 59 | NR_BOUNCE, |
60 | #ifdef CONFIG_NUMA | ||
61 | NUMA_HIT, /* allocated in intended node */ | ||
62 | NUMA_MISS, /* allocated in non intended node */ | ||
63 | NUMA_FOREIGN, /* was intended here, hit elsewhere */ | ||
64 | NUMA_INTERLEAVE_HIT, /* interleaver preferred this zone */ | ||
65 | NUMA_LOCAL, /* allocation from local node */ | ||
66 | NUMA_OTHER, /* allocation from other node */ | ||
67 | #endif | ||
60 | NR_VM_ZONE_STAT_ITEMS }; | 68 | NR_VM_ZONE_STAT_ITEMS }; |
61 | 69 | ||
62 | struct per_cpu_pages { | 70 | struct per_cpu_pages { |
@@ -71,15 +79,6 @@ struct per_cpu_pageset { | |||
71 | #ifdef CONFIG_SMP | 79 | #ifdef CONFIG_SMP |
72 | s8 vm_stat_diff[NR_VM_ZONE_STAT_ITEMS]; | 80 | s8 vm_stat_diff[NR_VM_ZONE_STAT_ITEMS]; |
73 | #endif | 81 | #endif |
74 | |||
75 | #ifdef CONFIG_NUMA | ||
76 | unsigned long numa_hit; /* allocated in intended node */ | ||
77 | unsigned long numa_miss; /* allocated in non intended node */ | ||
78 | unsigned long numa_foreign; /* was intended here, hit elsewhere */ | ||
79 | unsigned long interleave_hit; /* interleaver prefered this zone */ | ||
80 | unsigned long local_node; /* allocation from local node */ | ||
81 | unsigned long other_node; /* allocation from other node */ | ||
82 | #endif | ||
83 | } ____cacheline_aligned_in_smp; | 82 | } ____cacheline_aligned_in_smp; |
84 | 83 | ||
85 | #ifdef CONFIG_NUMA | 84 | #ifdef CONFIG_NUMA |
diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h index 5fad1613e7d6..16173b63ee67 100644 --- a/include/linux/vmstat.h +++ b/include/linux/vmstat.h | |||
@@ -173,9 +173,15 @@ static inline unsigned long node_page_state(int node, | |||
173 | #endif | 173 | #endif |
174 | zone_page_state(&zones[ZONE_DMA], item); | 174 | zone_page_state(&zones[ZONE_DMA], item); |
175 | } | 175 | } |
176 | |||
177 | extern void zone_statistics(struct zonelist *, struct zone *); | ||
178 | |||
176 | #else | 179 | #else |
180 | |||
177 | #define node_page_state(node, item) global_page_state(item) | 181 | #define node_page_state(node, item) global_page_state(item) |
178 | #endif | 182 | #define zone_statistics(_zl,_z) do { } while (0) |
183 | |||
184 | #endif /* CONFIG_NUMA */ | ||
179 | 185 | ||
180 | #define __add_zone_page_state(__z, __i, __d) \ | 186 | #define __add_zone_page_state(__z, __i, __d) \ |
181 | __mod_zone_page_state(__z, __i, __d) | 187 | __mod_zone_page_state(__z, __i, __d) |
@@ -190,6 +196,8 @@ static inline void zap_zone_vm_stats(struct zone *zone) | |||
190 | memset(zone->vm_stat, 0, sizeof(zone->vm_stat)); | 196 | memset(zone->vm_stat, 0, sizeof(zone->vm_stat)); |
191 | } | 197 | } |
192 | 198 | ||
199 | extern void inc_zone_state(struct zone *, enum zone_stat_item); | ||
200 | |||
193 | #ifdef CONFIG_SMP | 201 | #ifdef CONFIG_SMP |
194 | void __mod_zone_page_state(struct zone *, enum zone_stat_item item, int); | 202 | void __mod_zone_page_state(struct zone *, enum zone_stat_item item, int); |
195 | void __inc_zone_page_state(struct page *, enum zone_stat_item); | 203 | void __inc_zone_page_state(struct page *, enum zone_stat_item); |
diff --git a/mm/mempolicy.c b/mm/mempolicy.c index 6b9740bbf4c0..e07e27e846a2 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c | |||
@@ -1209,10 +1209,8 @@ static struct page *alloc_page_interleave(gfp_t gfp, unsigned order, | |||
1209 | 1209 | ||
1210 | zl = NODE_DATA(nid)->node_zonelists + gfp_zone(gfp); | 1210 | zl = NODE_DATA(nid)->node_zonelists + gfp_zone(gfp); |
1211 | page = __alloc_pages(gfp, order, zl); | 1211 | page = __alloc_pages(gfp, order, zl); |
1212 | if (page && page_zone(page) == zl->zones[0]) { | 1212 | if (page && page_zone(page) == zl->zones[0]) |
1213 | zone_pcp(zl->zones[0],get_cpu())->interleave_hit++; | 1213 | inc_zone_page_state(page, NUMA_INTERLEAVE_HIT); |
1214 | put_cpu(); | ||
1215 | } | ||
1216 | return page; | 1214 | return page; |
1217 | } | 1215 | } |
1218 | 1216 | ||
diff --git a/mm/page_alloc.c b/mm/page_alloc.c index 6aa2c31f513b..d61671260f92 100644 --- a/mm/page_alloc.c +++ b/mm/page_alloc.c | |||
@@ -709,27 +709,6 @@ void drain_local_pages(void) | |||
709 | } | 709 | } |
710 | #endif /* CONFIG_PM */ | 710 | #endif /* CONFIG_PM */ |
711 | 711 | ||
712 | static void zone_statistics(struct zonelist *zonelist, struct zone *z, int cpu) | ||
713 | { | ||
714 | #ifdef CONFIG_NUMA | ||
715 | pg_data_t *pg = z->zone_pgdat; | ||
716 | pg_data_t *orig = zonelist->zones[0]->zone_pgdat; | ||
717 | struct per_cpu_pageset *p; | ||
718 | |||
719 | p = zone_pcp(z, cpu); | ||
720 | if (pg == orig) { | ||
721 | p->numa_hit++; | ||
722 | } else { | ||
723 | p->numa_miss++; | ||
724 | zone_pcp(zonelist->zones[0], cpu)->numa_foreign++; | ||
725 | } | ||
726 | if (pg == NODE_DATA(numa_node_id())) | ||
727 | p->local_node++; | ||
728 | else | ||
729 | p->other_node++; | ||
730 | #endif | ||
731 | } | ||
732 | |||
733 | /* | 712 | /* |
734 | * Free a 0-order page | 713 | * Free a 0-order page |
735 | */ | 714 | */ |
@@ -827,7 +806,7 @@ again: | |||
827 | } | 806 | } |
828 | 807 | ||
829 | __mod_page_state_zone(zone, pgalloc, 1 << order); | 808 | __mod_page_state_zone(zone, pgalloc, 1 << order); |
830 | zone_statistics(zonelist, zone, cpu); | 809 | zone_statistics(zonelist, zone); |
831 | local_irq_restore(flags); | 810 | local_irq_restore(flags); |
832 | put_cpu(); | 811 | put_cpu(); |
833 | 812 | ||
diff --git a/mm/vmstat.c b/mm/vmstat.c index 06a6d1052198..ee7f89666250 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c | |||
@@ -185,9 +185,8 @@ EXPORT_SYMBOL(mod_zone_page_state); | |||
185 | * in between and therefore the atomicity vs. interrupt cannot be exploited | 185 | * in between and therefore the atomicity vs. interrupt cannot be exploited |
186 | * in a useful way here. | 186 | * in a useful way here. |
187 | */ | 187 | */ |
188 | void __inc_zone_page_state(struct page *page, enum zone_stat_item item) | 188 | static void __inc_zone_state(struct zone *zone, enum zone_stat_item item) |
189 | { | 189 | { |
190 | struct zone *zone = page_zone(page); | ||
191 | s8 *p = diff_pointer(zone, item); | 190 | s8 *p = diff_pointer(zone, item); |
192 | 191 | ||
193 | (*p)++; | 192 | (*p)++; |
@@ -197,6 +196,11 @@ void __inc_zone_page_state(struct page *page, enum zone_stat_item item) | |||
197 | *p = 0; | 196 | *p = 0; |
198 | } | 197 | } |
199 | } | 198 | } |
199 | |||
200 | void __inc_zone_page_state(struct page *page, enum zone_stat_item item) | ||
201 | { | ||
202 | __inc_zone_state(page_zone(page), item); | ||
203 | } | ||
200 | EXPORT_SYMBOL(__inc_zone_page_state); | 204 | EXPORT_SYMBOL(__inc_zone_page_state); |
201 | 205 | ||
202 | void __dec_zone_page_state(struct page *page, enum zone_stat_item item) | 206 | void __dec_zone_page_state(struct page *page, enum zone_stat_item item) |
@@ -213,22 +217,23 @@ void __dec_zone_page_state(struct page *page, enum zone_stat_item item) | |||
213 | } | 217 | } |
214 | EXPORT_SYMBOL(__dec_zone_page_state); | 218 | EXPORT_SYMBOL(__dec_zone_page_state); |
215 | 219 | ||
220 | void inc_zone_state(struct zone *zone, enum zone_stat_item item) | ||
221 | { | ||
222 | unsigned long flags; | ||
223 | |||
224 | local_irq_save(flags); | ||
225 | __inc_zone_state(zone, item); | ||
226 | local_irq_restore(flags); | ||
227 | } | ||
228 | |||
216 | void inc_zone_page_state(struct page *page, enum zone_stat_item item) | 229 | void inc_zone_page_state(struct page *page, enum zone_stat_item item) |
217 | { | 230 | { |
218 | unsigned long flags; | 231 | unsigned long flags; |
219 | struct zone *zone; | 232 | struct zone *zone; |
220 | s8 *p; | ||
221 | 233 | ||
222 | zone = page_zone(page); | 234 | zone = page_zone(page); |
223 | local_irq_save(flags); | 235 | local_irq_save(flags); |
224 | p = diff_pointer(zone, item); | 236 | __inc_zone_state(zone, item); |
225 | |||
226 | (*p)++; | ||
227 | |||
228 | if (unlikely(*p > STAT_THRESHOLD)) { | ||
229 | zone_page_state_add(*p, zone, item); | ||
230 | *p = 0; | ||
231 | } | ||
232 | local_irq_restore(flags); | 237 | local_irq_restore(flags); |
233 | } | 238 | } |
234 | EXPORT_SYMBOL(inc_zone_page_state); | 239 | EXPORT_SYMBOL(inc_zone_page_state); |
@@ -297,6 +302,28 @@ EXPORT_SYMBOL(refresh_vm_stats); | |||
297 | 302 | ||
298 | #endif | 303 | #endif |
299 | 304 | ||
305 | #ifdef CONFIG_NUMA | ||
306 | /* | ||
307 | * zonelist = the list of zones passed to the allocator | ||
308 | * z = the zone from which the allocation occurred. | ||
309 | * | ||
310 | * Must be called with interrupts disabled. | ||
311 | */ | ||
312 | void zone_statistics(struct zonelist *zonelist, struct zone *z) | ||
313 | { | ||
314 | if (z->zone_pgdat == zonelist->zones[0]->zone_pgdat) { | ||
315 | __inc_zone_state(z, NUMA_HIT); | ||
316 | } else { | ||
317 | __inc_zone_state(z, NUMA_MISS); | ||
318 | __inc_zone_state(zonelist->zones[0], NUMA_FOREIGN); | ||
319 | } | ||
320 | if (z->zone_pgdat == NODE_DATA(numa_node_id())) | ||
321 | __inc_zone_state(z, NUMA_LOCAL); | ||
322 | else | ||
323 | __inc_zone_state(z, NUMA_OTHER); | ||
324 | } | ||
325 | #endif | ||
326 | |||
300 | #ifdef CONFIG_PROC_FS | 327 | #ifdef CONFIG_PROC_FS |
301 | 328 | ||
302 | #include <linux/seq_file.h> | 329 | #include <linux/seq_file.h> |
@@ -369,6 +396,15 @@ static char *vmstat_text[] = { | |||
369 | "nr_unstable", | 396 | "nr_unstable", |
370 | "nr_bounce", | 397 | "nr_bounce", |
371 | 398 | ||
399 | #ifdef CONFIG_NUMA | ||
400 | "numa_hit", | ||
401 | "numa_miss", | ||
402 | "numa_foreign", | ||
403 | "numa_interleave", | ||
404 | "numa_local", | ||
405 | "numa_other", | ||
406 | #endif | ||
407 | |||
372 | /* Event counters */ | 408 | /* Event counters */ |
373 | "pgpgin", | 409 | "pgpgin", |
374 | "pgpgout", | 410 | "pgpgout", |
@@ -490,21 +526,6 @@ static int zoneinfo_show(struct seq_file *m, void *arg) | |||
490 | pageset->pcp[j].high, | 526 | pageset->pcp[j].high, |
491 | pageset->pcp[j].batch); | 527 | pageset->pcp[j].batch); |
492 | } | 528 | } |
493 | #ifdef CONFIG_NUMA | ||
494 | seq_printf(m, | ||
495 | "\n numa_hit: %lu" | ||
496 | "\n numa_miss: %lu" | ||
497 | "\n numa_foreign: %lu" | ||
498 | "\n interleave_hit: %lu" | ||
499 | "\n local_node: %lu" | ||
500 | "\n other_node: %lu", | ||
501 | pageset->numa_hit, | ||
502 | pageset->numa_miss, | ||
503 | pageset->numa_foreign, | ||
504 | pageset->interleave_hit, | ||
505 | pageset->local_node, | ||
506 | pageset->other_node); | ||
507 | #endif | ||
508 | } | 529 | } |
509 | seq_printf(m, | 530 | seq_printf(m, |
510 | "\n all_unreclaimable: %u" | 531 | "\n all_unreclaimable: %u" |