x86/mm: Fix more ballooning+paging and ballooning+sharing bugs
PATCH 1/1 x86/mm: Fix more ballooning+paging and ballooning+sharing bugs
xen/arch/x86/mm/p2m.c | 7 +++++-- xen/common/memory.c | 17 ++++++++++++++++- 2 files changed, 21 insertions(+), 3 deletions(-)
If the guest balloons away a page that has been nominated for paging but not yet paged out, we fix:
- Send EVICT_FAIL flag in the event to the pager
- Do not leak the underlying page
If the page was shared, we were not:
- properly refreshing the mfn to balloon after the unshare.
- unlocking the p2m on the error exit case
Signed-off-by Andres Lagar-Cavilla <[email protected]>
xen/arch/x86/mm/p2m.c +5 -2
@@ -927,11 +927,14 @@ void p2m_mem_paging_drop_page(struct dom req.gfn = gfn; req.flags =MEM_EVENT_FLAG_DROP_PAGE ; -mem_event_put_request (d, &d->mem_event->paging, &req); -/* Update stats unless the page hasn't yet been evicted */ if ( p2mt != p2m_ram_paging_out )atomic_dec (&d->paged_pages); +else +/* Evict will fail now, tag this request for pager */ + req.flags |=MEM_EVENT_FLAG_EVICT_FAIL ; + +mem_event_put_request (d, &d->mem_event->paging, &req); }/**
xen/common/memory.c +16 -1
@@ -167,6 +167,15 @@ int guest_remove_page(struct domain *d, {guest_physmap_remove_page (d, gmfn, mfn,0 );put_gfn (d, gmfn); +/* If the page hasn't yet been paged out, there is an +* actual page that needs to be released. */ +if ( p2mt == p2m_ram_paging_out ) + { +ASSERT (mfn_valid (mfn)); + page =mfn_to_page (mfn); +if (test_and_clear_bit (_PGC_allocated, &page->count_info) ) +put_page (page); + }p2m_mem_paging_drop_page (d, gmfn, p2mt);return 1 ; }
@@ -181,7 +190,6 @@ int guest_remove_page(struct domain *d,return 0 ; } - page =mfn_to_page (mfn);#ifdef CONFIG_X86_64 if (p2m_is_shared (p2mt) ) {
@@ -190,10 +198,17 @@ int guest_remove_page(struct domain *d,* need to trigger proper cleanup. Once done, this is * like any other page. */ if (mem_sharing_unshare_page (d, gmfn,0 ) ) + { +put_gfn (d, gmfn);return 0 ; + } +/* Maybe the mfn changed */ + mfn =mfn_x (get_gfn_query_unlocked (d, gmfn, &p2mt)); + ASSERT(!p2m_is_shared(p2mt)); }#endif /* CONFIG_X86_64 */ + page =mfn_to_page (mfn);if (unlikely (!get_page (page, d)) ) {put_gfn (d, gmfn);