Commit 3964acd0dbec123aa0a621973a2a0580034b4788
Committed by
Linus Torvalds
1 parent
36f571e9ed
Exists in
master
and in
20 other branches
mm: mempolicy: fix mbind_range() && vma_adjust() interaction
vma_adjust() does vma_set_policy(vma, vma_policy(next)) and this is doubly wrong: 1. This leaks vma->vm_policy if it is not NULL and not equal to next->vm_policy. This can happen if vma_merge() expands "area", not prev (case 8). 2. This sets the wrong policy if vma_merge() joins prev and area, area is the vma the caller needs to update and it still has the old policy. Revert commit 1444f92c8498 ("mm: merging memory blocks resets mempolicy") which introduced these problems. Change mbind_range() to recheck mpol_equal() after vma_merge() to fix the problem that commit tried to address. Signed-off-by: Oleg Nesterov <oleg@redhat.com> Acked-by: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Cc: Steven T Hampson <steven.t.hampson@intel.com> Cc: Mel Gorman <mgorman@suse.de> Cc: KOSAKI Motohiro <kosaki.motohiro@jp.fujitsu.com> Cc: Rik van Riel <riel@redhat.com> Cc: Andi Kleen <andi@firstfloor.org> Cc: <stable@vger.kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Showing 2 changed files with 6 additions and 2 deletions Side-by-side Diff
mm/mempolicy.c
... | ... | @@ -732,7 +732,10 @@ |
732 | 732 | if (prev) { |
733 | 733 | vma = prev; |
734 | 734 | next = vma->vm_next; |
735 | - continue; | |
735 | + if (mpol_equal(vma_policy(vma), new_pol)) | |
736 | + continue; | |
737 | + /* vma_merge() joined vma && vma->next, case 8 */ | |
738 | + goto replace; | |
736 | 739 | } |
737 | 740 | if (vma->vm_start != vmstart) { |
738 | 741 | err = split_vma(vma->vm_mm, vma, vmstart, 1); |
... | ... | @@ -744,6 +747,7 @@ |
744 | 747 | if (err) |
745 | 748 | goto out; |
746 | 749 | } |
750 | + replace: | |
747 | 751 | err = vma_replace_policy(vma, new_pol); |
748 | 752 | if (err) |
749 | 753 | goto out; |
mm/mmap.c
... | ... | @@ -865,7 +865,7 @@ |
865 | 865 | if (next->anon_vma) |
866 | 866 | anon_vma_merge(vma, next); |
867 | 867 | mm->map_count--; |
868 | - vma_set_policy(vma, vma_policy(next)); | |
868 | + mpol_put(vma_policy(next)); | |
869 | 869 | kmem_cache_free(vm_area_cachep, next); |
870 | 870 | /* |
871 | 871 | * In mprotect's case 6 (see comments on vma_merge), |