]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
mm: allow compaction of unevictable pages
authorEric B Munson <emunson@akamai.com>
Tue, 7 Apr 2015 23:44:27 +0000 (09:44 +1000)
committerStephen Rothwell <sfr@canb.auug.org.au>
Tue, 7 Apr 2015 23:44:27 +0000 (09:44 +1000)
Currently, pages which are marked as unevictable are protected from
compaction, but not from other types of migration.  The POSIX real time
extension explicitly states that mlock() will prevent a major page fault,
but the spirit of this is that mlock() should give a process the ability
to control sources of latency, including minor page faults.  However, the
mlock manpage only explicitly says that a locked page will not be written
to swap and this can cause some confusion.  The compaction code today does
not give a developer who wants to avoid swap but wants to have large
contiguous areas available any method to achieve this state.  This patch
introduces a sysctl for controlling compaction behavior with respect to
the unevictable lru.  Users who demand no page faults after a page is
present can set compact_unevictable_allowed to 0 and users who need the
large contiguous areas can enable compaction on locked memory by leaving
the default value of 1.

To illustrate this problem I wrote a quick test program that mmaps a large
number of 1MB files filled with random data.  These maps are created
locked and read only.  Then every other mmap is unmapped and I attempt to
allocate huge pages to the static huge page pool.  When the
compact_unevictable_allowed sysctl is 0, I cannot allocate hugepages after
fragmenting memory.  When the value is set to 1, allocations succeed.

Signed-off-by: Eric B Munson <emunson@akamai.com>
Acked-by: Michal Hocko <mhocko@suse.cz>
Acked-by: Vlastimil Babka <vbabka@suse.cz>
Acked-by: Christoph Lameter <cl@linux.com>
Acked-by: David Rientjes <rientjes@google.com>
Acked-by: Rik van Riel <riel@redhat.com>
Cc: Vlastimil Babka <vbabka@suse.cz>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Christoph Lameter <cl@linux.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Mel Gorman <mgorman@suse.de>
Cc: David Rientjes <rientjes@google.com>
Cc: Michal Hocko <mhocko@suse.cz>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Documentation/sysctl/vm.txt
include/linux/compaction.h
kernel/sysctl.c
mm/compaction.c

index 902b4574acfbbae33be058eeae51551600d2fd21..9832ec52f859a2f4e3c99b0767ef957a59a97bf1 100644 (file)
@@ -21,6 +21,7 @@ Currently, these files are in /proc/sys/vm:
 - admin_reserve_kbytes
 - block_dump
 - compact_memory
+- compact_unevictable_allowed
 - dirty_background_bytes
 - dirty_background_ratio
 - dirty_bytes
@@ -106,6 +107,16 @@ huge pages although processes will also directly compact memory as required.
 
 ==============================================================
 
+compact_unevictable_allowed
+
+Available only when CONFIG_COMPACTION is set. When set to 1, compaction is
+allowed to examine the unevictable lru (mlocked pages) for pages to compact.
+This should be used on systems where stalls for minor page faults are an
+acceptable trade for large contiguous free memory.  Set to 0 to prevent
+compaction from moving pages that are unevictable.  Default value is 1.
+
+==============================================================
+
 dirty_background_bytes
 
 Contains the amount of dirty memory at which the background kernel
index a014559e4a49d7a3bb95d49e72e68221ef8f4548..aa8f61cf3a19fa3a28214f2a504e031e9e7d3e68 100644 (file)
@@ -34,6 +34,7 @@ extern int sysctl_compaction_handler(struct ctl_table *table, int write,
 extern int sysctl_extfrag_threshold;
 extern int sysctl_extfrag_handler(struct ctl_table *table, int write,
                        void __user *buffer, size_t *length, loff_t *ppos);
+extern int sysctl_compact_unevictable_allowed;
 
 extern int fragmentation_index(struct zone *zone, unsigned int order);
 extern unsigned long try_to_compact_pages(gfp_t gfp_mask, unsigned int order,
index 245e7dcc3741a59c051c4d0dad0ca953071d6991..4d6629b24da81337bc5063824e357f9c13e76969 100644 (file)
@@ -1334,6 +1334,15 @@ static struct ctl_table vm_table[] = {
                .extra1         = &min_extfrag_threshold,
                .extra2         = &max_extfrag_threshold,
        },
+       {
+               .procname       = "compact_unevictable_allowed",
+               .data           = &sysctl_compact_unevictable_allowed,
+               .maxlen         = sizeof(int),
+               .mode           = 0644,
+               .proc_handler   = proc_dointvec,
+               .extra1         = &zero,
+               .extra2         = &one,
+       },
 
 #endif /* CONFIG_COMPACTION */
        {
index a18201a8124e5d0443e8231f8600cb3e2976d55c..570426edcadf8e08f0adc3ade02841c4fbea9e3e 100644 (file)
@@ -1046,6 +1046,12 @@ typedef enum {
        ISOLATE_SUCCESS,        /* Pages isolated, migrate */
 } isolate_migrate_t;
 
+/*
+ * Allow userspace to control policy on scanning the unevictable LRU for
+ * compactable pages.
+ */
+int sysctl_compact_unevictable_allowed __read_mostly = 1;
+
 /*
  * Isolate all pages that can be migrated from the first suitable block,
  * starting at the block pointed to by the migrate scanner pfn within
@@ -1057,6 +1063,7 @@ static isolate_migrate_t isolate_migratepages(struct zone *zone,
        unsigned long low_pfn, end_pfn;
        struct page *page;
        const isolate_mode_t isolate_mode =
+               (sysctl_compact_unevictable_allowed ? ISOLATE_UNEVICTABLE : 0) |
                (cc->mode == MIGRATE_ASYNC ? ISOLATE_ASYNC_MIGRATE : 0);
 
        /*