Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit e496cf3d authored by Kirill A. Shutemov's avatar Kirill A. Shutemov Committed by Linus Torvalds
Browse files

thp: introduce CONFIG_TRANSPARENT_HUGE_PAGECACHE

For file mappings, we don't deposit page tables on THP allocation
because it's not strictly required to implement split_huge_pmd(): we can
just clear pmd and let following page faults to reconstruct the page
table.

But Power makes use of deposited page table to address MMU quirk.

Let's hide THP page cache, including huge tmpfs, under separate config
option, so it can be forbidden on Power.

We can revert the patch later once solution for Power found.

Link: http://lkml.kernel.org/r/1466021202-61880-36-git-send-email-kirill.shutemov@linux.intel.com


Signed-off-by: default avatarKirill A. Shutemov <kirill.shutemov@linux.intel.com>
Cc: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent f3f0e1d2
Loading
Loading
Loading
Loading
+9 −1
Original line number Diff line number Diff line
@@ -54,7 +54,6 @@ extern unsigned long shmem_get_unmapped_area(struct file *, unsigned long addr,
		unsigned long len, unsigned long pgoff, unsigned long flags);
extern int shmem_lock(struct file *file, int lock, struct user_struct *user);
extern bool shmem_mapping(struct address_space *mapping);
extern bool shmem_huge_enabled(struct vm_area_struct *vma);
extern void shmem_unlock_mapping(struct address_space *mapping);
extern struct page *shmem_read_mapping_page_gfp(struct address_space *mapping,
					pgoff_t index, gfp_t gfp_mask);
@@ -112,4 +111,13 @@ static inline long shmem_fcntl(struct file *f, unsigned int c, unsigned long a)

#endif

#ifdef CONFIG_TRANSPARENT_HUGE_PAGECACHE
extern bool shmem_huge_enabled(struct vm_area_struct *vma);
#else
static inline bool shmem_huge_enabled(struct vm_area_struct *vma)
{
	return false;
}
#endif

#endif
+8 −0
Original line number Diff line number Diff line
@@ -439,6 +439,14 @@ choice
	  benefit.
endchoice

#
# We don't deposit page tables on file THP mapping,
# but Power makes use of them to address MMU quirk.
#
config	TRANSPARENT_HUGE_PAGECACHE
	def_bool y
	depends on TRANSPARENT_HUGEPAGE && !PPC

#
# UP and nommu archs use km based percpu allocator
#
+1 −1
Original line number Diff line number Diff line
@@ -287,7 +287,7 @@ static struct attribute *hugepage_attr[] = {
	&enabled_attr.attr,
	&defrag_attr.attr,
	&use_zero_page_attr.attr,
#ifdef CONFIG_SHMEM
#if defined(CONFIG_SHMEM) && defined(CONFIG_TRANSPARENT_HUGE_PAGECACHE)
	&shmem_enabled_attr.attr,
#endif
#ifdef CONFIG_DEBUG_VM
+7 −4
Original line number Diff line number Diff line
@@ -819,6 +819,8 @@ static bool hugepage_vma_check(struct vm_area_struct *vma)
	    (vma->vm_flags & VM_NOHUGEPAGE))
		return false;
	if (shmem_file(vma->vm_file)) {
		if (!IS_ENABLED(CONFIG_TRANSPARENT_HUGE_PAGECACHE))
			return false;
		return IS_ALIGNED((vma->vm_start >> PAGE_SHIFT) - vma->vm_pgoff,
				HPAGE_PMD_NR);
	}
@@ -1222,7 +1224,7 @@ static void collect_mm_slot(struct mm_slot *mm_slot)
	}
}

#ifdef CONFIG_SHMEM
#if defined(CONFIG_SHMEM) && defined(CONFIG_TRANSPARENT_HUGE_PAGECACHE)
static void retract_page_tables(struct address_space *mapping, pgoff_t pgoff)
{
	struct vm_area_struct *vma;
@@ -1681,8 +1683,6 @@ static unsigned int khugepaged_scan_mm_slot(unsigned int pages,
		if (khugepaged_scan.address < hstart)
			khugepaged_scan.address = hstart;
		VM_BUG_ON(khugepaged_scan.address & ~HPAGE_PMD_MASK);
		if (shmem_file(vma->vm_file) && !shmem_huge_enabled(vma))
			goto skip;

		while (khugepaged_scan.address < hend) {
			int ret;
@@ -1694,9 +1694,12 @@ static unsigned int khugepaged_scan_mm_slot(unsigned int pages,
				  khugepaged_scan.address + HPAGE_PMD_SIZE >
				  hend);
			if (shmem_file(vma->vm_file)) {
				struct file *file = get_file(vma->vm_file);
				struct file *file;
				pgoff_t pgoff = linear_page_index(vma,
						khugepaged_scan.address);
				if (!shmem_huge_enabled(vma))
					goto skip;
				file = get_file(vma->vm_file);
				up_read(&mm->mmap_sem);
				ret = 1;
				khugepaged_scan_shmem(mm, file->f_mapping,
+3 −2
Original line number Diff line number Diff line
@@ -2920,7 +2920,7 @@ static int pte_alloc_one_map(struct fault_env *fe)
	return 0;
}

#ifdef CONFIG_TRANSPARENT_HUGEPAGE
#ifdef CONFIG_TRANSPARENT_HUGE_PAGECACHE

#define HPAGE_CACHE_INDEX_MASK (HPAGE_PMD_NR - 1)
static inline bool transhuge_vma_suitable(struct vm_area_struct *vma,
@@ -3002,7 +3002,8 @@ int alloc_set_pte(struct fault_env *fe, struct mem_cgroup *memcg,
	pte_t entry;
	int ret;

	if (pmd_none(*fe->pmd) && PageTransCompound(page)) {
	if (pmd_none(*fe->pmd) && PageTransCompound(page) &&
			IS_ENABLED(CONFIG_TRANSPARENT_HUGE_PAGECACHE)) {
		/* THP on COW? */
		VM_BUG_ON_PAGE(memcg, page);

Loading