Skip to content

Commit 734654a

Browse files
xzpetergregkh
authored andcommitted
mm/hugetlb: fix calculation of adjust_range_if_pmd_sharing_possible
commit 75802ca upstream. This is found by code observation only. Firstly, the worst case scenario should assume the whole range was covered by pmd sharing. The old algorithm might not work as expected for ranges like (1g-2m, 1g+2m), where the adjusted range should be (0, 1g+2m) but the expected range should be (0, 2g). Since at it, remove the loop since it should not be required. With that, the new code should be faster too when the invalidating range is huge. Mike said: : With range (1g-2m, 1g+2m) within a vma (0, 2g) the existing code will only : adjust to (0, 1g+2m) which is incorrect. : : We should cc stable. The original reason for adjusting the range was to : prevent data corruption (getting wrong page). Since the range is not : always adjusted correctly, the potential for corruption still exists. : : However, I am fairly confident that adjust_range_if_pmd_sharing_possible : is only gong to be called in two cases: : : 1) for a single page : 2) for range == entire vma : : In those cases, the current code should produce the correct results. : : To be safe, let's just cc stable. Fixes: 017b166 ("mm: migration: fix migration of huge PMD shared pages") Signed-off-by: Peter Xu <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Reviewed-by: Mike Kravetz <[email protected]> Cc: Andrea Arcangeli <[email protected]> Cc: Matthew Wilcox <[email protected]> Cc: <[email protected]> Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Linus Torvalds <[email protected]> Signed-off-by: Mike Kravetz <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]>
1 parent dcb6e6e commit 734654a

File tree

1 file changed

+10
-14
lines changed

1 file changed

+10
-14
lines changed

mm/hugetlb.c

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -4650,25 +4650,21 @@ static bool vma_shareable(struct vm_area_struct *vma, unsigned long addr)
46504650
void adjust_range_if_pmd_sharing_possible(struct vm_area_struct *vma,
46514651
unsigned long *start, unsigned long *end)
46524652
{
4653-
unsigned long check_addr = *start;
4653+
unsigned long a_start, a_end;
46544654

46554655
if (!(vma->vm_flags & VM_MAYSHARE))
46564656
return;
46574657

4658-
for (check_addr = *start; check_addr < *end; check_addr += PUD_SIZE) {
4659-
unsigned long a_start = check_addr & PUD_MASK;
4660-
unsigned long a_end = a_start + PUD_SIZE;
4658+
/* Extend the range to be PUD aligned for a worst case scenario */
4659+
a_start = ALIGN_DOWN(*start, PUD_SIZE);
4660+
a_end = ALIGN(*end, PUD_SIZE);
46614661

4662-
/*
4663-
* If sharing is possible, adjust start/end if necessary.
4664-
*/
4665-
if (range_in_vma(vma, a_start, a_end)) {
4666-
if (a_start < *start)
4667-
*start = a_start;
4668-
if (a_end > *end)
4669-
*end = a_end;
4670-
}
4671-
}
4662+
/*
4663+
* Intersect the range with the vma range, since pmd sharing won't be
4664+
* across vma after all
4665+
*/
4666+
*start = max(vma->vm_start, a_start);
4667+
*end = min(vma->vm_end, a_end);
46724668
}
46734669

46744670
/*

0 commit comments

Comments
 (0)