diff options
author | Mel Gorman <mel@csn.ul.ie> | 2010-05-24 17:32:26 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-25 11:06:59 -0400 |
commit | f1a5ab1210579e2d3ac8c0c227645823af5aafb0 (patch) | |
tree | c646a3d58150eab1a8280d02e6254ef6b90a6f37 /mm/vmstat.c | |
parent | d7a5752c0c19750312efab3a2a80d350e11fa4a2 (diff) |
mm: export fragmentation index via debugfs
The fragmentation fragmentation index, is only meaningful if an allocation
would fail and indicates what the failure is due to. A value of -1 such
as in many of the examples above states that the allocation would succeed.
If it would fail, the value is between 0 and 1. A value tending towards
0 implies the allocation failed due to a lack of memory. A value tending
towards 1 implies it failed due to external fragmentation.
For the most part, the huge page size will be the size of interest but not
necessarily so it is exported on a per-order and per-zo basis via
/sys/kernel/debug/extfrag/extfrag_index
> cat /sys/kernel/debug/extfrag/extfrag_index
Node 0, zone DMA -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.00
Node 0, zone Normal -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 -1.000 0.954
Signed-off-by: Mel Gorman <mel@csn.ul.ie>
Reviewed-by: Minchan Kim <minchan.kim@gmail.com>
Acked-by: Rik van Riel <riel@redhat.com>
Reviewed-by: Christoph Lameter <cl@linux-foundation.org>
Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Cc: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/vmstat.c')
-rw-r--r-- | mm/vmstat.c | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/mm/vmstat.c b/mm/vmstat.c index d3e0fa169f05..23a5899c7461 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}}; |
@@ -420,6 +421,33 @@ static void fill_contig_page_info(struct zone *zone, | |||
420 | (order - suitable_order); | 421 | (order - suitable_order); |
421 | } | 422 | } |
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 | 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 | } | ||
423 | #endif | 451 | #endif |
424 | 452 | ||
425 | #if defined(CONFIG_PROC_FS) || defined(CONFIG_COMPACTION) | 453 | #if defined(CONFIG_PROC_FS) || defined(CONFIG_COMPACTION) |
@@ -1087,6 +1115,58 @@ static const struct file_operations unusable_file_ops = { | |||
1087 | .release = seq_release, | 1115 | .release = seq_release, |
1088 | }; | 1116 | }; |
1089 | 1117 | ||
1118 | static void extfrag_show_print(struct seq_file *m, | ||
1119 | pg_data_t *pgdat, struct zone *zone) | ||
1120 | { | ||
1121 | unsigned int order; | ||
1122 | int index; | ||
1123 | |||
1124 | /* Alloc on stack as interrupts are disabled for zone walk */ | ||
1125 | struct contig_page_info info; | ||
1126 | |||
1127 | seq_printf(m, "Node %d, zone %8s ", | ||
1128 | pgdat->node_id, | ||
1129 | zone->name); | ||
1130 | for (order = 0; order < MAX_ORDER; ++order) { | ||
1131 | fill_contig_page_info(zone, order, &info); | ||
1132 | index = fragmentation_index(order, &info); | ||
1133 | seq_printf(m, "%d.%03d ", index / 1000, index % 1000); | ||
1134 | } | ||
1135 | |||
1136 | seq_putc(m, '\n'); | ||
1137 | } | ||
1138 | |||
1139 | /* | ||
1140 | * Display fragmentation index for orders that allocations would fail for | ||
1141 | */ | ||
1142 | static int extfrag_show(struct seq_file *m, void *arg) | ||
1143 | { | ||
1144 | pg_data_t *pgdat = (pg_data_t *)arg; | ||
1145 | |||
1146 | walk_zones_in_node(m, pgdat, extfrag_show_print); | ||
1147 | |||
1148 | return 0; | ||
1149 | } | ||
1150 | |||
1151 | static const struct seq_operations extfrag_op = { | ||
1152 | .start = frag_start, | ||
1153 | .next = frag_next, | ||
1154 | .stop = frag_stop, | ||
1155 | .show = extfrag_show, | ||
1156 | }; | ||
1157 | |||
1158 | static int extfrag_open(struct inode *inode, struct file *file) | ||
1159 | { | ||
1160 | return seq_open(file, &extfrag_op); | ||
1161 | } | ||
1162 | |||
1163 | static const struct file_operations extfrag_file_ops = { | ||
1164 | .open = extfrag_open, | ||
1165 | .read = seq_read, | ||
1166 | .llseek = seq_lseek, | ||
1167 | .release = seq_release, | ||
1168 | }; | ||
1169 | |||
1090 | static int __init extfrag_debug_init(void) | 1170 | static int __init extfrag_debug_init(void) |
1091 | { | 1171 | { |
1092 | extfrag_debug_root = debugfs_create_dir("extfrag", NULL); | 1172 | extfrag_debug_root = debugfs_create_dir("extfrag", NULL); |
@@ -1097,6 +1177,10 @@ static int __init extfrag_debug_init(void) | |||
1097 | extfrag_debug_root, NULL, &unusable_file_ops)) | 1177 | extfrag_debug_root, NULL, &unusable_file_ops)) |
1098 | return -ENOMEM; | 1178 | return -ENOMEM; |
1099 | 1179 | ||
1180 | if (!debugfs_create_file("extfrag_index", 0444, | ||
1181 | extfrag_debug_root, NULL, &extfrag_file_ops)) | ||
1182 | return -ENOMEM; | ||
1183 | |||
1100 | return 0; | 1184 | return 0; |
1101 | } | 1185 | } |
1102 | 1186 | ||