The commit is pushed to "branch-rh7-3.10.0-229.7.2.vz7.9.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git after rh7-3.10.0-229.7.2.vz7.9.15 ------> commit b653eb7dd123fb0315efc08808128bc1b6fa7b93 Author: Vladimir Davydov <vdavy...@virtuozzo.com> Date: Tue Dec 8 18:15:56 2015 +0400
mm: page_idle: look up page anon_vma carefully when checking references Patchset description: rmap_walk() present in RH7 requires the caller to either hold mmap_sem or pin the page's anon_vma. page_idle_clear_pte_refs does neither. As a result, it might end up trying to lock/unlock anon_vma which has already been freed and possibly reallocated. This won't do any good. Let's pull the new version of rmap_walk() from upstream, which allows to specify a custom anon_vma lock function and use it in page_idle code to avoid this issue. This patch puts page_idle in sync with upstream. I hope this will fix: https://jira.sw.ru/browse/PSBM-42015 Joonsoo Kim (3): mm/rmap: factor lock function out of rmap_walk_anon() mm/rmap: make rmap_walk to get the rmap_walk_control argument mm/rmap: extend rmap_walk_xxx() to cope with different cases Vladimir Davydov (1): mm: page_idle: look up page anon_vma carefully when checking references ============================ This patch description: Since we don't hold mmap_sem when checking references, we can't just read anon_vma from page->mapping and call down_read on its rwsem, becuase the page can be unmapped in the meantime and the anon_vma can be freed so that we will end up messing with already freed and perhaps reallocated anon_vma. This can result in memory corruptions and dead locks. To fix this issue, this patch makes use of the rmap_walk infrastructure pulled by previous patches, which allows to use page_lock_anon_vma_read for locking page anon_vma. This function handles the race described above carefully, so make page_idle_clear_pte_refs use it, as it is done upstream. https://jira.sw.ru/browse/PSBM-42015 Fixes: 577afeb24634 ("ms/mm: introduce idle page tracking") Signed-off-by: Vladimir Davydov <vdavy...@virtuozzo.com> --- mm/page_idle.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/mm/page_idle.c b/mm/page_idle.c index c09a5a2..6470ba0 100644 --- a/mm/page_idle.c +++ b/mm/page_idle.c @@ -88,15 +88,28 @@ static int page_idle_clear_pte_refs_one(struct page *page, static void page_idle_clear_pte_refs(struct page *page) { + /* + * Since rwc.arg is unused, rwc is effectively immutable, so we + * can make it static const to save some cycles and stack. + */ + static const struct rmap_walk_control rwc = { + .rmap_one = page_idle_clear_pte_refs_one, + .anon_lock = page_lock_anon_vma_read, + }; + bool need_lock; + if (!page_mapped(page) || !page_rmapping(page)) return; - if (!trylock_page(page)) + need_lock = !PageAnon(page) || PageKsm(page); + if (need_lock && !trylock_page(page)) return; - rmap_walk(page, page_idle_clear_pte_refs_one, NULL); - unlock_page(page); + rmap_walk(page, (struct rmap_walk_control *)&rwc); + + if (need_lock) + unlock_page(page); } static ssize_t page_idle_bitmap_read(struct file *file, struct kobject *kobj, _______________________________________________ Devel mailing list Devel@openvz.org https://lists.openvz.org/mailman/listinfo/devel