All of lore.kernel.org
 help / color / mirror / Atom feed
diff for duplicates of <20170716132909.GB757@castle>

diff --git a/a/1.txt b/N1/1.txt
index 8b13789..4b671fe 100644
--- a/a/1.txt
+++ b/N1/1.txt
@@ -1 +1,451 @@
+>From 36c6f4d293469569ca8b53b89ab8eebd358a5fa5 Mon Sep 17 00:00:00 2001
+From: Roman Gushchin <guro@fb.com>
+Date: Mon, 3 Jul 2017 19:02:49 +0100
+Subject: [v2] mm: make allocation counters per-order
 
+High-order allocations are obviously more costly, and it's very useful
+to know how many of them happens, if there are any issues
+(or suspicions) with memory fragmentation.
+
+This commit changes existing per-zone allocation counters to be
+per-zone per-order. These counters are displayed using a new
+procfs interface (similar to /proc/buddyinfo):
+
+$ cat /proc/allocinfo
+     DMA          0          0          0          0          0 \
+       0          0          0          0          0          0
+   DMA32          3          0          1          0          0 \
+       0          0          0          0          0          0
+  Normal    4997056      23594      10902      23686        931 \
+      23        122        786         17          1          0
+ Movable          0          0          0          0          0 \
+       0          0          0          0          0          0
+  Device          0          0          0          0          0 \
+       0          0          0          0          0          0
+
+The existing vmstat interface remains untouched*, and still shows
+the total number of single page allocations, so high-order allocations
+are represented as a corresponding number of order-0 allocations.
+
+$ cat /proc/vmstat | grep alloc
+pgalloc_dma 0
+pgalloc_dma32 7
+pgalloc_normal 5461660
+pgalloc_movable 0
+pgalloc_device 0
+
+* I've added device zone for consistency with other zones,
+and to avoid messy exclusion of this zone in the code.
+
+v2:
+The functionality can be enabled/disabled by the PER_ORDER_ALLOC_COUNTERS
+config option.
+
+Signed-off-by: Roman Gushchin <guro@fb.com>
+Suggested-by: Johannes Weiner <hannes@cmpxchg.org>
+Cc: Debabrata Banerjee <dbavatar@gmail.com>
+Cc: Andrew Morton <akpm@linux-foundation.org>
+Cc: Mel Gorman <mgorman@techsingularity.net>
+Cc: Johannes Weiner <hannes@cmpxchg.org>
+Cc: Michal Hocko <mhocko@suse.com>
+Cc: Vladimir Davydov <vdavydov.dev@gmail.com>
+Cc: Rik van Riel <riel@redhat.com>
+Cc: kernel-team@fb.com
+Cc: linux-mm@kvack.org
+Cc: linux-kernel@vger.kernel.org
+---
+ arch/s390/appldata/appldata_mem.c |  16 +++++
+ include/linux/mmzone.h            |   2 +
+ include/linux/vm_event_item.h     |  27 ++++++--
+ include/linux/vmstat.h            |  20 ++++++
+ init/Kconfig                      |   9 +++
+ mm/page_alloc.c                   |  11 +++-
+ mm/vmstat.c                       | 128 +++++++++++++++++++++++++++++++++++---
+ 7 files changed, 199 insertions(+), 14 deletions(-)
+
+diff --git a/arch/s390/appldata/appldata_mem.c b/arch/s390/appldata/appldata_mem.c
+index 598df57..79679d3 100644
+--- a/arch/s390/appldata/appldata_mem.c
++++ b/arch/s390/appldata/appldata_mem.c
+@@ -66,6 +66,21 @@ struct appldata_mem_data {
+ 
+ } __packed;
+ 
++#ifdef CONFIG_PER_ORDER_ALLOC_COUNTERS
++static inline sum_pgalloc_events(u64 *pgalloc, unsigned long *ev)
++{
++	int order;
++
++	for (order = 1; order < MAX_ORDER; ++order) {
++		pgalloc += ev[PGALLOC_NORMAL + order * MAX_NR_ZONES] << order;
++		pgalloc += ev[PGALLOC_DMA + order * MAX_NR_ZONES] << order;
++	}
++}
++#else
++static inline sum_pgalloc_events(u64 *pgalloc, unsigned long *ev)
++{
++}
++#endif
+ 
+ /*
+  * appldata_get_mem_data()
+@@ -92,6 +107,7 @@ static void appldata_get_mem_data(void *data)
+ 	mem_data->pswpout    = ev[PSWPOUT];
+ 	mem_data->pgalloc    = ev[PGALLOC_NORMAL];
+ 	mem_data->pgalloc    += ev[PGALLOC_DMA];
++	sum_pgalloc_events(&mem_data->pgalloc, ev);
+ 	mem_data->pgfault    = ev[PGFAULT];
+ 	mem_data->pgmajfault = ev[PGMAJFAULT];
+ 
+diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h
+index fc14b8b..406dfc4 100644
+--- a/include/linux/mmzone.h
++++ b/include/linux/mmzone.h
+@@ -66,6 +66,8 @@ enum migratetype {
+ /* In mm/page_alloc.c; keep in sync also with show_migration_types() there */
+ extern char * const migratetype_names[MIGRATE_TYPES];
+ 
++extern const char *zone_name(int idx);
++
+ #ifdef CONFIG_CMA
+ #  define is_migrate_cma(migratetype) unlikely((migratetype) == MIGRATE_CMA)
+ #  define is_migrate_cma_page(_page) (get_pageblock_migratetype(_page) == MIGRATE_CMA)
+diff --git a/include/linux/vm_event_item.h b/include/linux/vm_event_item.h
+index 37e8d31..da94618 100644
+--- a/include/linux/vm_event_item.h
++++ b/include/linux/vm_event_item.h
+@@ -19,12 +19,31 @@
+ #define HIGHMEM_ZONE(xx)
+ #endif
+ 
+-#define FOR_ALL_ZONES(xx) DMA_ZONE(xx) DMA32_ZONE(xx) xx##_NORMAL, HIGHMEM_ZONE(xx) xx##_MOVABLE
++#ifdef CONFIG_ZONE_DEVICE
++#define DEVICE_ZONE(xx) xx##__DEVICE,
++#else
++#define DEVICE_ZONE(xx)
++#endif
++
++#define FOR_ALL_ZONES(xx) DMA_ZONE(xx) DMA32_ZONE(xx) xx##_NORMAL, HIGHMEM_ZONE(xx) xx##_MOVABLE, DEVICE_ZONE(xx)
++
++#ifdef CONFIG_PER_ORDER_ALLOC_COUNTERS
++#define PGALLOC_EVENTS_SIZE (MAX_NR_ZONES * MAX_ORDER)
++#define PGALLOC_EVENTS_CUT_SIZE (MAX_NR_ZONES * (MAX_ORDER - 1))
++#define PGALLOC_FIRST_ZONE (PGALLOC_NORMAL - ZONE_NORMAL)
++#else
++#define PGALLOC_EVENTS_SIZE MAX_NR_ZONES
++#define PGALLOC_EVENTS_CUT_SIZE 0
++#define PGALLOC_FIRST_ZONE (PGALLOC_NORMAL - ZONE_NORMAL)
++#endif
+ 
+ enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,
+-		FOR_ALL_ZONES(PGALLOC),
+-		FOR_ALL_ZONES(ALLOCSTALL),
+-		FOR_ALL_ZONES(PGSCAN_SKIP),
++		FOR_ALL_ZONES(PGALLOC)
++#ifdef CONFIG_PER_ORDER_ALLOC_COUNTERS
++		__PGALLOC_LAST = PGALLOC_FIRST_ZONE + PGALLOC_EVENTS_SIZE - 1,
++#endif
++		FOR_ALL_ZONES(ALLOCSTALL)
++		FOR_ALL_ZONES(PGSCAN_SKIP)
+ 		PGFREE, PGACTIVATE, PGDEACTIVATE, PGLAZYFREE,
+ 		PGFAULT, PGMAJFAULT,
+ 		PGLAZYFREED,
+diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h
+index b3d85f3..bca96fc 100644
+--- a/include/linux/vmstat.h
++++ b/include/linux/vmstat.h
+@@ -103,6 +103,26 @@ static inline void vm_events_fold_cpu(int cpu)
+ #define __count_zid_vm_events(item, zid, delta) \
+ 	__count_vm_events(item##_NORMAL - ZONE_NORMAL + zid, delta)
+ 
++#ifdef CONFIG_PER_ORDER_ALLOC_COUNTERS
++static inline void __count_alloc_event(enum zone_type zid, unsigned int order)
++{
++	enum vm_event_item item;
++
++	if (unlikely(order >= MAX_ORDER)) {
++		WARN_ON_ONCE(1);
++		return;
++	}
++
++	item = PGALLOC_FIRST_ZONE + order * MAX_NR_ZONES + zid;
++	__count_vm_events(item, 1);
++}
++#else
++static inline void __count_alloc_event(enum zone_type zid, unsigned int order)
++{
++	__count_zid_vm_events(PGALLOC, zid, 1 << order);
++}
++#endif
++
+ /*
+  * Zone and node-based page accounting with per cpu differentials.
+  */
+diff --git a/init/Kconfig b/init/Kconfig
+index 8514b25..164d6f0 100644
+--- a/init/Kconfig
++++ b/init/Kconfig
+@@ -1477,6 +1477,15 @@ config VM_EVENT_COUNTERS
+ 	  on EXPERT systems.  /proc/vmstat will only show page counts
+ 	  if VM event counters are disabled.
+ 
++config PER_ORDER_ALLOC_COUNTERS
++	bool "Per-order memory allocation counters"
++	depends on VM_EVENT_COUNTERS && PROC_FS
++	help
++	  This option enables splitting per-zone allocation counters
++	  into per-zone per-order counters.
++	  Per-order counters are exported using the /proc/allocinfo
++	  interface, and /proc/vmstat shows accumulated values.
++
+ config SLUB_DEBUG
+ 	default y
+ 	bool "Enable SLUB debugging support" if EXPERT
+diff --git a/mm/page_alloc.c b/mm/page_alloc.c
+index 80e4adb..e74b327 100644
+--- a/mm/page_alloc.c
++++ b/mm/page_alloc.c
+@@ -233,6 +233,13 @@ static char * const zone_names[MAX_NR_ZONES] = {
+ #endif
+ };
+ 
++const char *zone_name(int zid)
++{
++	if (zid < MAX_NR_ZONES)
++		return zone_names[zid];
++	return NULL;
++}
++
+ char * const migratetype_names[MIGRATE_TYPES] = {
+ 	"Unmovable",
+ 	"Movable",
+@@ -2779,7 +2786,7 @@ static struct page *rmqueue_pcplist(struct zone *preferred_zone,
+ 	list = &pcp->lists[migratetype];
+ 	page = __rmqueue_pcplist(zone,  migratetype, cold, pcp, list);
+ 	if (page) {
+-		__count_zid_vm_events(PGALLOC, page_zonenum(page), 1 << order);
++		__count_alloc_event(page_zonenum(page), order);
+ 		zone_statistics(preferred_zone, zone);
+ 	}
+ 	local_irq_restore(flags);
+@@ -2827,7 +2834,7 @@ struct page *rmqueue(struct zone *preferred_zone,
+ 	__mod_zone_freepage_state(zone, -(1 << order),
+ 				  get_pcppage_migratetype(page));
+ 
+-	__count_zid_vm_events(PGALLOC, page_zonenum(page), 1 << order);
++	__count_alloc_event(page_zonenum(page), order);
+ 	zone_statistics(preferred_zone, zone);
+ 	local_irq_restore(flags);
+ 
+diff --git a/mm/vmstat.c b/mm/vmstat.c
+index 9a4441b..1d468ed 100644
+--- a/mm/vmstat.c
++++ b/mm/vmstat.c
+@@ -27,6 +27,7 @@
+ #include <linux/mm_inline.h>
+ #include <linux/page_ext.h>
+ #include <linux/page_owner.h>
++#include <linux/mmzone.h>
+ 
+ #include "internal.h"
+ 
+@@ -34,18 +35,18 @@
+ DEFINE_PER_CPU(struct vm_event_state, vm_event_states) = {{0}};
+ EXPORT_PER_CPU_SYMBOL(vm_event_states);
+ 
+-static void sum_vm_events(unsigned long *ret)
++static void sum_vm_events(unsigned long *ret, int off, size_t nr_events)
+ {
+ 	int cpu;
+ 	int i;
+ 
+-	memset(ret, 0, NR_VM_EVENT_ITEMS * sizeof(unsigned long));
++	memset(ret, 0, nr_events * sizeof(unsigned long));
+ 
+ 	for_each_online_cpu(cpu) {
+ 		struct vm_event_state *this = &per_cpu(vm_event_states, cpu);
+ 
+-		for (i = 0; i < NR_VM_EVENT_ITEMS; i++)
+-			ret[i] += this->event[i];
++		for (i = 0; i < nr_events; i++)
++			ret[i] += this->event[off + i];
+ 	}
+ }
+ 
+@@ -57,7 +58,7 @@ static void sum_vm_events(unsigned long *ret)
+ void all_vm_events(unsigned long *ret)
+ {
+ 	get_online_cpus();
+-	sum_vm_events(ret);
++	sum_vm_events(ret, 0, NR_VM_EVENT_ITEMS);
+ 	put_online_cpus();
+ }
+ EXPORT_SYMBOL_GPL(all_vm_events);
+@@ -915,8 +916,15 @@ int fragmentation_index(struct zone *zone, unsigned int order)
+ #define TEXT_FOR_HIGHMEM(xx)
+ #endif
+ 
++#ifdef CONFIG_ZONE_DEVICE
++#define TEXT_FOR_DEVICE(xx) xx "_device",
++#else
++#define TEXT_FOR_DEVICE(xx)
++#endif
++
+ #define TEXTS_FOR_ZONES(xx) TEXT_FOR_DMA(xx) TEXT_FOR_DMA32(xx) xx "_normal", \
+-					TEXT_FOR_HIGHMEM(xx) xx "_movable",
++					TEXT_FOR_HIGHMEM(xx) xx "_movable", \
++					TEXT_FOR_DEVICE(xx)
+ 
+ const char * const vmstat_text[] = {
+ 	/* enum zone_stat_item countes */
+@@ -1480,12 +1488,92 @@ enum writeback_stat_item {
+ 	NR_VM_WRITEBACK_STAT_ITEMS,
+ };
+ 
++#ifdef CONFIG_PER_ORDER_ALLOC_COUNTERS
++static void sum_alloc_events(unsigned long *v)
++{
++	int zid, order, index;
++
++	for (zid = 0; zid < MAX_NR_ZONES; ++zid) {
++		for (order = 1; order < MAX_ORDER; order++) {
++			index = PGALLOC_FIRST_ZONE + zid;
++			v[index] += v[index + order * MAX_NR_ZONES] << order;
++		}
++	}
++}
++
++static int allocinfo_show(struct seq_file *m, void *arg)
++{
++	unsigned long allocs[PGALLOC_EVENTS_SIZE];
++	unsigned int order;
++	int zid;
++
++	if (arg != SEQ_START_TOKEN)
++		return 0;
++
++	get_online_cpus();
++	sum_vm_events(allocs, PGALLOC_FIRST_ZONE, PGALLOC_EVENTS_SIZE);
++	put_online_cpus();
++
++	for (zid = 0; zid < MAX_NR_ZONES; ++zid) {
++		seq_printf(m, "%8s ", zone_name(zid));
++
++		for (order = 0; order < MAX_ORDER; order++)
++			seq_printf(m, "%10lu ",
++				   allocs[zid + order * MAX_NR_ZONES]);
++
++		seq_putc(m, '\n');
++	}
++
++	return 0;
++}
++
++static void *allocinfo_start(struct seq_file *m, loff_t *pos)
++{
++	if (*pos)
++		return NULL;
++	return SEQ_START_TOKEN;
++}
++
++static void *allocinfo_next(struct seq_file *m, void *arg, loff_t *pos)
++{
++	++*pos;
++	return NULL;
++}
++
++static void allocinfo_stop(struct seq_file *m, void *arg)
++{
++}
++
++static const struct seq_operations allocinfo_op = {
++	.start	= allocinfo_start,
++	.next	= allocinfo_next,
++	.stop	= allocinfo_stop,
++	.show	= allocinfo_show,
++};
++
++static int allocinfo_open(struct inode *inode, struct file *file)
++{
++	return seq_open(file, &allocinfo_op);
++}
++
++static const struct file_operations allocinfo_file_operations = {
++	.open		= allocinfo_open,
++	.read		= seq_read,
++	.llseek		= seq_lseek,
++	.release	= seq_release,
++};
++#else
++static void sum_alloc_events(unsigned long *v)
++{
++}
++#endif
++
+ static void *vmstat_start(struct seq_file *m, loff_t *pos)
+ {
+ 	unsigned long *v;
+ 	int i, stat_items_size;
+ 
+-	if (*pos >= ARRAY_SIZE(vmstat_text))
++	if (*pos >= ARRAY_SIZE(vmstat_text) + PGALLOC_EVENTS_CUT_SIZE)
+ 		return NULL;
+ 	stat_items_size = NR_VM_ZONE_STAT_ITEMS * sizeof(unsigned long) +
+ 			  NR_VM_NODE_STAT_ITEMS * sizeof(unsigned long) +
+@@ -1513,6 +1601,7 @@ static void *vmstat_start(struct seq_file *m, loff_t *pos)
+ 
+ #ifdef CONFIG_VM_EVENT_COUNTERS
+ 	all_vm_events(v);
++	sum_alloc_events(v);
+ 	v[PGPGIN] /= 2;		/* sectors -> kbytes */
+ 	v[PGPGOUT] /= 2;
+ #endif
+@@ -1521,8 +1610,16 @@ static void *vmstat_start(struct seq_file *m, loff_t *pos)
+ 
+ static void *vmstat_next(struct seq_file *m, void *arg, loff_t *pos)
+ {
++	int alloc_event_start = NR_VM_ZONE_STAT_ITEMS +
++		NR_VM_NODE_STAT_ITEMS +
++		NR_VM_WRITEBACK_STAT_ITEMS +
++		PGALLOC_FIRST_ZONE;
++
+ 	(*pos)++;
+-	if (*pos >= ARRAY_SIZE(vmstat_text))
++	if (*pos == alloc_event_start + MAX_NR_ZONES)
++		*(pos) += PGALLOC_EVENTS_CUT_SIZE;
++
++	if (*pos >= ARRAY_SIZE(vmstat_text) + PGALLOC_EVENTS_CUT_SIZE)
+ 		return NULL;
+ 	return (unsigned long *)m->private + *pos;
+ }
+@@ -1531,6 +1628,18 @@ static int vmstat_show(struct seq_file *m, void *arg)
+ {
+ 	unsigned long *l = arg;
+ 	unsigned long off = l - (unsigned long *)m->private;
++	int alloc_event_start = NR_VM_ZONE_STAT_ITEMS +
++		NR_VM_NODE_STAT_ITEMS +
++		NR_VM_WRITEBACK_STAT_ITEMS +
++		PGALLOC_FIRST_ZONE;
++
++	if (off >= alloc_event_start + PGALLOC_EVENTS_SIZE)
++		off -= PGALLOC_EVENTS_CUT_SIZE;
++
++	if (unlikely(off >= sizeof(vmstat_text))) {
++		WARN_ON_ONCE(1);
++		return 0;
++	}
+ 
+ 	seq_puts(m, vmstat_text[off]);
+ 	seq_put_decimal_ull(m, " ", *l);
+@@ -1790,6 +1899,9 @@ void __init init_mm_internals(void)
+ #endif
+ #ifdef CONFIG_PROC_FS
+ 	proc_create("buddyinfo", 0444, NULL, &buddyinfo_file_operations);
++#ifdef CONFIG_PER_ORDER_ALLOC_COUNTERS
++	proc_create("allocinfo", 0444, NULL, &allocinfo_file_operations);
++#endif
+ 	proc_create("pagetypeinfo", 0444, NULL, &pagetypeinfo_file_operations);
+ 	proc_create("vmstat", 0444, NULL, &vmstat_file_operations);
+ 	proc_create("zoneinfo", 0444, NULL, &zoneinfo_file_operations);
+-- 
+2.7.4
diff --git a/a/content_digest b/N1/content_digest
index 8472766..92ed6dc 100644
--- a/a/content_digest
+++ b/N1/content_digest
@@ -6,15 +6,466 @@
  "Subject\0Re: [PATCH] mm: make allocation counters per-order\0"
  "Date\0Sun, 16 Jul 2017 14:29:09 +0100\0"
  "To\0Mel Gorman <mgorman@techsingularity.net>\0"
- "Cc\0linux-mm@kvack.org"
+ "Cc\0<linux-mm@kvack.org>"
   Andrew Morton <akpm@linux-foundation.org>
   Johannes Weiner <hannes@cmpxchg.org>
   Michal Hocko <mhocko@suse.com>
   Vladimir Davydov <vdavydov.dev@gmail.com>
   Rik van Riel <riel@redhat.com>
-  kernel-team@fb.com
- " linux-kernel@vger.kernel.org\0"
+  <kernel-team@fb.com>
+ " <linux-kernel@vger.kernel.org>\0"
  "\00:1\0"
  "b\0"
+ ">From 36c6f4d293469569ca8b53b89ab8eebd358a5fa5 Mon Sep 17 00:00:00 2001\n"
+ "From: Roman Gushchin <guro@fb.com>\n"
+ "Date: Mon, 3 Jul 2017 19:02:49 +0100\n"
+ "Subject: [v2] mm: make allocation counters per-order\n"
+ "\n"
+ "High-order allocations are obviously more costly, and it's very useful\n"
+ "to know how many of them happens, if there are any issues\n"
+ "(or suspicions) with memory fragmentation.\n"
+ "\n"
+ "This commit changes existing per-zone allocation counters to be\n"
+ "per-zone per-order. These counters are displayed using a new\n"
+ "procfs interface (similar to /proc/buddyinfo):\n"
+ "\n"
+ "$ cat /proc/allocinfo\n"
+ "     DMA          0          0          0          0          0 \\\n"
+ "       0          0          0          0          0          0\n"
+ "   DMA32          3          0          1          0          0 \\\n"
+ "       0          0          0          0          0          0\n"
+ "  Normal    4997056      23594      10902      23686        931 \\\n"
+ "      23        122        786         17          1          0\n"
+ " Movable          0          0          0          0          0 \\\n"
+ "       0          0          0          0          0          0\n"
+ "  Device          0          0          0          0          0 \\\n"
+ "       0          0          0          0          0          0\n"
+ "\n"
+ "The existing vmstat interface remains untouched*, and still shows\n"
+ "the total number of single page allocations, so high-order allocations\n"
+ "are represented as a corresponding number of order-0 allocations.\n"
+ "\n"
+ "$ cat /proc/vmstat | grep alloc\n"
+ "pgalloc_dma 0\n"
+ "pgalloc_dma32 7\n"
+ "pgalloc_normal 5461660\n"
+ "pgalloc_movable 0\n"
+ "pgalloc_device 0\n"
+ "\n"
+ "* I've added device zone for consistency with other zones,\n"
+ "and to avoid messy exclusion of this zone in the code.\n"
+ "\n"
+ "v2:\n"
+ "The functionality can be enabled/disabled by the PER_ORDER_ALLOC_COUNTERS\n"
+ "config option.\n"
+ "\n"
+ "Signed-off-by: Roman Gushchin <guro@fb.com>\n"
+ "Suggested-by: Johannes Weiner <hannes@cmpxchg.org>\n"
+ "Cc: Debabrata Banerjee <dbavatar@gmail.com>\n"
+ "Cc: Andrew Morton <akpm@linux-foundation.org>\n"
+ "Cc: Mel Gorman <mgorman@techsingularity.net>\n"
+ "Cc: Johannes Weiner <hannes@cmpxchg.org>\n"
+ "Cc: Michal Hocko <mhocko@suse.com>\n"
+ "Cc: Vladimir Davydov <vdavydov.dev@gmail.com>\n"
+ "Cc: Rik van Riel <riel@redhat.com>\n"
+ "Cc: kernel-team@fb.com\n"
+ "Cc: linux-mm@kvack.org\n"
+ "Cc: linux-kernel@vger.kernel.org\n"
+ "---\n"
+ " arch/s390/appldata/appldata_mem.c |  16 +++++\n"
+ " include/linux/mmzone.h            |   2 +\n"
+ " include/linux/vm_event_item.h     |  27 ++++++--\n"
+ " include/linux/vmstat.h            |  20 ++++++\n"
+ " init/Kconfig                      |   9 +++\n"
+ " mm/page_alloc.c                   |  11 +++-\n"
+ " mm/vmstat.c                       | 128 +++++++++++++++++++++++++++++++++++---\n"
+ " 7 files changed, 199 insertions(+), 14 deletions(-)\n"
+ "\n"
+ "diff --git a/arch/s390/appldata/appldata_mem.c b/arch/s390/appldata/appldata_mem.c\n"
+ "index 598df57..79679d3 100644\n"
+ "--- a/arch/s390/appldata/appldata_mem.c\n"
+ "+++ b/arch/s390/appldata/appldata_mem.c\n"
+ "@@ -66,6 +66,21 @@ struct appldata_mem_data {\n"
+ " \n"
+ " } __packed;\n"
+ " \n"
+ "+#ifdef CONFIG_PER_ORDER_ALLOC_COUNTERS\n"
+ "+static inline sum_pgalloc_events(u64 *pgalloc, unsigned long *ev)\n"
+ "+{\n"
+ "+\tint order;\n"
+ "+\n"
+ "+\tfor (order = 1; order < MAX_ORDER; ++order) {\n"
+ "+\t\tpgalloc += ev[PGALLOC_NORMAL + order * MAX_NR_ZONES] << order;\n"
+ "+\t\tpgalloc += ev[PGALLOC_DMA + order * MAX_NR_ZONES] << order;\n"
+ "+\t}\n"
+ "+}\n"
+ "+#else\n"
+ "+static inline sum_pgalloc_events(u64 *pgalloc, unsigned long *ev)\n"
+ "+{\n"
+ "+}\n"
+ "+#endif\n"
+ " \n"
+ " /*\n"
+ "  * appldata_get_mem_data()\n"
+ "@@ -92,6 +107,7 @@ static void appldata_get_mem_data(void *data)\n"
+ " \tmem_data->pswpout    = ev[PSWPOUT];\n"
+ " \tmem_data->pgalloc    = ev[PGALLOC_NORMAL];\n"
+ " \tmem_data->pgalloc    += ev[PGALLOC_DMA];\n"
+ "+\tsum_pgalloc_events(&mem_data->pgalloc, ev);\n"
+ " \tmem_data->pgfault    = ev[PGFAULT];\n"
+ " \tmem_data->pgmajfault = ev[PGMAJFAULT];\n"
+ " \n"
+ "diff --git a/include/linux/mmzone.h b/include/linux/mmzone.h\n"
+ "index fc14b8b..406dfc4 100644\n"
+ "--- a/include/linux/mmzone.h\n"
+ "+++ b/include/linux/mmzone.h\n"
+ "@@ -66,6 +66,8 @@ enum migratetype {\n"
+ " /* In mm/page_alloc.c; keep in sync also with show_migration_types() there */\n"
+ " extern char * const migratetype_names[MIGRATE_TYPES];\n"
+ " \n"
+ "+extern const char *zone_name(int idx);\n"
+ "+\n"
+ " #ifdef CONFIG_CMA\n"
+ " #  define is_migrate_cma(migratetype) unlikely((migratetype) == MIGRATE_CMA)\n"
+ " #  define is_migrate_cma_page(_page) (get_pageblock_migratetype(_page) == MIGRATE_CMA)\n"
+ "diff --git a/include/linux/vm_event_item.h b/include/linux/vm_event_item.h\n"
+ "index 37e8d31..da94618 100644\n"
+ "--- a/include/linux/vm_event_item.h\n"
+ "+++ b/include/linux/vm_event_item.h\n"
+ "@@ -19,12 +19,31 @@\n"
+ " #define HIGHMEM_ZONE(xx)\n"
+ " #endif\n"
+ " \n"
+ "-#define FOR_ALL_ZONES(xx) DMA_ZONE(xx) DMA32_ZONE(xx) xx##_NORMAL, HIGHMEM_ZONE(xx) xx##_MOVABLE\n"
+ "+#ifdef CONFIG_ZONE_DEVICE\n"
+ "+#define DEVICE_ZONE(xx) xx##__DEVICE,\n"
+ "+#else\n"
+ "+#define DEVICE_ZONE(xx)\n"
+ "+#endif\n"
+ "+\n"
+ "+#define FOR_ALL_ZONES(xx) DMA_ZONE(xx) DMA32_ZONE(xx) xx##_NORMAL, HIGHMEM_ZONE(xx) xx##_MOVABLE, DEVICE_ZONE(xx)\n"
+ "+\n"
+ "+#ifdef CONFIG_PER_ORDER_ALLOC_COUNTERS\n"
+ "+#define PGALLOC_EVENTS_SIZE (MAX_NR_ZONES * MAX_ORDER)\n"
+ "+#define PGALLOC_EVENTS_CUT_SIZE (MAX_NR_ZONES * (MAX_ORDER - 1))\n"
+ "+#define PGALLOC_FIRST_ZONE (PGALLOC_NORMAL - ZONE_NORMAL)\n"
+ "+#else\n"
+ "+#define PGALLOC_EVENTS_SIZE MAX_NR_ZONES\n"
+ "+#define PGALLOC_EVENTS_CUT_SIZE 0\n"
+ "+#define PGALLOC_FIRST_ZONE (PGALLOC_NORMAL - ZONE_NORMAL)\n"
+ "+#endif\n"
+ " \n"
+ " enum vm_event_item { PGPGIN, PGPGOUT, PSWPIN, PSWPOUT,\n"
+ "-\t\tFOR_ALL_ZONES(PGALLOC),\n"
+ "-\t\tFOR_ALL_ZONES(ALLOCSTALL),\n"
+ "-\t\tFOR_ALL_ZONES(PGSCAN_SKIP),\n"
+ "+\t\tFOR_ALL_ZONES(PGALLOC)\n"
+ "+#ifdef CONFIG_PER_ORDER_ALLOC_COUNTERS\n"
+ "+\t\t__PGALLOC_LAST = PGALLOC_FIRST_ZONE + PGALLOC_EVENTS_SIZE - 1,\n"
+ "+#endif\n"
+ "+\t\tFOR_ALL_ZONES(ALLOCSTALL)\n"
+ "+\t\tFOR_ALL_ZONES(PGSCAN_SKIP)\n"
+ " \t\tPGFREE, PGACTIVATE, PGDEACTIVATE, PGLAZYFREE,\n"
+ " \t\tPGFAULT, PGMAJFAULT,\n"
+ " \t\tPGLAZYFREED,\n"
+ "diff --git a/include/linux/vmstat.h b/include/linux/vmstat.h\n"
+ "index b3d85f3..bca96fc 100644\n"
+ "--- a/include/linux/vmstat.h\n"
+ "+++ b/include/linux/vmstat.h\n"
+ "@@ -103,6 +103,26 @@ static inline void vm_events_fold_cpu(int cpu)\n"
+ " #define __count_zid_vm_events(item, zid, delta) \\\n"
+ " \t__count_vm_events(item##_NORMAL - ZONE_NORMAL + zid, delta)\n"
+ " \n"
+ "+#ifdef CONFIG_PER_ORDER_ALLOC_COUNTERS\n"
+ "+static inline void __count_alloc_event(enum zone_type zid, unsigned int order)\n"
+ "+{\n"
+ "+\tenum vm_event_item item;\n"
+ "+\n"
+ "+\tif (unlikely(order >= MAX_ORDER)) {\n"
+ "+\t\tWARN_ON_ONCE(1);\n"
+ "+\t\treturn;\n"
+ "+\t}\n"
+ "+\n"
+ "+\titem = PGALLOC_FIRST_ZONE + order * MAX_NR_ZONES + zid;\n"
+ "+\t__count_vm_events(item, 1);\n"
+ "+}\n"
+ "+#else\n"
+ "+static inline void __count_alloc_event(enum zone_type zid, unsigned int order)\n"
+ "+{\n"
+ "+\t__count_zid_vm_events(PGALLOC, zid, 1 << order);\n"
+ "+}\n"
+ "+#endif\n"
+ "+\n"
+ " /*\n"
+ "  * Zone and node-based page accounting with per cpu differentials.\n"
+ "  */\n"
+ "diff --git a/init/Kconfig b/init/Kconfig\n"
+ "index 8514b25..164d6f0 100644\n"
+ "--- a/init/Kconfig\n"
+ "+++ b/init/Kconfig\n"
+ "@@ -1477,6 +1477,15 @@ config VM_EVENT_COUNTERS\n"
+ " \t  on EXPERT systems.  /proc/vmstat will only show page counts\n"
+ " \t  if VM event counters are disabled.\n"
+ " \n"
+ "+config PER_ORDER_ALLOC_COUNTERS\n"
+ "+\tbool \"Per-order memory allocation counters\"\n"
+ "+\tdepends on VM_EVENT_COUNTERS && PROC_FS\n"
+ "+\thelp\n"
+ "+\t  This option enables splitting per-zone allocation counters\n"
+ "+\t  into per-zone per-order counters.\n"
+ "+\t  Per-order counters are exported using the /proc/allocinfo\n"
+ "+\t  interface, and /proc/vmstat shows accumulated values.\n"
+ "+\n"
+ " config SLUB_DEBUG\n"
+ " \tdefault y\n"
+ " \tbool \"Enable SLUB debugging support\" if EXPERT\n"
+ "diff --git a/mm/page_alloc.c b/mm/page_alloc.c\n"
+ "index 80e4adb..e74b327 100644\n"
+ "--- a/mm/page_alloc.c\n"
+ "+++ b/mm/page_alloc.c\n"
+ "@@ -233,6 +233,13 @@ static char * const zone_names[MAX_NR_ZONES] = {\n"
+ " #endif\n"
+ " };\n"
+ " \n"
+ "+const char *zone_name(int zid)\n"
+ "+{\n"
+ "+\tif (zid < MAX_NR_ZONES)\n"
+ "+\t\treturn zone_names[zid];\n"
+ "+\treturn NULL;\n"
+ "+}\n"
+ "+\n"
+ " char * const migratetype_names[MIGRATE_TYPES] = {\n"
+ " \t\"Unmovable\",\n"
+ " \t\"Movable\",\n"
+ "@@ -2779,7 +2786,7 @@ static struct page *rmqueue_pcplist(struct zone *preferred_zone,\n"
+ " \tlist = &pcp->lists[migratetype];\n"
+ " \tpage = __rmqueue_pcplist(zone,  migratetype, cold, pcp, list);\n"
+ " \tif (page) {\n"
+ "-\t\t__count_zid_vm_events(PGALLOC, page_zonenum(page), 1 << order);\n"
+ "+\t\t__count_alloc_event(page_zonenum(page), order);\n"
+ " \t\tzone_statistics(preferred_zone, zone);\n"
+ " \t}\n"
+ " \tlocal_irq_restore(flags);\n"
+ "@@ -2827,7 +2834,7 @@ struct page *rmqueue(struct zone *preferred_zone,\n"
+ " \t__mod_zone_freepage_state(zone, -(1 << order),\n"
+ " \t\t\t\t  get_pcppage_migratetype(page));\n"
+ " \n"
+ "-\t__count_zid_vm_events(PGALLOC, page_zonenum(page), 1 << order);\n"
+ "+\t__count_alloc_event(page_zonenum(page), order);\n"
+ " \tzone_statistics(preferred_zone, zone);\n"
+ " \tlocal_irq_restore(flags);\n"
+ " \n"
+ "diff --git a/mm/vmstat.c b/mm/vmstat.c\n"
+ "index 9a4441b..1d468ed 100644\n"
+ "--- a/mm/vmstat.c\n"
+ "+++ b/mm/vmstat.c\n"
+ "@@ -27,6 +27,7 @@\n"
+ " #include <linux/mm_inline.h>\n"
+ " #include <linux/page_ext.h>\n"
+ " #include <linux/page_owner.h>\n"
+ "+#include <linux/mmzone.h>\n"
+ " \n"
+ " #include \"internal.h\"\n"
+ " \n"
+ "@@ -34,18 +35,18 @@\n"
+ " DEFINE_PER_CPU(struct vm_event_state, vm_event_states) = {{0}};\n"
+ " EXPORT_PER_CPU_SYMBOL(vm_event_states);\n"
+ " \n"
+ "-static void sum_vm_events(unsigned long *ret)\n"
+ "+static void sum_vm_events(unsigned long *ret, int off, size_t nr_events)\n"
+ " {\n"
+ " \tint cpu;\n"
+ " \tint i;\n"
+ " \n"
+ "-\tmemset(ret, 0, NR_VM_EVENT_ITEMS * sizeof(unsigned long));\n"
+ "+\tmemset(ret, 0, nr_events * sizeof(unsigned long));\n"
+ " \n"
+ " \tfor_each_online_cpu(cpu) {\n"
+ " \t\tstruct vm_event_state *this = &per_cpu(vm_event_states, cpu);\n"
+ " \n"
+ "-\t\tfor (i = 0; i < NR_VM_EVENT_ITEMS; i++)\n"
+ "-\t\t\tret[i] += this->event[i];\n"
+ "+\t\tfor (i = 0; i < nr_events; i++)\n"
+ "+\t\t\tret[i] += this->event[off + i];\n"
+ " \t}\n"
+ " }\n"
+ " \n"
+ "@@ -57,7 +58,7 @@ static void sum_vm_events(unsigned long *ret)\n"
+ " void all_vm_events(unsigned long *ret)\n"
+ " {\n"
+ " \tget_online_cpus();\n"
+ "-\tsum_vm_events(ret);\n"
+ "+\tsum_vm_events(ret, 0, NR_VM_EVENT_ITEMS);\n"
+ " \tput_online_cpus();\n"
+ " }\n"
+ " EXPORT_SYMBOL_GPL(all_vm_events);\n"
+ "@@ -915,8 +916,15 @@ int fragmentation_index(struct zone *zone, unsigned int order)\n"
+ " #define TEXT_FOR_HIGHMEM(xx)\n"
+ " #endif\n"
+ " \n"
+ "+#ifdef CONFIG_ZONE_DEVICE\n"
+ "+#define TEXT_FOR_DEVICE(xx) xx \"_device\",\n"
+ "+#else\n"
+ "+#define TEXT_FOR_DEVICE(xx)\n"
+ "+#endif\n"
+ "+\n"
+ " #define TEXTS_FOR_ZONES(xx) TEXT_FOR_DMA(xx) TEXT_FOR_DMA32(xx) xx \"_normal\", \\\n"
+ "-\t\t\t\t\tTEXT_FOR_HIGHMEM(xx) xx \"_movable\",\n"
+ "+\t\t\t\t\tTEXT_FOR_HIGHMEM(xx) xx \"_movable\", \\\n"
+ "+\t\t\t\t\tTEXT_FOR_DEVICE(xx)\n"
+ " \n"
+ " const char * const vmstat_text[] = {\n"
+ " \t/* enum zone_stat_item countes */\n"
+ "@@ -1480,12 +1488,92 @@ enum writeback_stat_item {\n"
+ " \tNR_VM_WRITEBACK_STAT_ITEMS,\n"
+ " };\n"
+ " \n"
+ "+#ifdef CONFIG_PER_ORDER_ALLOC_COUNTERS\n"
+ "+static void sum_alloc_events(unsigned long *v)\n"
+ "+{\n"
+ "+\tint zid, order, index;\n"
+ "+\n"
+ "+\tfor (zid = 0; zid < MAX_NR_ZONES; ++zid) {\n"
+ "+\t\tfor (order = 1; order < MAX_ORDER; order++) {\n"
+ "+\t\t\tindex = PGALLOC_FIRST_ZONE + zid;\n"
+ "+\t\t\tv[index] += v[index + order * MAX_NR_ZONES] << order;\n"
+ "+\t\t}\n"
+ "+\t}\n"
+ "+}\n"
+ "+\n"
+ "+static int allocinfo_show(struct seq_file *m, void *arg)\n"
+ "+{\n"
+ "+\tunsigned long allocs[PGALLOC_EVENTS_SIZE];\n"
+ "+\tunsigned int order;\n"
+ "+\tint zid;\n"
+ "+\n"
+ "+\tif (arg != SEQ_START_TOKEN)\n"
+ "+\t\treturn 0;\n"
+ "+\n"
+ "+\tget_online_cpus();\n"
+ "+\tsum_vm_events(allocs, PGALLOC_FIRST_ZONE, PGALLOC_EVENTS_SIZE);\n"
+ "+\tput_online_cpus();\n"
+ "+\n"
+ "+\tfor (zid = 0; zid < MAX_NR_ZONES; ++zid) {\n"
+ "+\t\tseq_printf(m, \"%8s \", zone_name(zid));\n"
+ "+\n"
+ "+\t\tfor (order = 0; order < MAX_ORDER; order++)\n"
+ "+\t\t\tseq_printf(m, \"%10lu \",\n"
+ "+\t\t\t\t   allocs[zid + order * MAX_NR_ZONES]);\n"
+ "+\n"
+ "+\t\tseq_putc(m, '\\n');\n"
+ "+\t}\n"
+ "+\n"
+ "+\treturn 0;\n"
+ "+}\n"
+ "+\n"
+ "+static void *allocinfo_start(struct seq_file *m, loff_t *pos)\n"
+ "+{\n"
+ "+\tif (*pos)\n"
+ "+\t\treturn NULL;\n"
+ "+\treturn SEQ_START_TOKEN;\n"
+ "+}\n"
+ "+\n"
+ "+static void *allocinfo_next(struct seq_file *m, void *arg, loff_t *pos)\n"
+ "+{\n"
+ "+\t++*pos;\n"
+ "+\treturn NULL;\n"
+ "+}\n"
+ "+\n"
+ "+static void allocinfo_stop(struct seq_file *m, void *arg)\n"
+ "+{\n"
+ "+}\n"
+ "+\n"
+ "+static const struct seq_operations allocinfo_op = {\n"
+ "+\t.start\t= allocinfo_start,\n"
+ "+\t.next\t= allocinfo_next,\n"
+ "+\t.stop\t= allocinfo_stop,\n"
+ "+\t.show\t= allocinfo_show,\n"
+ "+};\n"
+ "+\n"
+ "+static int allocinfo_open(struct inode *inode, struct file *file)\n"
+ "+{\n"
+ "+\treturn seq_open(file, &allocinfo_op);\n"
+ "+}\n"
+ "+\n"
+ "+static const struct file_operations allocinfo_file_operations = {\n"
+ "+\t.open\t\t= allocinfo_open,\n"
+ "+\t.read\t\t= seq_read,\n"
+ "+\t.llseek\t\t= seq_lseek,\n"
+ "+\t.release\t= seq_release,\n"
+ "+};\n"
+ "+#else\n"
+ "+static void sum_alloc_events(unsigned long *v)\n"
+ "+{\n"
+ "+}\n"
+ "+#endif\n"
+ "+\n"
+ " static void *vmstat_start(struct seq_file *m, loff_t *pos)\n"
+ " {\n"
+ " \tunsigned long *v;\n"
+ " \tint i, stat_items_size;\n"
+ " \n"
+ "-\tif (*pos >= ARRAY_SIZE(vmstat_text))\n"
+ "+\tif (*pos >= ARRAY_SIZE(vmstat_text) + PGALLOC_EVENTS_CUT_SIZE)\n"
+ " \t\treturn NULL;\n"
+ " \tstat_items_size = NR_VM_ZONE_STAT_ITEMS * sizeof(unsigned long) +\n"
+ " \t\t\t  NR_VM_NODE_STAT_ITEMS * sizeof(unsigned long) +\n"
+ "@@ -1513,6 +1601,7 @@ static void *vmstat_start(struct seq_file *m, loff_t *pos)\n"
+ " \n"
+ " #ifdef CONFIG_VM_EVENT_COUNTERS\n"
+ " \tall_vm_events(v);\n"
+ "+\tsum_alloc_events(v);\n"
+ " \tv[PGPGIN] /= 2;\t\t/* sectors -> kbytes */\n"
+ " \tv[PGPGOUT] /= 2;\n"
+ " #endif\n"
+ "@@ -1521,8 +1610,16 @@ static void *vmstat_start(struct seq_file *m, loff_t *pos)\n"
+ " \n"
+ " static void *vmstat_next(struct seq_file *m, void *arg, loff_t *pos)\n"
+ " {\n"
+ "+\tint alloc_event_start = NR_VM_ZONE_STAT_ITEMS +\n"
+ "+\t\tNR_VM_NODE_STAT_ITEMS +\n"
+ "+\t\tNR_VM_WRITEBACK_STAT_ITEMS +\n"
+ "+\t\tPGALLOC_FIRST_ZONE;\n"
+ "+\n"
+ " \t(*pos)++;\n"
+ "-\tif (*pos >= ARRAY_SIZE(vmstat_text))\n"
+ "+\tif (*pos == alloc_event_start + MAX_NR_ZONES)\n"
+ "+\t\t*(pos) += PGALLOC_EVENTS_CUT_SIZE;\n"
+ "+\n"
+ "+\tif (*pos >= ARRAY_SIZE(vmstat_text) + PGALLOC_EVENTS_CUT_SIZE)\n"
+ " \t\treturn NULL;\n"
+ " \treturn (unsigned long *)m->private + *pos;\n"
+ " }\n"
+ "@@ -1531,6 +1628,18 @@ static int vmstat_show(struct seq_file *m, void *arg)\n"
+ " {\n"
+ " \tunsigned long *l = arg;\n"
+ " \tunsigned long off = l - (unsigned long *)m->private;\n"
+ "+\tint alloc_event_start = NR_VM_ZONE_STAT_ITEMS +\n"
+ "+\t\tNR_VM_NODE_STAT_ITEMS +\n"
+ "+\t\tNR_VM_WRITEBACK_STAT_ITEMS +\n"
+ "+\t\tPGALLOC_FIRST_ZONE;\n"
+ "+\n"
+ "+\tif (off >= alloc_event_start + PGALLOC_EVENTS_SIZE)\n"
+ "+\t\toff -= PGALLOC_EVENTS_CUT_SIZE;\n"
+ "+\n"
+ "+\tif (unlikely(off >= sizeof(vmstat_text))) {\n"
+ "+\t\tWARN_ON_ONCE(1);\n"
+ "+\t\treturn 0;\n"
+ "+\t}\n"
+ " \n"
+ " \tseq_puts(m, vmstat_text[off]);\n"
+ " \tseq_put_decimal_ull(m, \" \", *l);\n"
+ "@@ -1790,6 +1899,9 @@ void __init init_mm_internals(void)\n"
+ " #endif\n"
+ " #ifdef CONFIG_PROC_FS\n"
+ " \tproc_create(\"buddyinfo\", 0444, NULL, &buddyinfo_file_operations);\n"
+ "+#ifdef CONFIG_PER_ORDER_ALLOC_COUNTERS\n"
+ "+\tproc_create(\"allocinfo\", 0444, NULL, &allocinfo_file_operations);\n"
+ "+#endif\n"
+ " \tproc_create(\"pagetypeinfo\", 0444, NULL, &pagetypeinfo_file_operations);\n"
+ " \tproc_create(\"vmstat\", 0444, NULL, &vmstat_file_operations);\n"
+ " \tproc_create(\"zoneinfo\", 0444, NULL, &zoneinfo_file_operations);\n"
+ "-- \n"
+ 2.7.4
 
-d10f1ca7f38ef30ceaaf85b14f4b76ecf8620961554df1977826917f19b8cab7
+65cd3fed8b362b51deea4be840e603bdca1c927472bed0d08651dfe8c63daa4b

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.