xen/xenpaging.error-handling.patch

190 lines
5.9 KiB
Diff

# HG changeset patch
# Parent 5a299906312e606553e6dd2acbe44ab692722a75
xenpaging: improve evict error handling
Adjust return codes in Xen and handle errors in evict_victim() properly.
p2m_mem_paging_nominate() returns -EAGAIN, p2m_mem_paging_evict()
returns -EBUSY. Other errors indicate guest failures, which
xenpaging_evict_page() can now catch correctly. Also write() failures
are fatal.
Without this change, evict_victim() may spin forever if the guest is
killed because this function does not get a signal.
Signed-off-by: Olaf Hering <olaf@aepfle.de>
---
tools/xenpaging/xenpaging.c | 47 ++++++++++++++++++++++++++---------------
xen/arch/x86/mm/p2m.c | 7 +-----
xen/include/public/mem_event.h | 2 -
3 files changed, 33 insertions(+), 23 deletions(-)
Index: xen-4.1.2-testing/tools/xenpaging/xenpaging.c
===================================================================
--- xen-4.1.2-testing.orig/tools/xenpaging/xenpaging.c
+++ xen-4.1.2-testing/tools/xenpaging/xenpaging.c
@@ -569,29 +569,35 @@ static int xenpaging_evict_page(xenpagin
xc_interface *xch = paging->xc_handle;
void *page;
unsigned long gfn;
- int ret;
+ int ret = -1;
DECLARE_DOMCTL;
/* Map page to get a handle */
gfn = victim->gfn;
- ret = -EFAULT;
page = xc_map_foreign_pages(xch, paging->mem_event.domain_id,
PROT_READ | PROT_WRITE, &gfn, 1);
if ( page == NULL )
{
- PERROR("Error mapping page %lx", victim->gfn);
+ if ( errno == EINVAL )
+ ret = 1;
+ else
+ PERROR("Error mapping page %lx", victim->gfn);
goto out;
}
/* Nominate the page */
- ret = xc_mem_paging_nominate(xch, paging->mem_event.domain_id, gfn);
- if ( ret != 0 )
+ if ( xc_mem_paging_nominate(xch, paging->mem_event.domain_id, gfn) )
+ {
+ if ( errno == EAGAIN )
+ ret = 1;
+ else
+ PERROR("Error nominating page %lx", victim->gfn);
goto out;
+ }
/* Copy page */
- ret = write_page(fd, page, i);
- if ( ret != 0 )
+ if ( write_page(fd, page, i) )
{
PERROR("Error copying page %lx", victim->gfn);
goto out;
@@ -601,10 +607,10 @@ static int xenpaging_evict_page(xenpagin
page = NULL;
/* Tell Xen to evict page */
- ret = xc_mem_paging_evict(xch, paging->mem_event.domain_id,
- victim->gfn);
- if ( ret != 0 )
+ if ( xc_mem_paging_evict(xch, paging->mem_event.domain_id, victim->gfn) )
{
+ if ( errno == EBUSY )
+ ret = 1;
PERROR("Error evicting page %lx", victim->gfn);
goto out;
}
@@ -616,6 +622,8 @@ static int xenpaging_evict_page(xenpagin
/* Record number of evicted pages */
paging->num_paged_out++;
+ ret = 0;
+
out:
if (page)
munmap(page, PAGE_SIZE);
@@ -724,7 +732,7 @@ static int evict_victim(xenpaging_t *pag
xenpaging_victim_t *victim, int fd, int i)
{
xc_interface *xch = paging->xc_handle;
- int j = 0;
+ static int num_paged_out;
int ret;
do
@@ -732,9 +740,13 @@ static int evict_victim(xenpaging_t *pag
ret = policy_choose_victim(paging, victim);
if ( ret != 0 )
{
- if ( ret != -ENOSPC )
- ERROR("Error choosing victim");
- goto out;
+ if ( num_paged_out != paging->num_paged_out ) {
+ DPRINTF("Flushing qemu cache\n");
+ xenpaging_mem_paging_flush_ioemu_cache(paging);
+ num_paged_out = paging->num_paged_out;
+ }
+ ret = -ENOSPC;
+ goto out;
}
if ( interrupted )
@@ -742,11 +754,12 @@ static int evict_victim(xenpaging_t *pag
ret = -EINTR;
goto out;
}
+
ret = xenpaging_evict_page(paging, victim, fd, i);
- if ( ret && j++ % 1000 == 0 )
+ if ( ret < 0 )
{
- if ( xenpaging_mem_paging_flush_ioemu_cache(paging) )
- PERROR("Error flushing ioemu cache");
+ ret = -EINTR;
+ goto out;
}
}
while ( ret );
Index: xen-4.1.2-testing/xen/arch/x86/mm/p2m.c
===================================================================
--- xen-4.1.2-testing.orig/xen/arch/x86/mm/p2m.c
+++ xen-4.1.2-testing/xen/arch/x86/mm/p2m.c
@@ -2863,19 +2863,17 @@ int p2m_mem_paging_nominate(struct p2m_d
p2m_type_t p2mt;
p2m_access_t a;
mfn_t mfn;
- int ret;
+ int ret = -EAGAIN;
p2m_lock(p2m);
mfn = p2m->get_entry(p2m, gfn, &p2mt, &a, p2m_query);
/* Check if mfn is valid */
- ret = -EINVAL;
if ( !mfn_valid(mfn) )
goto out;
/* Check p2m type */
- ret = -EAGAIN;
if ( !p2m_is_pageable(p2mt) )
goto out;
@@ -2928,7 +2926,7 @@ int p2m_mem_paging_evict(struct p2m_doma
p2m_access_t a;
mfn_t mfn;
struct domain *d = p2m->domain;
- int ret = -EINVAL;
+ int ret = -EBUSY;
p2m_lock(p2m);
@@ -2941,7 +2939,6 @@ int p2m_mem_paging_evict(struct p2m_doma
if ( p2mt != p2m_ram_paging_out )
goto out;
- ret = -EBUSY;
/* Get the page so it doesn't get modified under Xen's feet */
page = mfn_to_page(mfn);
if ( unlikely(!get_page(page, d)) )
Index: xen-4.1.2-testing/xen/include/public/mem_event.h
===================================================================
--- xen-4.1.2-testing.orig/xen/include/public/mem_event.h
+++ xen-4.1.2-testing/xen/include/public/mem_event.h
@@ -49,7 +49,7 @@
#define MEM_EVENT_REASON_INT3 5 /* int3 was hit: gla/gfn are RIP */
#define MEM_EVENT_REASON_SINGLESTEP 6 /* single step was invoked: gla/gfn are RIP */
-#define MEM_EVENT_PAGING_AGE 2UL /* Number distinguish the mem_paging <-> pager interface */
+#define MEM_EVENT_PAGING_AGE 3UL /* Number distinguish the mem_paging <-> pager interface */
typedef struct mem_event_shared_page {
uint32_t port;