diff options
Diffstat (limited to 'mm/mempolicy.c')
-rw-r--r-- | mm/mempolicy.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/mm/mempolicy.c b/mm/mempolicy.c index adc395481813..c3fdbcb17658 100644 --- a/mm/mempolicy.c +++ b/mm/mempolicy.c | |||
@@ -636,6 +636,7 @@ static int mbind_range(struct mm_struct *mm, unsigned long start, | |||
636 | struct vm_area_struct *prev; | 636 | struct vm_area_struct *prev; |
637 | struct vm_area_struct *vma; | 637 | struct vm_area_struct *vma; |
638 | int err = 0; | 638 | int err = 0; |
639 | pgoff_t pgoff; | ||
639 | unsigned long vmstart; | 640 | unsigned long vmstart; |
640 | unsigned long vmend; | 641 | unsigned long vmend; |
641 | 642 | ||
@@ -643,13 +644,21 @@ static int mbind_range(struct mm_struct *mm, unsigned long start, | |||
643 | if (!vma || vma->vm_start > start) | 644 | if (!vma || vma->vm_start > start) |
644 | return -EFAULT; | 645 | return -EFAULT; |
645 | 646 | ||
647 | if (start > vma->vm_start) | ||
648 | prev = vma; | ||
649 | |||
646 | for (; vma && vma->vm_start < end; prev = vma, vma = next) { | 650 | for (; vma && vma->vm_start < end; prev = vma, vma = next) { |
647 | next = vma->vm_next; | 651 | next = vma->vm_next; |
648 | vmstart = max(start, vma->vm_start); | 652 | vmstart = max(start, vma->vm_start); |
649 | vmend = min(end, vma->vm_end); | 653 | vmend = min(end, vma->vm_end); |
650 | 654 | ||
655 | if (mpol_equal(vma_policy(vma), new_pol)) | ||
656 | continue; | ||
657 | |||
658 | pgoff = vma->vm_pgoff + | ||
659 | ((vmstart - vma->vm_start) >> PAGE_SHIFT); | ||
651 | prev = vma_merge(mm, prev, vmstart, vmend, vma->vm_flags, | 660 | prev = vma_merge(mm, prev, vmstart, vmend, vma->vm_flags, |
652 | vma->anon_vma, vma->vm_file, vma->vm_pgoff, | 661 | vma->anon_vma, vma->vm_file, pgoff, |
653 | new_pol); | 662 | new_pol); |
654 | if (prev) { | 663 | if (prev) { |
655 | vma = prev; | 664 | vma = prev; |