forked from Minki/linux
mempolicy: mbind_range() set_policy() after vma_merge()
v2.6.34 commit9d8cebd4bc
("mm: fix mbind vma merge problem") introduced vma_merge() to mbind_range(); but unlike madvise, mlock and mprotect, it put a "continue" to next vma where its precedents go to update flags on current vma before advancing: that left vma with the wrong setting in the infamous vma_merge() case 8. v3.10 commit1444f92c84
("mm: merging memory blocks resets mempolicy") tried to fix that in vma_adjust(), without fully understanding the issue. v3.11 commit3964acd0db
("mm: mempolicy: fix mbind_range() && vma_adjust() interaction") reverted that, and went about the fix in the right way, but chose to optimize out an unnecessary mpol_dup() with a prior mpol_equal() test. But on tmpfs, that also pessimized out the vital call to its ->set_policy(), leaving the new mbind unenforced. The user visible effect was that the pages got allocated on the local node (happened to be 0), after the mbind() caller had specifically asked for them to be allocated on node 1. There was not any page migration involved in the case reported: the pages simply got allocated on the wrong node. Just delete that optimization now (though it could be made conditional on vma not having a set_policy). Also remove the "next" variable: it turned out to be blameless, but also pointless. Link: https://lkml.kernel.org/r/319e4db9-64ae-4bca-92f0-ade85d342ff@google.com Fixes:3964acd0db
("mm: mempolicy: fix mbind_range() && vma_adjust() interaction") Signed-off-by: Hugh Dickins <hughd@google.com> Acked-by: Oleg Nesterov <oleg@redhat.com> Reviewed-by: Liam R. Howlett <Liam.Howlett@oracle.com> Cc: Vlastimil Babka <vbabka@suse.cz> Cc: <stable@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
abd4349ff9
commit
4e0906008c
@ -786,7 +786,6 @@ static int vma_replace_policy(struct vm_area_struct *vma,
|
||||
static int mbind_range(struct mm_struct *mm, unsigned long start,
|
||||
unsigned long end, struct mempolicy *new_pol)
|
||||
{
|
||||
struct vm_area_struct *next;
|
||||
struct vm_area_struct *prev;
|
||||
struct vm_area_struct *vma;
|
||||
int err = 0;
|
||||
@ -801,8 +800,7 @@ static int mbind_range(struct mm_struct *mm, unsigned long start,
|
||||
if (start > vma->vm_start)
|
||||
prev = vma;
|
||||
|
||||
for (; vma && vma->vm_start < end; prev = vma, vma = next) {
|
||||
next = vma->vm_next;
|
||||
for (; vma && vma->vm_start < end; prev = vma, vma = vma->vm_next) {
|
||||
vmstart = max(start, vma->vm_start);
|
||||
vmend = min(end, vma->vm_end);
|
||||
|
||||
@ -817,10 +815,6 @@ static int mbind_range(struct mm_struct *mm, unsigned long start,
|
||||
anon_vma_name(vma));
|
||||
if (prev) {
|
||||
vma = prev;
|
||||
next = vma->vm_next;
|
||||
if (mpol_equal(vma_policy(vma), new_pol))
|
||||
continue;
|
||||
/* vma_merge() joined vma && vma->next, case 8 */
|
||||
goto replace;
|
||||
}
|
||||
if (vma->vm_start != vmstart) {
|
||||
|
Loading…
Reference in New Issue
Block a user