diff options
author | Mel Gorman <mel@csn.ul.ie> | 2010-05-24 17:32:28 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-05-25 11:06:59 -0400 |
commit | 76ab0f530e4a01d4dc20cdc1d5e87753c579dc18 (patch) | |
tree | 8e1566df85e02f67876685c36d217fec4845f79f /mm | |
parent | 748446bb6b5a9390b546af38ec899c868a9dbcf0 (diff) |
mm: compaction: add /proc trigger for memory compaction
Add a proc file /proc/sys/vm/compact_memory. When an arbitrary value is
written to the file, all zones are compacted. The expected user of such a
trigger is a job scheduler that prepares the system before the target
application runs.
Signed-off-by: Mel Gorman <mel@csn.ul.ie>
Acked-by: Rik van Riel <riel@redhat.com>
Reviewed-by: KAMEZAWA Hiroyuki <kamezawa.hiroyu@jp.fujitsu.com>
Reviewed-by: Minchan Kim <minchan.kim@gmail.com>
Reviewed-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com>
Reviewed-by: Christoph Lameter <cl@linux-foundation.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm')
-rw-r--r-- | mm/compaction.c | 62 |
1 files changed, 62 insertions, 0 deletions
diff --git a/mm/compaction.c b/mm/compaction.c index be1ff3f7552b..77854fbc0f56 100644 --- a/mm/compaction.c +++ b/mm/compaction.c | |||
@@ -12,6 +12,7 @@ | |||
12 | #include <linux/compaction.h> | 12 | #include <linux/compaction.h> |
13 | #include <linux/mm_inline.h> | 13 | #include <linux/mm_inline.h> |
14 | #include <linux/backing-dev.h> | 14 | #include <linux/backing-dev.h> |
15 | #include <linux/sysctl.h> | ||
15 | #include "internal.h" | 16 | #include "internal.h" |
16 | 17 | ||
17 | /* | 18 | /* |
@@ -391,3 +392,64 @@ static int compact_zone(struct zone *zone, struct compact_control *cc) | |||
391 | 392 | ||
392 | return ret; | 393 | return ret; |
393 | } | 394 | } |
395 | |||
396 | /* Compact all zones within a node */ | ||
397 | static int compact_node(int nid) | ||
398 | { | ||
399 | int zoneid; | ||
400 | pg_data_t *pgdat; | ||
401 | struct zone *zone; | ||
402 | |||
403 | if (nid < 0 || nid >= nr_node_ids || !node_online(nid)) | ||
404 | return -EINVAL; | ||
405 | pgdat = NODE_DATA(nid); | ||
406 | |||
407 | /* Flush pending updates to the LRU lists */ | ||
408 | lru_add_drain_all(); | ||
409 | |||
410 | for (zoneid = 0; zoneid < MAX_NR_ZONES; zoneid++) { | ||
411 | struct compact_control cc = { | ||
412 | .nr_freepages = 0, | ||
413 | .nr_migratepages = 0, | ||
414 | }; | ||
415 | |||
416 | zone = &pgdat->node_zones[zoneid]; | ||
417 | if (!populated_zone(zone)) | ||
418 | continue; | ||
419 | |||
420 | cc.zone = zone; | ||
421 | INIT_LIST_HEAD(&cc.freepages); | ||
422 | INIT_LIST_HEAD(&cc.migratepages); | ||
423 | |||
424 | compact_zone(zone, &cc); | ||
425 | |||
426 | VM_BUG_ON(!list_empty(&cc.freepages)); | ||
427 | VM_BUG_ON(!list_empty(&cc.migratepages)); | ||
428 | } | ||
429 | |||
430 | return 0; | ||
431 | } | ||
432 | |||
433 | /* Compact all nodes in the system */ | ||
434 | static int compact_nodes(void) | ||
435 | { | ||
436 | int nid; | ||
437 | |||
438 | for_each_online_node(nid) | ||
439 | compact_node(nid); | ||
440 | |||
441 | return COMPACT_COMPLETE; | ||
442 | } | ||
443 | |||
444 | /* The written value is actually unused, all memory is compacted */ | ||
445 | int sysctl_compact_memory; | ||
446 | |||
447 | /* This is the entry point for compacting all nodes via /proc/sys/vm */ | ||
448 | int sysctl_compaction_handler(struct ctl_table *table, int write, | ||
449 | void __user *buffer, size_t *length, loff_t *ppos) | ||
450 | { | ||
451 | if (write) | ||
452 | return compact_nodes(); | ||
453 | |||
454 | return 0; | ||
455 | } | ||