aboutsummaryrefslogtreecommitdiffstats
path: root/mm/huge_memory.c
diff options
context:
space:
mode:
authorKirill A. Shutemov <kirill.shutemov@linux.intel.com>2016-01-15 19:54:40 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2016-01-15 20:56:32 -0500
commit49071d436b51b58aeaf7abcd1877f38ca0146e31 (patch)
tree2adf8f687cc81072646412a97c07d2abc077182a /mm/huge_memory.c
parentb20ce5e03b936be077463015661dcf52be274e5b (diff)
thp: add debugfs handle to split all huge pages
Writing 1 into 'split_huge_pages' will try to find and split all huge pages in the system. This is useful for debuging. [akpm@linux-foundation.org: fix printk text, per Vlastimil] Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Cc: Sasha Levin <sasha.levin@oracle.com> Cc: Andrea Arcangeli <aarcange@redhat.com> Acked-by: Vlastimil Babka <vbabka@suse.cz> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'mm/huge_memory.c')
-rw-r--r--mm/huge_memory.c59
1 files changed, 59 insertions, 0 deletions
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index ab544b145b52..a0b910a0c2cb 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -23,6 +23,7 @@
23#include <linux/freezer.h> 23#include <linux/freezer.h>
24#include <linux/mman.h> 24#include <linux/mman.h>
25#include <linux/pagemap.h> 25#include <linux/pagemap.h>
26#include <linux/debugfs.h>
26#include <linux/migrate.h> 27#include <linux/migrate.h>
27#include <linux/hashtable.h> 28#include <linux/hashtable.h>
28#include <linux/userfaultfd_k.h> 29#include <linux/userfaultfd_k.h>
@@ -3350,3 +3351,61 @@ static struct shrinker deferred_split_shrinker = {
3350 .scan_objects = deferred_split_scan, 3351 .scan_objects = deferred_split_scan,
3351 .seeks = DEFAULT_SEEKS, 3352 .seeks = DEFAULT_SEEKS,
3352}; 3353};
3354
3355#ifdef CONFIG_DEBUG_FS
3356static int split_huge_pages_set(void *data, u64 val)
3357{
3358 struct zone *zone;
3359 struct page *page;
3360 unsigned long pfn, max_zone_pfn;
3361 unsigned long total = 0, split = 0;
3362
3363 if (val != 1)
3364 return -EINVAL;
3365
3366 for_each_populated_zone(zone) {
3367 max_zone_pfn = zone_end_pfn(zone);
3368 for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++) {
3369 if (!pfn_valid(pfn))
3370 continue;
3371
3372 page = pfn_to_page(pfn);
3373 if (!get_page_unless_zero(page))
3374 continue;
3375
3376 if (zone != page_zone(page))
3377 goto next;
3378
3379 if (!PageHead(page) || !PageAnon(page) ||
3380 PageHuge(page))
3381 goto next;
3382
3383 total++;
3384 lock_page(page);
3385 if (!split_huge_page(page))
3386 split++;
3387 unlock_page(page);
3388next:
3389 put_page(page);
3390 }
3391 }
3392
3393 pr_info("%lu of %lu THP split", split, total);
3394
3395 return 0;
3396}
3397DEFINE_SIMPLE_ATTRIBUTE(split_huge_pages_fops, NULL, split_huge_pages_set,
3398 "%llu\n");
3399
3400static int __init split_huge_pages_debugfs(void)
3401{
3402 void *ret;
3403
3404 ret = debugfs_create_file("split_huge_pages", 0644, NULL, NULL,
3405 &split_huge_pages_fops);
3406 if (!ret)
3407 pr_warn("Failed to create split_huge_pages in debugfs");
3408 return 0;
3409}
3410late_initcall(split_huge_pages_debugfs);
3411#endif