Commit c01cfed1 authored by Baolin Wang's avatar Baolin Wang Committed by Euler
Browse files

mm: shmem: fix incorrect index alignment for within_size policy

mainline inclusion
from mainline-v6.13-rc1
commit d0e6983a6d1719738cf8d13982a68094f0a1872a
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/IBGFBA

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d0e6983a6d1719738cf8d13982a68094f0a1872a

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

With enabling the shmem per-size within_size policy, using an incorrect
'order' size to round_up() the index can lead to incorrect i_size checks,
resulting in an inappropriate large orders being returned.

Changing to use '1 << order' to round_up() the index to fix this issue.
Additionally, adding an 'aligned_index' variable to avoid affecting the
index checks.

Link: https://lkml.kernel.org/r/77d8ef76a7d3d646e9225e9af88a76549a68aab1.1734593154.git.baolin.wang@linux.alibaba.com


Fixes: e7a2ab7b3bb5 ("mm: shmem: add mTHP support for anonymous shmem")
Signed-off-by: default avatarBaolin Wang <baolin.wang@linux.alibaba.com>
Acked-by: default avatarDavid Hildenbrand <david@redhat.com>
Cc: Hugh Dickins <hughd@google.com>
Cc: <stable@vger.kernel.org>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarWang Lian <dev01404@linx-info.com>
---
parent 604e996d
Loading
Loading
Loading
Loading
+3 −2
Original line number Diff line number Diff line
@@ -1682,6 +1682,7 @@ unsigned long shmem_allowable_huge_orders(struct inode *inode,
	unsigned long mask = READ_ONCE(huge_shmem_orders_always);
	unsigned long within_size_orders = READ_ONCE(huge_shmem_orders_within_size);
	unsigned long vm_flags = vma ? vma->vm_flags : 0;
	pgoff_t aligned_index;
	bool global_huge;
	loff_t i_size;
	int order;
@@ -1716,9 +1717,9 @@ unsigned long shmem_allowable_huge_orders(struct inode *inode,
	/* Allow mTHP that will be fully within i_size. */
	order = highest_order(within_size_orders);
	while (within_size_orders) {
		index = round_up(index + 1, order);
		aligned_index = round_up(index + 1, 1 << order);
		i_size = round_up(i_size_read(inode), PAGE_SIZE);
		if (i_size >> PAGE_SHIFT >= index) {
		if (i_size >> PAGE_SHIFT >= aligned_index) {
			mask |= within_size_orders;
			break;
		}