diff options
Diffstat (limited to 'mm/vmstat.c')
-rw-r--r-- | mm/vmstat.c | 253 |
1 files changed, 252 insertions, 1 deletions
diff --git a/mm/vmstat.c b/mm/vmstat.c index fa12ea3051fb..7759941d4e77 100644 --- a/mm/vmstat.c +++ b/mm/vmstat.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/cpu.h> | 16 | #include <linux/cpu.h> |
17 | #include <linux/vmstat.h> | 17 | #include <linux/vmstat.h> |
18 | #include <linux/sched.h> | 18 | #include <linux/sched.h> |
19 | #include <linux/math64.h> | ||
19 | 20 | ||
20 | #ifdef CONFIG_VM_EVENT_COUNTERS | 21 | #ifdef CONFIG_VM_EVENT_COUNTERS |
21 | DEFINE_PER_CPU(struct vm_event_state, vm_event_states) = {{0}}; | 22 | DEFINE_PER_CPU(struct vm_event_state, vm_event_states) = {{0}}; |
@@ -379,7 +380,86 @@ void zone_statistics(struct zone *preferred_zone, struct zone *z) | |||
379 | } | 380 | } |
380 | #endif | 381 | #endif |
381 | 382 | ||
382 | #ifdef CONFIG_PROC_FS | 383 | #ifdef CONFIG_COMPACTION |
384 | struct contig_page_info { | ||
385 | unsigned long free_pages; | ||
386 | unsigned long free_blocks_total; | ||
387 | unsigned long free_blocks_suitable; | ||
388 | }; | ||
389 | |||
390 | /* | ||
391 | * Calculate the number of free pages in a zone, how many contiguous | ||
392 | * pages are free and how many are large enough to satisfy an allocation of | ||
393 | * the target size. Note that this function makes no attempt to estimate | ||
394 | * how many suitable free blocks there *might* be if MOVABLE pages were | ||
395 | * migrated. Calculating that is possible, but expensive and can be | ||
396 | * figured out from userspace | ||
397 | */ | ||
398 | static void fill_contig_page_info(struct zone *zone, | ||
399 | unsigned int suitable_order, | ||
400 | struct contig_page_info *info) | ||
401 | { | ||
402 | unsigned int order; | ||
403 | |||
404 | info->free_pages = 0; | ||
405 | info->free_blocks_total = 0; | ||
406 | info->free_blocks_suitable = 0; | ||
407 | |||
408 | for (order = 0; order < MAX_ORDER; order++) { | ||
409 | unsigned long blocks; | ||
410 | |||
411 | /* Count number of free blocks */ | ||
412 | blocks = zone->free_area[order].nr_free; | ||
413 | info->free_blocks_total += blocks; | ||
414 | |||
415 | /* Count free base pages */ | ||
416 | info->free_pages += blocks << order; | ||
417 | |||
418 | /* Count the suitable free blocks */ | ||
419 | if (order >= suitable_order) | ||
420 | info->free_blocks_suitable += blocks << | ||
421 | (order - suitable_order); | ||
422 | } | ||
423 | } | ||
424 | |||
425 | /* | ||
426 | * A fragmentation index only makes sense if an allocation of a requested | ||
427 | * size would fail. If that is true, the fragmentation index indicates | ||
428 | * whether external fragmentation or a lack of memory was the problem. | ||
429 | * The value can be used to determine if page reclaim or compaction | ||
430 | * should be used | ||
431 | */ | ||
432 | static int __fragmentation_index(unsigned int order, struct contig_page_info *info) | ||
433 | { | ||
434 | unsigned long requested = 1UL << order; | ||
435 | |||
436 | if (!info->free_blocks_total) | ||
437 | return 0; | ||
438 | |||
439 | /* Fragmentation index only makes sense when a request would fail */ | ||
440 | if (info->free_blocks_suitable) | ||
441 | return -1000; | ||
442 | |||
443 | /* | ||
444 | * Index is between 0 and 1 so return within 3 decimal places | ||
445 | * | ||
446 | * 0 => allocation would fail due to lack of memory | ||
447 | * 1 => allocation would fail due to fragmentation | ||
448 | */ | ||
449 | return 1000 - div_u64( (1000+(div_u64(info->free_pages * 1000ULL, requested))), info->free_blocks_total); | ||
450 | } | ||
451 | |||
452 | /* Same as __fragmentation index but allocs contig_page_info on stack */ | ||
453 | int fragmentation_index(struct zone *zone, unsigned int order) | ||
454 | { | ||
455 | struct contig_page_info info; | ||
456 | |||
457 | fill_contig_page_info(zone, order, &info); | ||
458 | return __fragmentation_index(order, &info); | ||
459 | } | ||
460 | #endif | ||
461 | |||
462 | #if defined(CONFIG_PROC_FS) || defined(CONFIG_COMPACTION) | ||
383 | #include <linux/proc_fs.h> | 463 | #include <linux/proc_fs.h> |
384 | #include <linux/seq_file.h> | 464 | #include <linux/seq_file.h> |
385 | 465 | ||
@@ -432,7 +512,9 @@ static void walk_zones_in_node(struct seq_file *m, pg_data_t *pgdat, | |||
432 | spin_unlock_irqrestore(&zone->lock, flags); | 512 | spin_unlock_irqrestore(&zone->lock, flags); |
433 | } | 513 | } |
434 | } | 514 | } |
515 | #endif | ||
435 | 516 | ||
517 | #ifdef CONFIG_PROC_FS | ||
436 | static void frag_show_print(struct seq_file *m, pg_data_t *pgdat, | 518 | static void frag_show_print(struct seq_file *m, pg_data_t *pgdat, |
437 | struct zone *zone) | 519 | struct zone *zone) |
438 | { | 520 | { |
@@ -693,6 +775,16 @@ static const char * const vmstat_text[] = { | |||
693 | "allocstall", | 775 | "allocstall", |
694 | 776 | ||
695 | "pgrotated", | 777 | "pgrotated", |
778 | |||
779 | #ifdef CONFIG_COMPACTION | ||
780 | "compact_blocks_moved", | ||
781 | "compact_pages_moved", | ||
782 | "compact_pagemigrate_failed", | ||
783 | "compact_stall", | ||
784 | "compact_fail", | ||
785 | "compact_success", | ||
786 | #endif | ||
787 | |||
696 | #ifdef CONFIG_HUGETLB_PAGE | 788 | #ifdef CONFIG_HUGETLB_PAGE |
697 | "htlb_buddy_alloc_success", | 789 | "htlb_buddy_alloc_success", |
698 | "htlb_buddy_alloc_fail", | 790 | "htlb_buddy_alloc_fail", |
@@ -954,3 +1046,162 @@ static int __init setup_vmstat(void) | |||
954 | return 0; | 1046 | return 0; |
955 | } | 1047 | } |
956 | module_init(setup_vmstat) | 1048 | module_init(setup_vmstat) |
1049 | |||
1050 | #if defined(CONFIG_DEBUG_FS) && defined(CONFIG_COMPACTION) | ||
1051 | #include <linux/debugfs.h> | ||
1052 | |||
1053 | static struct dentry *extfrag_debug_root; | ||
1054 | |||
1055 | /* | ||
1056 | * Return an index indicating how much of the available free memory is | ||
1057 | * unusable for an allocation of the requested size. | ||
1058 | */ | ||
1059 | static int unusable_free_index(unsigned int order, | ||
1060 | struct contig_page_info *info) | ||
1061 | { | ||
1062 | /* No free memory is interpreted as all free memory is unusable */ | ||
1063 | if (info->free_pages == 0) | ||
1064 | return 1000; | ||
1065 | |||
1066 | /* | ||
1067 | * Index should be a value between 0 and 1. Return a value to 3 | ||
1068 | * decimal places. | ||
1069 | * | ||
1070 | * 0 => no fragmentation | ||
1071 | * 1 => high fragmentation | ||
1072 | */ | ||
1073 | return div_u64((info->free_pages - (info->free_blocks_suitable << order)) * 1000ULL, info->free_pages); | ||
1074 | |||
1075 | } | ||
1076 | |||
1077 | static void unusable_show_print(struct seq_file *m, | ||
1078 | pg_data_t *pgdat, struct zone *zone) | ||
1079 | { | ||
1080 | unsigned int order; | ||
1081 | int index; | ||
1082 | struct contig_page_info info; | ||
1083 | |||
1084 | seq_printf(m, "Node %d, zone %8s ", | ||
1085 | pgdat->node_id, | ||
1086 | zone->name); | ||
1087 | for (order = 0; order < MAX_ORDER; ++order) { | ||
1088 | fill_contig_page_info(zone, order, &info); | ||
1089 | index = unusable_free_index(order, &info); | ||
1090 | seq_printf(m, "%d.%03d ", index / 1000, index % 1000); | ||
1091 | } | ||
1092 | |||
1093 | seq_putc(m, '\n'); | ||
1094 | } | ||
1095 | |||
1096 | /* | ||
1097 | * Display unusable free space index | ||
1098 | * | ||
1099 | * The unusable free space index measures how much of the available free | ||
1100 | * memory cannot be used to satisfy an allocation of a given size and is a | ||
1101 | * value between 0 and 1. The higher the value, the more of free memory is | ||
1102 | * unusable and by implication, the worse the external fragmentation is. This | ||
1103 | * can be expressed as a percentage by multiplying by 100. | ||
1104 | */ | ||
1105 | static int unusable_show(struct seq_file *m, void *arg) | ||
1106 | { | ||
1107 | pg_data_t *pgdat = (pg_data_t *)arg; | ||
1108 | |||
1109 | /* check memoryless node */ | ||
1110 | if (!node_state(pgdat->node_id, N_HIGH_MEMORY)) | ||
1111 | return 0; | ||
1112 | |||
1113 | walk_zones_in_node(m, pgdat, unusable_show_print); | ||
1114 | |||
1115 | return 0; | ||
1116 | } | ||
1117 | |||
1118 | static const struct seq_operations unusable_op = { | ||
1119 | .start = frag_start, | ||
1120 | .next = frag_next, | ||
1121 | .stop = frag_stop, | ||
1122 | .show = unusable_show, | ||
1123 | }; | ||
1124 | |||
1125 | static int unusable_open(struct inode *inode, struct file *file) | ||
1126 | { | ||
1127 | return seq_open(file, &unusable_op); | ||
1128 | } | ||
1129 | |||
1130 | static const struct file_operations unusable_file_ops = { | ||
1131 | .open = unusable_open, | ||
1132 | .read = seq_read, | ||
1133 | .llseek = seq_lseek, | ||
1134 | .release = seq_release, | ||
1135 | }; | ||
1136 | |||
1137 | static void extfrag_show_print(struct seq_file *m, | ||
1138 | pg_data_t *pgdat, struct zone *zone) | ||
1139 | { | ||
1140 | unsigned int order; | ||
1141 | int index; | ||
1142 | |||
1143 | /* Alloc on stack as interrupts are disabled for zone walk */ | ||
1144 | struct contig_page_info info; | ||
1145 | |||
1146 | seq_printf(m, "Node %d, zone %8s ", | ||
1147 | pgdat->node_id, | ||
1148 | zone->name); | ||
1149 | for (order = 0; order < MAX_ORDER; ++order) { | ||
1150 | fill_contig_page_info(zone, order, &info); | ||
1151 | index = __fragmentation_index(order, &info); | ||
1152 | seq_printf(m, "%d.%03d ", index / 1000, index % 1000); | ||
1153 | } | ||
1154 | |||
1155 | seq_putc(m, '\n'); | ||
1156 | } | ||
1157 | |||
1158 | /* | ||
1159 | * Display fragmentation index for orders that allocations would fail for | ||
1160 | */ | ||
1161 | static int extfrag_show(struct seq_file *m, void *arg) | ||
1162 | { | ||
1163 | pg_data_t *pgdat = (pg_data_t *)arg; | ||
1164 | |||
1165 | walk_zones_in_node(m, pgdat, extfrag_show_print); | ||
1166 | |||
1167 | return 0; | ||
1168 | } | ||
1169 | |||
1170 | static const struct seq_operations extfrag_op = { | ||
1171 | .start = frag_start, | ||
1172 | .next = frag_next, | ||
1173 | .stop = frag_stop, | ||
1174 | .show = extfrag_show, | ||
1175 | }; | ||
1176 | |||
1177 | static int extfrag_open(struct inode *inode, struct file *file) | ||
1178 | { | ||
1179 | return seq_open(file, &extfrag_op); | ||
1180 | } | ||
1181 | |||
1182 | static const struct file_operations extfrag_file_ops = { | ||
1183 | .open = extfrag_open, | ||
1184 | .read = seq_read, | ||
1185 | .llseek = seq_lseek, | ||
1186 | .release = seq_release, | ||
1187 | }; | ||
1188 | |||
1189 | static int __init extfrag_debug_init(void) | ||
1190 | { | ||
1191 | extfrag_debug_root = debugfs_create_dir("extfrag", NULL); | ||
1192 | if (!extfrag_debug_root) | ||
1193 | return -ENOMEM; | ||
1194 | |||
1195 | if (!debugfs_create_file("unusable_index", 0444, | ||
1196 | extfrag_debug_root, NULL, &unusable_file_ops)) | ||
1197 | return -ENOMEM; | ||
1198 | |||
1199 | if (!debugfs_create_file("extfrag_index", 0444, | ||
1200 | extfrag_debug_root, NULL, &extfrag_file_ops)) | ||
1201 | return -ENOMEM; | ||
1202 | |||
1203 | return 0; | ||
1204 | } | ||
1205 | |||
1206 | module_init(extfrag_debug_init); | ||
1207 | #endif | ||