Commit 836d5ffd34550901ea024347693e689273ded8aa
Committed by
Linus Torvalds
1 parent
53e9a6159f
Exists in
master
and in
20 other branches
[PATCH] mm: fix madvise vma merging
Better late than never, I've at last reviewed the madvise vma merging going into 2.6.13. Remove a pointless check and fix two little bugs - a simple test (with /proc/<pid>/maps hacked to show ReadHints) showed both mismerges in practice: though being madvise, neither was disastrous. 1. Correct placement of the success label in madvise_behavior: as in mprotect_fixup and mlock_fixup, it is necessary to update vm_flags when vma_merge succeeds (to handle the exceptional Case 8 noted in the comments above vma_merge itself). 2. Correct initial value of prev when starting part way into a vma: as in sys_mprotect and do_mlock, it needs to be set to vma in this case (vma_merge handles only that minimum of cases shown in its comments). 3. If find_vma_prev sets prev, then the vma it returns is prev->vm_next, so it's pointless to make that same assignment again in sys_madvise. Signed-off-by: Hugh Dickins <hugh@veritas.com> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Showing 1 changed file with 5 additions and 4 deletions Side-by-side Diff
mm/madvise.c
... | ... | @@ -37,7 +37,7 @@ |
37 | 37 | |
38 | 38 | if (new_flags == vma->vm_flags) { |
39 | 39 | *prev = vma; |
40 | - goto success; | |
40 | + goto out; | |
41 | 41 | } |
42 | 42 | |
43 | 43 | pgoff = vma->vm_pgoff + ((start - vma->vm_start) >> PAGE_SHIFT); |
... | ... | @@ -62,6 +62,7 @@ |
62 | 62 | goto out; |
63 | 63 | } |
64 | 64 | |
65 | +success: | |
65 | 66 | /* |
66 | 67 | * vm_flags is protected by the mmap_sem held in write mode. |
67 | 68 | */ |
... | ... | @@ -70,7 +71,6 @@ |
70 | 71 | out: |
71 | 72 | if (error == -ENOMEM) |
72 | 73 | error = -EAGAIN; |
73 | -success: | |
74 | 74 | return error; |
75 | 75 | } |
76 | 76 | |
... | ... | @@ -237,8 +237,9 @@ |
237 | 237 | * - different from the way of handling in mlock etc. |
238 | 238 | */ |
239 | 239 | vma = find_vma_prev(current->mm, start, &prev); |
240 | - if (!vma && prev) | |
241 | - vma = prev->vm_next; | |
240 | + if (vma && start > vma->vm_start) | |
241 | + prev = vma; | |
242 | + | |
242 | 243 | for (;;) { |
243 | 244 | /* Still start < end. */ |
244 | 245 | error = -ENOMEM; |