2012-01-05 20:41:54 +01:00
|
|
|
# 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(-)
|
|
|
|
|
2012-02-08 23:29:38 +01:00
|
|
|
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
|
2012-01-05 20:41:54 +01:00
|
|
|
@@ -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;
|
2012-02-08 23:29:38 +01:00
|
|
|
+ static int num_paged_out;
|
2012-01-05 20:41:54 +01:00
|
|
|
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;
|
2012-02-08 23:29:38 +01:00
|
|
|
+ if ( num_paged_out != paging->num_paged_out ) {
|
2012-01-05 20:41:54 +01:00
|
|
|
+ DPRINTF("Flushing qemu cache\n");
|
|
|
|
+ xenpaging_mem_paging_flush_ioemu_cache(paging);
|
2012-02-08 23:29:38 +01:00
|
|
|
+ num_paged_out = paging->num_paged_out;
|
2012-01-05 20:41:54 +01:00
|
|
|
+ }
|
2012-02-08 23:29:38 +01:00
|
|
|
+ ret = -ENOSPC;
|
2012-01-05 20:41:54 +01:00
|
|
|
+ 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 );
|
2012-02-08 23:29:38 +01:00
|
|
|
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
|
2012-01-05 20:41:54 +01:00
|
|
|
@@ -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)) )
|
2012-02-08 23:29:38 +01:00
|
|
|
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
|
2012-01-05 20:41:54 +01:00
|
|
|
@@ -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;
|