diff options
author | James Morris <jmorris@namei.org> | 2009-09-29 17:47:33 -0400 |
---|---|---|
committer | James Morris <jmorris@namei.org> | 2009-09-29 17:47:33 -0400 |
commit | 1669b049db50fc7f1d4e694fb115a0f408c63fce (patch) | |
tree | 9b3b90b5cbff9b8f30ecf0b2a44896ce8bef0c20 /mm/mremap.c | |
parent | 7f366784f5c2b8fc0658b5b374f4c63ee42c789f (diff) | |
parent | 17d857be649a21ca90008c6dc425d849fa83db5c (diff) |
Merge branch 'master' into next
Diffstat (limited to 'mm/mremap.c')
-rw-r--r-- | mm/mremap.c | 18 |
1 files changed, 16 insertions, 2 deletions
diff --git a/mm/mremap.c b/mm/mremap.c index a39b7b91be46..97bff2547719 100644 --- a/mm/mremap.c +++ b/mm/mremap.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/hugetlb.h> | 11 | #include <linux/hugetlb.h> |
12 | #include <linux/slab.h> | 12 | #include <linux/slab.h> |
13 | #include <linux/shm.h> | 13 | #include <linux/shm.h> |
14 | #include <linux/ksm.h> | ||
14 | #include <linux/mman.h> | 15 | #include <linux/mman.h> |
15 | #include <linux/swap.h> | 16 | #include <linux/swap.h> |
16 | #include <linux/capability.h> | 17 | #include <linux/capability.h> |
@@ -85,8 +86,8 @@ static void move_ptes(struct vm_area_struct *vma, pmd_t *old_pmd, | |||
85 | if (vma->vm_file) { | 86 | if (vma->vm_file) { |
86 | /* | 87 | /* |
87 | * Subtle point from Rajesh Venkatasubramanian: before | 88 | * Subtle point from Rajesh Venkatasubramanian: before |
88 | * moving file-based ptes, we must lock vmtruncate out, | 89 | * moving file-based ptes, we must lock truncate_pagecache |
89 | * since it might clean the dst vma before the src vma, | 90 | * out, since it might clean the dst vma before the src vma, |
90 | * and we propagate stale pages into the dst afterward. | 91 | * and we propagate stale pages into the dst afterward. |
91 | */ | 92 | */ |
92 | mapping = vma->vm_file->f_mapping; | 93 | mapping = vma->vm_file->f_mapping; |
@@ -174,6 +175,7 @@ static unsigned long move_vma(struct vm_area_struct *vma, | |||
174 | unsigned long excess = 0; | 175 | unsigned long excess = 0; |
175 | unsigned long hiwater_vm; | 176 | unsigned long hiwater_vm; |
176 | int split = 0; | 177 | int split = 0; |
178 | int err; | ||
177 | 179 | ||
178 | /* | 180 | /* |
179 | * We'd prefer to avoid failure later on in do_munmap: | 181 | * We'd prefer to avoid failure later on in do_munmap: |
@@ -182,6 +184,18 @@ static unsigned long move_vma(struct vm_area_struct *vma, | |||
182 | if (mm->map_count >= sysctl_max_map_count - 3) | 184 | if (mm->map_count >= sysctl_max_map_count - 3) |
183 | return -ENOMEM; | 185 | return -ENOMEM; |
184 | 186 | ||
187 | /* | ||
188 | * Advise KSM to break any KSM pages in the area to be moved: | ||
189 | * it would be confusing if they were to turn up at the new | ||
190 | * location, where they happen to coincide with different KSM | ||
191 | * pages recently unmapped. But leave vma->vm_flags as it was, | ||
192 | * so KSM can come around to merge on vma and new_vma afterwards. | ||
193 | */ | ||
194 | err = ksm_madvise(vma, old_addr, old_addr + old_len, | ||
195 | MADV_UNMERGEABLE, &vm_flags); | ||
196 | if (err) | ||
197 | return err; | ||
198 | |||
185 | new_pgoff = vma->vm_pgoff + ((old_addr - vma->vm_start) >> PAGE_SHIFT); | 199 | new_pgoff = vma->vm_pgoff + ((old_addr - vma->vm_start) >> PAGE_SHIFT); |
186 | new_vma = copy_vma(&vma, new_addr, new_len, new_pgoff); | 200 | new_vma = copy_vma(&vma, new_addr, new_len, new_pgoff); |
187 | if (!new_vma) | 201 | if (!new_vma) |