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.