diff options
Diffstat (limited to 'mm/vmstat.c')
-rw-r--r-- | mm/vmstat.c | 102 |
1 files changed, 102 insertions, 0 deletions
diff --git a/mm/vmstat.c b/mm/vmstat.c index 1b12d390dc68..1284f89fca08 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c | |||
@@ -22,6 +22,8 @@ | |||
22 | #include <linux/writeback.h> | 22 | #include <linux/writeback.h> |
23 | #include <linux/compaction.h> | 23 | #include <linux/compaction.h> |
24 | #include <linux/mm_inline.h> | 24 | #include <linux/mm_inline.h> |
25 | #include <linux/page_ext.h> | ||
26 | #include <linux/page_owner.h> | ||
25 | 27 | ||
26 | #include "internal.h" | 28 | #include "internal.h" |
27 | 29 | ||
@@ -898,6 +900,7 @@ const char * const vmstat_text[] = { | |||
898 | #ifdef CONFIG_DEBUG_VM_VMACACHE | 900 | #ifdef CONFIG_DEBUG_VM_VMACACHE |
899 | "vmacache_find_calls", | 901 | "vmacache_find_calls", |
900 | "vmacache_find_hits", | 902 | "vmacache_find_hits", |
903 | "vmacache_full_flushes", | ||
901 | #endif | 904 | #endif |
902 | #endif /* CONFIG_VM_EVENTS_COUNTERS */ | 905 | #endif /* CONFIG_VM_EVENTS_COUNTERS */ |
903 | }; | 906 | }; |
@@ -1017,6 +1020,104 @@ static int pagetypeinfo_showblockcount(struct seq_file *m, void *arg) | |||
1017 | return 0; | 1020 | return 0; |
1018 | } | 1021 | } |
1019 | 1022 | ||
1023 | #ifdef CONFIG_PAGE_OWNER | ||
1024 | static void pagetypeinfo_showmixedcount_print(struct seq_file *m, | ||
1025 | pg_data_t *pgdat, | ||
1026 | struct zone *zone) | ||
1027 | { | ||
1028 | struct page *page; | ||
1029 | struct page_ext *page_ext; | ||
1030 | unsigned long pfn = zone->zone_start_pfn, block_end_pfn; | ||
1031 | unsigned long end_pfn = pfn + zone->spanned_pages; | ||
1032 | unsigned long count[MIGRATE_TYPES] = { 0, }; | ||
1033 | int pageblock_mt, page_mt; | ||
1034 | int i; | ||
1035 | |||
1036 | /* Scan block by block. First and last block may be incomplete */ | ||
1037 | pfn = zone->zone_start_pfn; | ||
1038 | |||
1039 | /* | ||
1040 | * Walk the zone in pageblock_nr_pages steps. If a page block spans | ||
1041 | * a zone boundary, it will be double counted between zones. This does | ||
1042 | * not matter as the mixed block count will still be correct | ||
1043 | */ | ||
1044 | for (; pfn < end_pfn; ) { | ||
1045 | if (!pfn_valid(pfn)) { | ||
1046 | pfn = ALIGN(pfn + 1, MAX_ORDER_NR_PAGES); | ||
1047 | continue; | ||
1048 | } | ||
1049 | |||
1050 | block_end_pfn = ALIGN(pfn + 1, pageblock_nr_pages); | ||
1051 | block_end_pfn = min(block_end_pfn, end_pfn); | ||
1052 | |||
1053 | page = pfn_to_page(pfn); | ||
1054 | pageblock_mt = get_pfnblock_migratetype(page, pfn); | ||
1055 | |||
1056 | for (; pfn < block_end_pfn; pfn++) { | ||
1057 | if (!pfn_valid_within(pfn)) | ||
1058 | continue; | ||
1059 | |||
1060 | page = pfn_to_page(pfn); | ||
1061 | if (PageBuddy(page)) { | ||
1062 | pfn += (1UL << page_order(page)) - 1; | ||
1063 | continue; | ||
1064 | } | ||
1065 | |||
1066 | if (PageReserved(page)) | ||
1067 | continue; | ||
1068 | |||
1069 | page_ext = lookup_page_ext(page); | ||
1070 | |||
1071 | if (!test_bit(PAGE_EXT_OWNER, &page_ext->flags)) | ||
1072 | continue; | ||
1073 | |||
1074 | page_mt = gfpflags_to_migratetype(page_ext->gfp_mask); | ||
1075 | if (pageblock_mt != page_mt) { | ||
1076 | if (is_migrate_cma(pageblock_mt)) | ||
1077 | count[MIGRATE_MOVABLE]++; | ||
1078 | else | ||
1079 | count[pageblock_mt]++; | ||
1080 | |||
1081 | pfn = block_end_pfn; | ||
1082 | break; | ||
1083 | } | ||
1084 | pfn += (1UL << page_ext->order) - 1; | ||
1085 | } | ||
1086 | } | ||
1087 | |||
1088 | /* Print counts */ | ||
1089 | seq_printf(m, "Node %d, zone %8s ", pgdat->node_id, zone->name); | ||
1090 | for (i = 0; i < MIGRATE_TYPES; i++) | ||
1091 | seq_printf(m, "%12lu ", count[i]); | ||
1092 | seq_putc(m, '\n'); | ||
1093 | } | ||
1094 | #endif /* CONFIG_PAGE_OWNER */ | ||
1095 | |||
1096 | /* | ||
1097 | * Print out the number of pageblocks for each migratetype that contain pages | ||
1098 | * of other types. This gives an indication of how well fallbacks are being | ||
1099 | * contained by rmqueue_fallback(). It requires information from PAGE_OWNER | ||
1100 | * to determine what is going on | ||
1101 | */ | ||
1102 | static void pagetypeinfo_showmixedcount(struct seq_file *m, pg_data_t *pgdat) | ||
1103 | { | ||
1104 | #ifdef CONFIG_PAGE_OWNER | ||
1105 | int mtype; | ||
1106 | |||
1107 | if (!page_owner_inited) | ||
1108 | return; | ||
1109 | |||
1110 | drain_all_pages(NULL); | ||
1111 | |||
1112 | seq_printf(m, "\n%-23s", "Number of mixed blocks "); | ||
1113 | for (mtype = 0; mtype < MIGRATE_TYPES; mtype++) | ||
1114 | seq_printf(m, "%12s ", migratetype_names[mtype]); | ||
1115 | seq_putc(m, '\n'); | ||
1116 | |||
1117 | walk_zones_in_node(m, pgdat, pagetypeinfo_showmixedcount_print); | ||
1118 | #endif /* CONFIG_PAGE_OWNER */ | ||
1119 | } | ||
1120 | |||
1020 | /* | 1121 | /* |
1021 | * This prints out statistics in relation to grouping pages by mobility. | 1122 | * This prints out statistics in relation to grouping pages by mobility. |
1022 | * It is expensive to collect so do not constantly read the file. | 1123 | * It is expensive to collect so do not constantly read the file. |
@@ -1034,6 +1135,7 @@ static int pagetypeinfo_show(struct seq_file *m, void *arg) | |||
1034 | seq_putc(m, '\n'); | 1135 | seq_putc(m, '\n'); |
1035 | pagetypeinfo_showfree(m, pgdat); | 1136 | pagetypeinfo_showfree(m, pgdat); |
1036 | pagetypeinfo_showblockcount(m, pgdat); | 1137 | pagetypeinfo_showblockcount(m, pgdat); |
1138 | pagetypeinfo_showmixedcount(m, pgdat); | ||
1037 | 1139 | ||
1038 | return 0; | 1140 | return 0; |
1039 | } | 1141 | } |