mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 02:30:34 +02:00 
			
		
		
		
	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>
This commit is contained in:
		
							parent
							
								
									b20ce5e03b
								
							
						
					
					
						commit
						49071d436b
					
				
					 1 changed files with 59 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -23,6 +23,7 @@
 | 
			
		|||
#include <linux/freezer.h>
 | 
			
		||||
#include <linux/mman.h>
 | 
			
		||||
#include <linux/pagemap.h>
 | 
			
		||||
#include <linux/debugfs.h>
 | 
			
		||||
#include <linux/migrate.h>
 | 
			
		||||
#include <linux/hashtable.h>
 | 
			
		||||
#include <linux/userfaultfd_k.h>
 | 
			
		||||
| 
						 | 
				
			
			@ -3350,3 +3351,61 @@ static struct shrinker deferred_split_shrinker = {
 | 
			
		|||
	.scan_objects = deferred_split_scan,
 | 
			
		||||
	.seeks = DEFAULT_SEEKS,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_DEBUG_FS
 | 
			
		||||
static int split_huge_pages_set(void *data, u64 val)
 | 
			
		||||
{
 | 
			
		||||
	struct zone *zone;
 | 
			
		||||
	struct page *page;
 | 
			
		||||
	unsigned long pfn, max_zone_pfn;
 | 
			
		||||
	unsigned long total = 0, split = 0;
 | 
			
		||||
 | 
			
		||||
	if (val != 1)
 | 
			
		||||
		return -EINVAL;
 | 
			
		||||
 | 
			
		||||
	for_each_populated_zone(zone) {
 | 
			
		||||
		max_zone_pfn = zone_end_pfn(zone);
 | 
			
		||||
		for (pfn = zone->zone_start_pfn; pfn < max_zone_pfn; pfn++) {
 | 
			
		||||
			if (!pfn_valid(pfn))
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			page = pfn_to_page(pfn);
 | 
			
		||||
			if (!get_page_unless_zero(page))
 | 
			
		||||
				continue;
 | 
			
		||||
 | 
			
		||||
			if (zone != page_zone(page))
 | 
			
		||||
				goto next;
 | 
			
		||||
 | 
			
		||||
			if (!PageHead(page) || !PageAnon(page) ||
 | 
			
		||||
					PageHuge(page))
 | 
			
		||||
				goto next;
 | 
			
		||||
 | 
			
		||||
			total++;
 | 
			
		||||
			lock_page(page);
 | 
			
		||||
			if (!split_huge_page(page))
 | 
			
		||||
				split++;
 | 
			
		||||
			unlock_page(page);
 | 
			
		||||
next:
 | 
			
		||||
			put_page(page);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	pr_info("%lu of %lu THP split", split, total);
 | 
			
		||||
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
DEFINE_SIMPLE_ATTRIBUTE(split_huge_pages_fops, NULL, split_huge_pages_set,
 | 
			
		||||
		"%llu\n");
 | 
			
		||||
 | 
			
		||||
static int __init split_huge_pages_debugfs(void)
 | 
			
		||||
{
 | 
			
		||||
	void *ret;
 | 
			
		||||
 | 
			
		||||
	ret = debugfs_create_file("split_huge_pages", 0644, NULL, NULL,
 | 
			
		||||
			&split_huge_pages_fops);
 | 
			
		||||
	if (!ret)
 | 
			
		||||
		pr_warn("Failed to create split_huge_pages in debugfs");
 | 
			
		||||
	return 0;
 | 
			
		||||
}
 | 
			
		||||
late_initcall(split_huge_pages_debugfs);
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue