Commit dc801cc2 authored by Liu Shixin's avatar Liu Shixin
Browse files

mm/huge_memory: allow to enable 64K anouymous mapping align alone

hulk inclusion
category: feature
bugzilla: https://gitee.com/openeuler/kernel/issues/IAKLTF



--------------------------------

In commit 08f7407a ("mm: add thp anon pmd size mapping align control"),
we add a control to pmd size anouymous mapping align. But not as the name
shows, it controls 64K anonymous mapping align too, which is so weird.

To fix it, we move thp_anon_mapping_pmd_align into thp_get_unmapped_area().
And allow user to enable 64K anouymous mapping align without enable pmd
size anouymous mapping align.

By the way, refactor the code of mapping align to make it more readable.

Signed-off-by: default avatarLiu Shixin <liushixin2@huawei.com>
parent 09350a7c
Loading
Loading
Loading
Loading
+4 −6
Original line number Diff line number Diff line
@@ -211,12 +211,10 @@ possible to enable/disable it by configurate the corresponding bit::
	echo 0x2 >/sys/kernel/mm/transparent_hugepage/thp_exec_enabled
	echo 0x3 >/sys/kernel/mm/transparent_hugepage/thp_exec_enabled

The kernel could try to enable mappings for different sizes, eg, 64K on
arm64, BIT0 for file mapping, BIT1 for anonymous mapping, and THP size
page, BIT2 for anonymous mapping, where 2M anonymous mapping for arm64
is dependent on BIT2 being turned on, the above feature are disabled by
default, and could enable the above feature by writing the corresponding
bit to 1::
The kernel could try to enable mappings for different sizes, BIT0 for
64K file mapping, BIT1 for 64K anonymous mapping, and BIT2 for PMD size
anonymous mapping, the above feature are disabled by default, and could
enable the above feature by writing the corresponding bit to 1::

	echo 0x1 >/sys/kernel/mm/transparent_hugepage/thp_mapping_align
	echo 0x4 >/sys/kernel/mm/transparent_hugepage/thp_mapping_align
+0 −6
Original line number Diff line number Diff line
@@ -313,10 +313,6 @@ static inline void count_mthp_stat(int order, enum mthp_stat_item item)
	(transparent_hugepage_flags &				\
	 (1<<TRANSPARENT_HUGEPAGE_FILE_MTHP_FLAG))

#define thp_anon_mapping_pmd_align()				\
	(transparent_hugepage_flags &				\
	 (1<<TRANSPARENT_HUGEPAGE_ANON_MAPPING_PMD_ALIGN_FLAG))

unsigned long thp_get_unmapped_area(struct file *filp, unsigned long addr,
		unsigned long len, unsigned long pgoff, unsigned long flags);

@@ -472,8 +468,6 @@ static inline void folio_prep_large_rmappable(struct folio *folio) {}

#define file_mthp_enabled()	false

#define thp_anon_mapping_pmd_align()	NULL

#define thp_get_unmapped_area	NULL

static inline bool
+28 −52
Original line number Diff line number Diff line
@@ -602,8 +602,7 @@ static ssize_t thp_mapping_align_store(struct kobject *kobj,
	ret = kstrtoul(buf, 16, &val);
	if (ret < 0)
		return ret;
	if ((val & ~THP_MAPPING_ALIGN_ALL) || (!(val & ANON_MAPPING_PMD_ALIGN) &&
	    (val & ANON_MAPPING_ALIGN)))
	if (val & ~THP_MAPPING_ALIGN_ALL)
		return -EINVAL;

	thp_flag_set(TRANSPARENT_HUGEPAGE_FILE_MAPPING_ALIGN_FLAG,
@@ -1088,64 +1087,31 @@ static unsigned long __thp_get_unmapped_area(struct file *filp,
	return ret;
}

#define thp_file_mapping_align_enabled()			\
#define mthp_file_mapping_align()				\
	(transparent_hugepage_flags &				\
	 (1<<TRANSPARENT_HUGEPAGE_FILE_MAPPING_ALIGN_FLAG))

#define thp_anon_mapping_align_enabled()			\
#define mthp_anon_mapping_align()			\
	(transparent_hugepage_flags &				\
	 (1<<TRANSPARENT_HUGEPAGE_ANON_MAPPING_ALIGN_FLAG))

static bool file_mapping_align_enabled(struct file *filp)
#define thp_anon_mapping_align()				\
	(transparent_hugepage_flags &				\
	 (1<<TRANSPARENT_HUGEPAGE_ANON_MAPPING_PMD_ALIGN_FLAG))

static bool mthp_mapping_align_enabled(struct file *filp)
{
	struct address_space *mapping;

	if (!thp_file_mapping_align_enabled())
		return false;

	if (!filp)
		return false;

	mapping = filp->f_mapping;
	if (!mapping || !mapping_large_folio_support(mapping))
		return false;

	return true;
}

static bool anon_mapping_align_enabled(int order)
{
	unsigned long mask;

	if (!thp_anon_mapping_align_enabled())
		return 0;

	mask = READ_ONCE(huge_anon_orders_always) |
	       READ_ONCE(huge_anon_orders_madvise);
		return mthp_anon_mapping_align();

	if (hugepage_global_enabled())
		mask |= READ_ONCE(huge_anon_orders_inherit);

	mask = BIT(order) & mask;
	if (!mask)
	if (!mthp_file_mapping_align())
		return false;

	return true;
}

static unsigned long folio_get_unmapped_area(struct file *filp, unsigned long addr,
		unsigned long len, unsigned long pgoff, unsigned long flags)
{
	int order = arch_wants_exec_folio_order();

	if (order < 0)
		return 0;
	mapping = filp->f_mapping;

	if (file_mapping_align_enabled(filp) ||
		(!filp && anon_mapping_align_enabled(order)))
		return __thp_get_unmapped_area(filp, addr, len, pgoff, flags,
					       PAGE_SIZE << order);
	return 0;
	return mapping && mapping_large_folio_support(mapping);
}

unsigned long thp_get_unmapped_area(struct file *filp, unsigned long addr,
@@ -1154,13 +1120,23 @@ unsigned long thp_get_unmapped_area(struct file *filp, unsigned long addr,
	unsigned long ret;
	loff_t off = (loff_t)pgoff << PAGE_SHIFT;

	ret = __thp_get_unmapped_area(filp, addr, len, off, flags, PMD_SIZE);
	if (filp || thp_anon_mapping_align()) {
		ret = __thp_get_unmapped_area(filp, addr, len, off, flags,
					      PMD_SIZE);
		if (ret)
			return ret;
	}

	ret = folio_get_unmapped_area(filp, addr, len, off, flags);
	if (mthp_mapping_align_enabled(filp)) {
		int order = arch_wants_exec_folio_order();

		if (order >= 0) {
			ret = __thp_get_unmapped_area(filp, addr, len, off,
					flags, PAGE_SIZE << order);
			if (ret)
				return ret;
		}
	}

	return current->mm->get_unmapped_area(filp, addr, len, pgoff, flags);
}
+1 −2
Original line number Diff line number Diff line
@@ -1859,8 +1859,7 @@ get_unmapped_area(struct file *file, unsigned long addr, unsigned long len,
		 * so use shmem's get_unmapped_area in case it can be huge.
		 */
		get_area = shmem_get_unmapped_area;
	} else if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE) &&
		   thp_anon_mapping_pmd_align()) {
	} else if (IS_ENABLED(CONFIG_TRANSPARENT_HUGEPAGE)) {
		/* Ensures that larger anonymous mappings are THP aligned. */
		get_area = thp_get_unmapped_area;
	}