diff options
Diffstat (limited to 'mm/madvise.c')
-rw-r--r-- | mm/madvise.c | 53 |
1 files changed, 27 insertions, 26 deletions
diff --git a/mm/madvise.c b/mm/madvise.c index 76eb4193acdd..d9ae2067952e 100644 --- a/mm/madvise.c +++ b/mm/madvise.c | |||
@@ -11,6 +11,7 @@ | |||
11 | #include <linux/mempolicy.h> | 11 | #include <linux/mempolicy.h> |
12 | #include <linux/hugetlb.h> | 12 | #include <linux/hugetlb.h> |
13 | #include <linux/sched.h> | 13 | #include <linux/sched.h> |
14 | #include <linux/ksm.h> | ||
14 | 15 | ||
15 | /* | 16 | /* |
16 | * Any behaviour which results in changes to the vma->vm_flags needs to | 17 | * Any behaviour which results in changes to the vma->vm_flags needs to |
@@ -41,7 +42,7 @@ static long madvise_behavior(struct vm_area_struct * vma, | |||
41 | struct mm_struct * mm = vma->vm_mm; | 42 | struct mm_struct * mm = vma->vm_mm; |
42 | int error = 0; | 43 | int error = 0; |
43 | pgoff_t pgoff; | 44 | pgoff_t pgoff; |
44 | int new_flags = vma->vm_flags; | 45 | unsigned long new_flags = vma->vm_flags; |
45 | 46 | ||
46 | switch (behavior) { | 47 | switch (behavior) { |
47 | case MADV_NORMAL: | 48 | case MADV_NORMAL: |
@@ -57,8 +58,18 @@ static long madvise_behavior(struct vm_area_struct * vma, | |||
57 | new_flags |= VM_DONTCOPY; | 58 | new_flags |= VM_DONTCOPY; |
58 | break; | 59 | break; |
59 | case MADV_DOFORK: | 60 | case MADV_DOFORK: |
61 | if (vma->vm_flags & VM_IO) { | ||
62 | error = -EINVAL; | ||
63 | goto out; | ||
64 | } | ||
60 | new_flags &= ~VM_DONTCOPY; | 65 | new_flags &= ~VM_DONTCOPY; |
61 | break; | 66 | break; |
67 | case MADV_MERGEABLE: | ||
68 | case MADV_UNMERGEABLE: | ||
69 | error = ksm_madvise(vma, start, end, behavior, &new_flags); | ||
70 | if (error) | ||
71 | goto out; | ||
72 | break; | ||
62 | } | 73 | } |
63 | 74 | ||
64 | if (new_flags == vma->vm_flags) { | 75 | if (new_flags == vma->vm_flags) { |
@@ -211,37 +222,16 @@ static long | |||
211 | madvise_vma(struct vm_area_struct *vma, struct vm_area_struct **prev, | 222 | madvise_vma(struct vm_area_struct *vma, struct vm_area_struct **prev, |
212 | unsigned long start, unsigned long end, int behavior) | 223 | unsigned long start, unsigned long end, int behavior) |
213 | { | 224 | { |
214 | long error; | ||
215 | |||
216 | switch (behavior) { | 225 | switch (behavior) { |
217 | case MADV_DOFORK: | ||
218 | if (vma->vm_flags & VM_IO) { | ||
219 | error = -EINVAL; | ||
220 | break; | ||
221 | } | ||
222 | case MADV_DONTFORK: | ||
223 | case MADV_NORMAL: | ||
224 | case MADV_SEQUENTIAL: | ||
225 | case MADV_RANDOM: | ||
226 | error = madvise_behavior(vma, prev, start, end, behavior); | ||
227 | break; | ||
228 | case MADV_REMOVE: | 226 | case MADV_REMOVE: |
229 | error = madvise_remove(vma, prev, start, end); | 227 | return madvise_remove(vma, prev, start, end); |
230 | break; | ||
231 | |||
232 | case MADV_WILLNEED: | 228 | case MADV_WILLNEED: |
233 | error = madvise_willneed(vma, prev, start, end); | 229 | return madvise_willneed(vma, prev, start, end); |
234 | break; | ||
235 | |||
236 | case MADV_DONTNEED: | 230 | case MADV_DONTNEED: |
237 | error = madvise_dontneed(vma, prev, start, end); | 231 | return madvise_dontneed(vma, prev, start, end); |
238 | break; | ||
239 | |||
240 | default: | 232 | default: |
241 | BUG(); | 233 | return madvise_behavior(vma, prev, start, end, behavior); |
242 | break; | ||
243 | } | 234 | } |
244 | return error; | ||
245 | } | 235 | } |
246 | 236 | ||
247 | static int | 237 | static int |
@@ -256,12 +246,17 @@ madvise_behavior_valid(int behavior) | |||
256 | case MADV_REMOVE: | 246 | case MADV_REMOVE: |
257 | case MADV_WILLNEED: | 247 | case MADV_WILLNEED: |
258 | case MADV_DONTNEED: | 248 | case MADV_DONTNEED: |
249 | #ifdef CONFIG_KSM | ||
250 | case MADV_MERGEABLE: | ||
251 | case MADV_UNMERGEABLE: | ||
252 | #endif | ||
259 | return 1; | 253 | return 1; |
260 | 254 | ||
261 | default: | 255 | default: |
262 | return 0; | 256 | return 0; |
263 | } | 257 | } |
264 | } | 258 | } |
259 | |||
265 | /* | 260 | /* |
266 | * The madvise(2) system call. | 261 | * The madvise(2) system call. |
267 | * | 262 | * |
@@ -286,6 +281,12 @@ madvise_behavior_valid(int behavior) | |||
286 | * so the kernel can free resources associated with it. | 281 | * so the kernel can free resources associated with it. |
287 | * MADV_REMOVE - the application wants to free up the given range of | 282 | * MADV_REMOVE - the application wants to free up the given range of |
288 | * pages and associated backing store. | 283 | * pages and associated backing store. |
284 | * MADV_DONTFORK - omit this area from child's address space when forking: | ||
285 | * typically, to avoid COWing pages pinned by get_user_pages(). | ||
286 | * MADV_DOFORK - cancel MADV_DONTFORK: no longer omit this area when forking. | ||
287 | * MADV_MERGEABLE - the application recommends that KSM try to merge pages in | ||
288 | * this area with pages of identical content from other such areas. | ||
289 | * MADV_UNMERGEABLE- cancel MADV_MERGEABLE: no longer merge pages with others. | ||
289 | * | 290 | * |
290 | * return values: | 291 | * return values: |
291 | * zero - success | 292 | * zero - success |