diff options
Diffstat (limited to 'mm/vmstat.c')
-rw-r--r-- | mm/vmstat.c | 89 |
1 files changed, 88 insertions, 1 deletions
diff --git a/mm/vmstat.c b/mm/vmstat.c index 4f5cd974e11a..4bbf65f7335b 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c | |||
@@ -956,6 +956,67 @@ static void pagetypeinfo_showfree_print(struct seq_file *m, | |||
956 | } | 956 | } |
957 | } | 957 | } |
958 | 958 | ||
959 | static void pagetypeinfo_showpartitionfree_print(struct seq_file *m, | ||
960 | pg_data_t *pgdat, struct zone *zone, int cpu) | ||
961 | { | ||
962 | int order, mtype; | ||
963 | |||
964 | for (mtype = 0; mtype < MIGRATE_TYPES; mtype++) { | ||
965 | seq_printf(m, "Node %4d, zone %8s, type %12s ", | ||
966 | pgdat->node_id, | ||
967 | zone->name, | ||
968 | migratetype_names[mtype]); | ||
969 | for (order = 0; order < MAX_PARTITIONED_ORDER; ++order) { | ||
970 | unsigned long freecount = 0; | ||
971 | struct free_area *area; | ||
972 | struct list_head *curr; | ||
973 | |||
974 | area = &(zone->free_area_d[cpu][order]); | ||
975 | |||
976 | list_for_each(curr, &area->free_list[mtype]) | ||
977 | freecount++; | ||
978 | seq_printf(m, "%6lu ", freecount); | ||
979 | } | ||
980 | seq_putc(m, '\n'); | ||
981 | } | ||
982 | } | ||
983 | |||
984 | static void walk_zones_in_node_in_partition(struct seq_file *m, pg_data_t *pgdat, | ||
985 | int cpu, void (*print)(struct seq_file *m, pg_data_t *, struct zone *, int)) | ||
986 | { | ||
987 | struct zone *zone; | ||
988 | struct zone *node_zones = pgdat->node_zones; | ||
989 | unsigned long flags; | ||
990 | |||
991 | for (zone = node_zones; zone - node_zones < MAX_NR_ZONES; ++zone) { | ||
992 | if (!populated_zone(zone)) | ||
993 | continue; | ||
994 | |||
995 | spin_lock_irqsave(&zone->lock, flags); | ||
996 | print(m, pgdat, zone, cpu); | ||
997 | spin_unlock_irqrestore(&zone->lock, flags); | ||
998 | } | ||
999 | } | ||
1000 | |||
1001 | /* Print out the free pages at each order for each migatetype and partition */ | ||
1002 | static int pagetypeinfo_showpartitioned(struct seq_file *m, void *arg) | ||
1003 | { | ||
1004 | int order, cpu; | ||
1005 | pg_data_t *pgdat = (pg_data_t *)arg; | ||
1006 | |||
1007 | for_each_online_cpu(cpu) { | ||
1008 | /* Print header */ | ||
1009 | seq_putc(m, '\n'); | ||
1010 | seq_printf(m, "CPU%d %-43s ", cpu, "free pages count per migrate type at order"); | ||
1011 | for (order = 0; order < MAX_PARTITIONED_ORDER; ++order) | ||
1012 | seq_printf(m, "%6d ", order); | ||
1013 | seq_putc(m, '\n'); | ||
1014 | |||
1015 | walk_zones_in_node_in_partition(m, pgdat, cpu, pagetypeinfo_showpartitionfree_print); | ||
1016 | } | ||
1017 | return 0; | ||
1018 | } | ||
1019 | |||
959 | /* Print out the free pages at each order for each migatetype */ | 1020 | /* Print out the free pages at each order for each migatetype */ |
960 | static int pagetypeinfo_showfree(struct seq_file *m, void *arg) | 1021 | static int pagetypeinfo_showfree(struct seq_file *m, void *arg) |
961 | { | 1022 | { |
@@ -1138,7 +1199,7 @@ static int pagetypeinfo_show(struct seq_file *m, void *arg) | |||
1138 | pagetypeinfo_showfree(m, pgdat); | 1199 | pagetypeinfo_showfree(m, pgdat); |
1139 | pagetypeinfo_showblockcount(m, pgdat); | 1200 | pagetypeinfo_showblockcount(m, pgdat); |
1140 | pagetypeinfo_showmixedcount(m, pgdat); | 1201 | pagetypeinfo_showmixedcount(m, pgdat); |
1141 | 1202 | pagetypeinfo_showpartitioned(m, pgdat); | |
1142 | return 0; | 1203 | return 0; |
1143 | } | 1204 | } |
1144 | 1205 | ||
@@ -1180,10 +1241,27 @@ static const struct file_operations pagetypeinfo_file_ops = { | |||
1180 | .release = seq_release, | 1241 | .release = seq_release, |
1181 | }; | 1242 | }; |
1182 | 1243 | ||
1244 | #define BANK_MASK 0x38000000 | ||
1245 | #define BANK_SHIFT 27 | ||
1246 | #define CACHE_MASK 0x0000f000 | ||
1247 | #define CACHE_SHIFT 12 | ||
1248 | /* Decoding page bank number, 0~7 */ | ||
1249 | static inline unsigned int page_bank(struct page *page) | ||
1250 | { | ||
1251 | return ((page_to_phys(page)& BANK_MASK) >> BANK_SHIFT); | ||
1252 | } | ||
1253 | /* Decoding page color, 0~15 */ | ||
1254 | static inline unsigned int page_color(struct page *page) | ||
1255 | { | ||
1256 | return ((page_to_phys(page)& CACHE_MASK) >> CACHE_SHIFT); | ||
1257 | } | ||
1258 | |||
1183 | static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat, | 1259 | static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat, |
1184 | struct zone *zone) | 1260 | struct zone *zone) |
1185 | { | 1261 | { |
1186 | int i; | 1262 | int i; |
1263 | int mtype; | ||
1264 | |||
1187 | seq_printf(m, "Node %d, zone %8s", pgdat->node_id, zone->name); | 1265 | seq_printf(m, "Node %d, zone %8s", pgdat->node_id, zone->name); |
1188 | seq_printf(m, | 1266 | seq_printf(m, |
1189 | "\n pages free %lu" | 1267 | "\n pages free %lu" |
@@ -1232,6 +1310,15 @@ static void zoneinfo_show_print(struct seq_file *m, pg_data_t *pgdat, | |||
1232 | seq_printf(m, "\n vm stats threshold: %d", | 1310 | seq_printf(m, "\n vm stats threshold: %d", |
1233 | pageset->stat_threshold); | 1311 | pageset->stat_threshold); |
1234 | #endif | 1312 | #endif |
1313 | /* test */ | ||
1314 | seq_printf(m, "\n"); | ||
1315 | for (mtype = 0; mtype < MIGRATE_PCPTYPES; mtype++) { | ||
1316 | struct page *p; | ||
1317 | list_for_each_entry(p, &pageset->pcp.lists[mtype], lru) { | ||
1318 | if (p) | ||
1319 | seq_printf(m, "page bank = %d color = %d\n", page_bank(p), page_color(p)); | ||
1320 | } | ||
1321 | } | ||
1235 | } | 1322 | } |
1236 | seq_printf(m, | 1323 | seq_printf(m, |
1237 | "\n all_unreclaimable: %u" | 1324 | "\n all_unreclaimable: %u" |