Skip to content

Commit 75802ca

Browse files
xzpetertorvalds
authored andcommitted
mm/hugetlb: fix calculation of adjust_range_if_pmd_sharing_possible
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]>
1 parent 42742d9 commit 75802ca

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
@@ -5314,25 +5314,21 @@ static bool vma_shareable(struct vm_area_struct *vma, unsigned long addr)
53145314
void adjust_range_if_pmd_sharing_possible(struct vm_area_struct *vma,
53155315
unsigned long *start, unsigned long *end)
53165316
{
5317-
unsigned long check_addr;
5317+
unsigned long a_start, a_end;
53185318

53195319
if (!(vma->vm_flags & VM_MAYSHARE))
53205320
return;
53215321

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

5326-
/*
5327-
* If sharing is possible, adjust start/end if necessary.
5328-
*/
5329-
if (range_in_vma(vma, a_start, a_end)) {
5330-
if (a_start < *start)
5331-
*start = a_start;
5332-
if (a_end > *end)
5333-
*end = a_end;
5334-
}
5335-
}
5326+
/*
5327+
* Intersect the range with the vma range, since pmd sharing won't be
5328+
* across vma after all
5329+
*/
5330+
*start = max(vma->vm_start, a_start);
5331+
*end = min(vma->vm_end, a_end);
53365332
}
53375333

53385334
/*

0 commit comments

Comments
 (0)