lkml.org 
[lkml]   [2010]   [Apr]   [20]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 10/14] mm,compaction: Add /proc trigger for memory compaction
    Date
    This patch adds 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>
    ---
    Documentation/sysctl/vm.txt | 10 +++++++
    include/linux/compaction.h | 6 ++++
    kernel/sysctl.c | 10 +++++++
    mm/compaction.c | 61 +++++++++++++++++++++++++++++++++++++++++++
    4 files changed, 87 insertions(+), 0 deletions(-)
    diff --git a/Documentation/sysctl/vm.txt b/Documentation/sysctl/vm.txt
    index 56366a5..3b3fa1b 100644
    --- a/Documentation/sysctl/vm.txt
    +++ b/Documentation/sysctl/vm.txt
    @@ -19,6 +19,7 @@ files can be found in mm/swap.c.
    Currently, these files are in /proc/sys/vm:

    - block_dump
    +- compact_memory
    - dirty_background_bytes
    - dirty_background_ratio
    - dirty_bytes
    @@ -64,6 +65,15 @@ information on block I/O debugging is in Documentation/laptops/laptop-mode.txt.

    ==============================================================

    +compact_memory
    +
    +Available only when CONFIG_COMPACTION is set. When 1 is written to the file,
    +all zones are compacted such that free memory is available in contiguous
    +blocks where possible. This can be important for example in the allocation of
    +huge pages although processes will also directly compact memory as required.
    +
    +==============================================================
    +
    dirty_background_bytes

    Contains the amount of dirty memory at which the pdflush background writeback
    diff --git a/include/linux/compaction.h b/include/linux/compaction.h
    index 465ca88..5723888 100644
    --- a/include/linux/compaction.h
    +++ b/include/linux/compaction.h
    @@ -6,4 +6,10 @@
    #define COMPACT_PARTIAL 1
    #define COMPACT_COMPLETE 2

    +#ifdef CONFIG_COMPACTION
    +extern int sysctl_compact_memory;
    +extern int sysctl_compaction_handler(struct ctl_table *table, int write,
    + void __user *buffer, size_t *length, loff_t *ppos);
    +#endif /* CONFIG_COMPACTION */
    +
    #endif /* _LINUX_COMPACTION_H */
    diff --git a/kernel/sysctl.c b/kernel/sysctl.c
    index 26f25eb..987d6cf 100644
    --- a/kernel/sysctl.c
    +++ b/kernel/sysctl.c
    @@ -37,6 +37,7 @@
    #include <linux/highuid.h>
    #include <linux/writeback.h>
    #include <linux/ratelimit.h>
    +#include <linux/compaction.h>
    #include <linux/hugetlb.h>
    #include <linux/initrd.h>
    #include <linux/key.h>
    @@ -1121,6 +1122,15 @@ static struct ctl_table vm_table[] = {
    .mode = 0644,
    .proc_handler = drop_caches_sysctl_handler,
    },
    +#ifdef CONFIG_COMPACTION
    + {
    + .procname = "compact_memory",
    + .data = &sysctl_compact_memory,
    + .maxlen = sizeof(int),
    + .mode = 0200,
    + .proc_handler = sysctl_compaction_handler,
    + },
    +#endif /* CONFIG_COMPACTION */
    {
    .procname = "min_free_kbytes",
    .data = &min_free_kbytes,
    diff --git a/mm/compaction.c b/mm/compaction.c
    index 1b80dd8..5e4444c 100644
    --- a/mm/compaction.c
    +++ b/mm/compaction.c
    @@ -12,6 +12,7 @@
    #include <linux/compaction.h>
    #include <linux/mm_inline.h>
    #include <linux/backing-dev.h>
    +#include <linux/sysctl.h>
    #include "internal.h"

    /*
    @@ -392,3 +393,63 @@ static int compact_zone(struct zone *zone, struct compact_control *cc)
    return ret;
    }

    +/* Compact all zones within a node */
    +static int compact_node(int nid)
    +{
    + int zoneid;
    + pg_data_t *pgdat;
    + struct zone *zone;
    +
    + if (nid < 0 || nid >= nr_node_ids || !node_online(nid))
    + return -EINVAL;
    + pgdat = NODE_DATA(nid);
    +
    + /* Flush pending updates to the LRU lists */
    + lru_add_drain_all();
    +
    + for (zoneid = 0; zoneid < MAX_NR_ZONES; zoneid++) {
    + struct compact_control cc = {
    + .nr_freepages = 0,
    + .nr_migratepages = 0,
    + };
    +
    + zone = &pgdat->node_zones[zoneid];
    + if (!populated_zone(zone))
    + continue;
    +
    + cc.zone = zone;
    + INIT_LIST_HEAD(&cc.freepages);
    + INIT_LIST_HEAD(&cc.migratepages);
    +
    + compact_zone(zone, &cc);
    +
    + VM_BUG_ON(!list_empty(&cc.freepages));
    + VM_BUG_ON(!list_empty(&cc.migratepages));
    + }
    +
    + return 0;
    +}
    +
    +/* Compact all nodes in the system */
    +static int compact_nodes(void)
    +{
    + int nid;
    +
    + for_each_online_node(nid)
    + compact_node(nid);
    +
    + return COMPACT_COMPLETE;
    +}
    +
    +/* The written value is actually unused, all memory is compacted */
    +int sysctl_compact_memory;
    +
    +/* This is the entry point for compacting all nodes via /proc/sys/vm */
    +int sysctl_compaction_handler(struct ctl_table *table, int write,
    + void __user *buffer, size_t *length, loff_t *ppos)
    +{
    + if (write)
    + return compact_nodes();
    +
    + return 0;
    +}
    --
    1.6.5


    \
     
     \ /
      Last update: 2010-04-20 23:05    [from the cache]
    ©2003-2011 Jasper Spaans