Commit e8788c0cce63e0cc8689a123d1ce0af1e28cd583
Committed by
Linus Torvalds
1 parent
6af6aab34a
Exists in
master
and in
4 other branches
[PATCH] remove_from_swap: fix locking
remove_from_swap() currently attempts to use page_lock_anon_vma to obtain an anon_vma lock. That is not working since the page may have been remapped via swap ptes in order to move the page. However, do_migrate_pages() obtain the mmap_sem lock and therefore there is a guarantee that the anonymous vma will not vanish from under us. There is therefore no need to use page_lock_anon_vma. Signed-off-by: Christoph Lameter <clameter@sgi.com> Acked-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 13 additions and 5 deletions Side-by-side Diff
mm/rmap.c
... | ... | @@ -212,25 +212,33 @@ |
212 | 212 | * through real pte's pointing to valid pages and then releasing |
213 | 213 | * the page from the swap cache. |
214 | 214 | * |
215 | - * Must hold page lock on page. | |
215 | + * Must hold page lock on page and mmap_sem of one vma that contains | |
216 | + * the page. | |
216 | 217 | */ |
217 | 218 | void remove_from_swap(struct page *page) |
218 | 219 | { |
219 | 220 | struct anon_vma *anon_vma; |
220 | 221 | struct vm_area_struct *vma; |
222 | + unsigned long mapping; | |
221 | 223 | |
222 | - if (!PageAnon(page) || !PageSwapCache(page)) | |
224 | + if (!PageSwapCache(page)) | |
223 | 225 | return; |
224 | 226 | |
225 | - anon_vma = page_lock_anon_vma(page); | |
226 | - if (!anon_vma) | |
227 | + mapping = (unsigned long)page->mapping; | |
228 | + | |
229 | + if (!mapping || (mapping & PAGE_MAPPING_ANON) == 0) | |
227 | 230 | return; |
228 | 231 | |
232 | + /* | |
233 | + * We hold the mmap_sem lock. So no need to call page_lock_anon_vma. | |
234 | + */ | |
235 | + anon_vma = (struct anon_vma *) (mapping - PAGE_MAPPING_ANON); | |
236 | + spin_lock(&anon_vma->lock); | |
237 | + | |
229 | 238 | list_for_each_entry(vma, &anon_vma->head, anon_vma_node) |
230 | 239 | remove_vma_swap(vma, page); |
231 | 240 | |
232 | 241 | spin_unlock(&anon_vma->lock); |
233 | - | |
234 | 242 | delete_from_swap_cache(page); |
235 | 243 | } |
236 | 244 | EXPORT_SYMBOL(remove_from_swap); |