* [PATCH 0 of 9] tools/xenpaging: cleanups and performance improvements
@ 2012-02-20 20:48 Olaf Hering
2012-02-20 20:48 ` [PATCH 1 of 9] xenpaging: use flat index for pagefile and page-in requests Olaf Hering
` (9 more replies)
0 siblings, 10 replies; 11+ messages in thread
From: Olaf Hering @ 2012-02-20 20:48 UTC (permalink / raw)
To: xen-devel
Series sent on 2012-01-31, now rebased to 24847:0900b1c905f1
This series adjusts the error reporting in the various code paths, with
the intention that fatal errors can be detected by callers and handled
properly. During my performance analysis with callgrind I found and
fixed a few bottlenecks in the page-in code paths.
Changes:
xenpaging: use flat index for pagefile and page-in requests
xenpaging: no poll timeout while page-out is in progress
xenpaging: reduce number of qemu cache flushes
xenpaging: move nominate+evict into single function
xenpaging: improve performance in policy_choose_victim
xenpaging: unify error handling
xenpaging: move pagefile filedescriptor into struct xenpaging
xenpaging: move page_buffer into struct xenpaging
xenpaging: implement stack of free slots in pagefile
tools/xenpaging/policy.h | 2
tools/xenpaging/policy_default.c | 63 ++++--
tools/xenpaging/xenpaging.c | 353 ++++++++++++++++++++++-----------------
tools/xenpaging/xenpaging.h | 16 -
4 files changed, 261 insertions(+), 173 deletions(-)
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 1 of 9] xenpaging: use flat index for pagefile and page-in requests
2012-02-20 20:48 [PATCH 0 of 9] tools/xenpaging: cleanups and performance improvements Olaf Hering
@ 2012-02-20 20:48 ` Olaf Hering
2012-02-20 20:48 ` [PATCH 2 of 9] xenpaging: no poll timeout while page-out is in progress Olaf Hering
` (8 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Olaf Hering @ 2012-02-20 20:48 UTC (permalink / raw)
To: xen-devel
# HG changeset patch
# User Olaf Hering <olaf@aepfle.de>
# Date 1329769124 -3600
# Node ID 4b2dbd2cb9977f357a5dd754c923ed14dda2ec51
# Parent 0900b1c905f1d038aad58a2732fe2bad682149a3
xenpaging: use flat index for pagefile and page-in requests
This change is based on an idea by <hongkaixing@huawei.com> and
<bicky.shi@huawei.com>.
Scanning the victims[] array is time consuming with a large number of
target pages. Replace the loop to find the slot in the pagefile which
holds the requested gfn with an index.
Remove the victims array and replace it with a flat array. This array
holds the gfn for a given slot in the pagefile. Adjust all users of the
victims array.
Rename variable in main() from i to slot to clearify the meaning.
Update xenpaging_evict_page() to pass a pointer to xen_pfn_t to
xc_map_foreign_pages().
Update policy_choose_victim() to return either a gfn or INVALID_MFN.
Signed-off-by: Olaf Hering <olaf@aepfle.de>
diff -r 0900b1c905f1 -r 4b2dbd2cb997 tools/xenpaging/policy.h
--- a/tools/xenpaging/policy.h
+++ b/tools/xenpaging/policy.h
@@ -29,7 +29,7 @@
int policy_init(struct xenpaging *paging);
-int policy_choose_victim(struct xenpaging *paging, struct victim *victim);
+unsigned long policy_choose_victim(struct xenpaging *paging);
void policy_notify_paged_out(unsigned long gfn);
void policy_notify_paged_in(unsigned long gfn);
void policy_notify_paged_in_nomru(unsigned long gfn);
diff -r 0900b1c905f1 -r 4b2dbd2cb997 tools/xenpaging/policy_default.c
--- a/tools/xenpaging/policy_default.c
+++ b/tools/xenpaging/policy_default.c
@@ -77,7 +77,7 @@ int policy_init(struct xenpaging *paging
return rc;
}
-int policy_choose_victim(struct xenpaging *paging, struct victim *victim)
+unsigned long policy_choose_victim(struct xenpaging *paging)
{
xc_interface *xch = paging->xc_handle;
unsigned long wrap = current_gfn;
@@ -102,16 +102,13 @@ int policy_choose_victim(struct xenpagin
/* One more round before returning ENOSPC */
continue;
}
- victim->gfn = INVALID_MFN;
- return -ENOSPC;
+ return INVALID_MFN;
}
}
while ( test_bit(current_gfn, bitmap) || test_bit(current_gfn, unconsumed) );
set_bit(current_gfn, unconsumed);
- victim->gfn = current_gfn;
-
- return 0;
+ return current_gfn;
}
void policy_notify_paged_out(unsigned long gfn)
diff -r 0900b1c905f1 -r 4b2dbd2cb997 tools/xenpaging/xenpaging.c
--- a/tools/xenpaging/xenpaging.c
+++ b/tools/xenpaging/xenpaging.c
@@ -430,6 +430,12 @@ static struct xenpaging *xenpaging_init(
}
DPRINTF("max_pages = %d\n", paging->max_pages);
+ /* Allocate indicies for pagefile slots */
+ paging->slot_to_gfn = calloc(paging->max_pages, sizeof(*paging->slot_to_gfn));
+ paging->gfn_to_slot = calloc(paging->max_pages, sizeof(*paging->gfn_to_slot));
+ if ( !paging->slot_to_gfn || !paging->gfn_to_slot )
+ goto err;
+
/* Initialise policy */
rc = policy_init(paging);
if ( rc != 0 )
@@ -468,6 +474,8 @@ static struct xenpaging *xenpaging_init(
free(dom_path);
free(watch_target_tot_pages);
+ free(paging->slot_to_gfn);
+ free(paging->gfn_to_slot);
free(paging->bitmap);
free(paging);
}
@@ -561,31 +569,29 @@ static void put_response(struct mem_even
RING_PUSH_RESPONSES(back_ring);
}
-static int xenpaging_evict_page(struct xenpaging *paging, struct victim *victim, int fd, int i)
+static int xenpaging_evict_page(struct xenpaging *paging, unsigned long gfn, int fd, int slot)
{
xc_interface *xch = paging->xc_handle;
void *page;
- unsigned long gfn;
+ xen_pfn_t victim = gfn;
int ret;
DECLARE_DOMCTL;
/* Map page */
- gfn = victim->gfn;
ret = -EFAULT;
- page = xc_map_foreign_pages(xch, paging->mem_event.domain_id,
- PROT_READ, &gfn, 1);
+ page = xc_map_foreign_pages(xch, paging->mem_event.domain_id, PROT_READ, &victim, 1);
if ( page == NULL )
{
- PERROR("Error mapping page %lx", victim->gfn);
+ PERROR("Error mapping page %lx", gfn);
goto out;
}
/* Copy page */
- ret = write_page(fd, page, i);
+ ret = write_page(fd, page, slot);
if ( ret != 0 )
{
- PERROR("Error copying page %lx", victim->gfn);
+ PERROR("Error copying page %lx", gfn);
munmap(page, PAGE_SIZE);
goto out;
}
@@ -593,17 +599,20 @@ static int xenpaging_evict_page(struct x
munmap(page, PAGE_SIZE);
/* Tell Xen to evict page */
- ret = xc_mem_paging_evict(xch, paging->mem_event.domain_id,
- victim->gfn);
+ ret = xc_mem_paging_evict(xch, paging->mem_event.domain_id, gfn);
if ( ret != 0 )
{
- PERROR("Error evicting page %lx", victim->gfn);
+ PERROR("Error evicting page %lx", gfn);
goto out;
}
- DPRINTF("evict_page > gfn %lx pageslot %d\n", victim->gfn, i);
+ DPRINTF("evict_page > gfn %lx pageslot %d\n", gfn, slot);
/* Notify policy of page being paged out */
- policy_notify_paged_out(victim->gfn);
+ policy_notify_paged_out(gfn);
+
+ /* Update index */
+ paging->slot_to_gfn[slot] = gfn;
+ paging->gfn_to_slot[gfn] = slot;
/* Record number of evicted pages */
paging->num_paged_out++;
@@ -710,19 +719,19 @@ static void resume_pages(struct xenpagin
page_in_trigger();
}
-static int evict_victim(struct xenpaging *paging, struct victim *victim, int fd, int i)
+static int evict_victim(struct xenpaging *paging, int fd, int slot)
{
xc_interface *xch = paging->xc_handle;
+ unsigned long gfn;
int j = 0;
int ret;
do
{
- ret = policy_choose_victim(paging, victim);
- if ( ret != 0 )
+ gfn = policy_choose_victim(paging);
+ if ( gfn == INVALID_MFN )
{
- if ( ret != -ENOSPC )
- ERROR("Error choosing victim");
+ ret = -ENOSPC;
goto out;
}
@@ -731,9 +740,9 @@ static int evict_victim(struct xenpaging
ret = -EINTR;
goto out;
}
- ret = xc_mem_paging_nominate(xch, paging->mem_event.domain_id, victim->gfn);
+ ret = xc_mem_paging_nominate(xch, paging->mem_event.domain_id, gfn);
if ( ret == 0 )
- ret = xenpaging_evict_page(paging, victim, fd, i);
+ ret = xenpaging_evict_page(paging, gfn, fd, slot);
else
{
if ( j++ % 1000 == 0 )
@@ -743,7 +752,7 @@ static int evict_victim(struct xenpaging
}
while ( ret );
- if ( test_and_set_bit(victim->gfn, paging->bitmap) )
+ if ( test_and_set_bit(gfn, paging->bitmap) )
ERROR("Page has been evicted before");
ret = 0;
@@ -753,7 +762,7 @@ static int evict_victim(struct xenpaging
}
/* Evict a batch of pages and write them to a free slot in the paging file */
-static int evict_pages(struct xenpaging *paging, int fd, struct victim *victims, int num_pages)
+static int evict_pages(struct xenpaging *paging, int fd, int num_pages)
{
xc_interface *xch = paging->xc_handle;
int rc, slot, num = 0;
@@ -761,10 +770,10 @@ static int evict_pages(struct xenpaging
for ( slot = 0; slot < paging->max_pages && num < num_pages; slot++ )
{
/* Slot is allocated */
- if ( victims[slot].gfn != INVALID_MFN )
+ if ( paging->slot_to_gfn[slot] )
continue;
- rc = evict_victim(paging, &victims[slot], fd, slot);
+ rc = evict_victim(paging, fd, slot);
if ( rc == -ENOSPC )
break;
if ( rc == -EINTR )
@@ -780,11 +789,10 @@ int main(int argc, char *argv[])
{
struct sigaction act;
struct xenpaging *paging;
- struct victim *victims;
mem_event_request_t req;
mem_event_response_t rsp;
int num, prev_num = 0;
- int i;
+ int slot;
int tot_pages;
int rc = -1;
int rc1;
@@ -813,15 +821,6 @@ int main(int argc, char *argv[])
return 2;
}
- /* Allocate upper limit of pages to allow growing and shrinking */
- victims = calloc(paging->max_pages, sizeof(struct victim));
- if ( !victims )
- goto out;
-
- /* Mark all slots as unallocated */
- for ( i = 0; i < paging->max_pages; i++ )
- victims[i].gfn = INVALID_MFN;
-
/* ensure that if we get a signal, we'll do cleanup, then exit */
act.sa_handler = close_handler;
act.sa_flags = 0;
@@ -853,32 +852,35 @@ int main(int argc, char *argv[])
{
get_request(&paging->mem_event, &req);
+ if ( req.gfn > paging->max_pages )
+ {
+ ERROR("Requested gfn %"PRIx64" higher than max_pages %lx\n", req.gfn, paging->max_pages);
+ goto out;
+ }
+
/* Check if the page has already been paged in */
if ( test_and_clear_bit(req.gfn, paging->bitmap) )
{
/* Find where in the paging file to read from */
- for ( i = 0; i < paging->max_pages; i++ )
+ slot = paging->gfn_to_slot[req.gfn];
+
+ /* Sanity check */
+ if ( paging->slot_to_gfn[slot] != req.gfn )
{
- if ( victims[i].gfn == req.gfn )
- break;
- }
-
- if ( i >= paging->max_pages )
- {
- DPRINTF("Couldn't find page %"PRIx64"\n", req.gfn);
+ ERROR("Expected gfn %"PRIx64" in slot %d, but found gfn %lx\n", req.gfn, slot, paging->slot_to_gfn[slot]);
goto out;
}
-
+
if ( req.flags & MEM_EVENT_FLAG_DROP_PAGE )
{
- DPRINTF("drop_page ^ gfn %"PRIx64" pageslot %d\n", req.gfn, i);
+ DPRINTF("drop_page ^ gfn %"PRIx64" pageslot %d\n", req.gfn, slot);
/* Notify policy of page being dropped */
policy_notify_dropped(req.gfn);
}
else
{
/* Populate the page */
- rc = xenpaging_populate_page(paging, req.gfn, fd, i);
+ rc = xenpaging_populate_page(paging, req.gfn, fd, slot);
if ( rc != 0 )
{
PERROR("Error populating page %"PRIx64"", req.gfn);
@@ -899,7 +901,7 @@ int main(int argc, char *argv[])
}
/* Clear this pagefile slot */
- victims[i].gfn = INVALID_MFN;
+ paging->slot_to_gfn[slot] = 0;
}
else
{
@@ -969,7 +971,7 @@ int main(int argc, char *argv[])
/* Limit the number of evicts to be able to process page-in requests */
if ( num > 42 )
num = 42;
- evict_pages(paging, fd, victims, num);
+ evict_pages(paging, fd, num);
}
/* Resume some pages if target not reached */
else if ( tot_pages < paging->target_tot_pages && paging->num_paged_out )
@@ -989,7 +991,6 @@ int main(int argc, char *argv[])
out:
close(fd);
unlink_pagefile();
- free(victims);
/* Tear down domain paging */
rc1 = xenpaging_teardown(paging);
diff -r 0900b1c905f1 -r 4b2dbd2cb997 tools/xenpaging/xenpaging.h
--- a/tools/xenpaging/xenpaging.h
+++ b/tools/xenpaging/xenpaging.h
@@ -46,6 +46,9 @@ struct xenpaging {
unsigned long *bitmap;
+ unsigned long *slot_to_gfn;
+ int *gfn_to_slot;
+
struct mem_event mem_event;
/* number of pages for which data structures were allocated */
int max_pages;
@@ -56,13 +59,6 @@ struct xenpaging {
unsigned long pagein_queue[XENPAGING_PAGEIN_QUEUE_SIZE];
};
-
-struct victim {
- /* the gfn of the page to evict */
- unsigned long gfn;
-};
-
-
extern void create_page_in_thread(struct xenpaging *paging);
extern void page_in_trigger(void);
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 2 of 9] xenpaging: no poll timeout while page-out is in progress
2012-02-20 20:48 [PATCH 0 of 9] tools/xenpaging: cleanups and performance improvements Olaf Hering
2012-02-20 20:48 ` [PATCH 1 of 9] xenpaging: use flat index for pagefile and page-in requests Olaf Hering
@ 2012-02-20 20:48 ` Olaf Hering
2012-02-20 20:48 ` [PATCH 3 of 9] xenpaging: reduce number of qemu cache flushes Olaf Hering
` (7 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Olaf Hering @ 2012-02-20 20:48 UTC (permalink / raw)
To: xen-devel
# HG changeset patch
# User Olaf Hering <olaf@aepfle.de>
# Date 1329769124 -3600
# Node ID 9c678c4e4658f17325e4549cb152d610f85efad4
# Parent 4b2dbd2cb9977f357a5dd754c923ed14dda2ec51
xenpaging: no poll timeout while page-out is in progress
The main loop calls xenpaging_wait_for_event_or_timeout() unconditionally
before doing any work. This function calls poll() with a timeout of 100ms. As
a result the page-out process is very slow due to the delay in poll().
Call poll() without timeout so that it returns immediately until the page-out
is done. Page-out is done when either the policy finds no more pages to
nominate or when the requested number of pages is reached.
The condition is cleared when a watch event arrives, so that processing the
new target is not delayed once again by poll().
v2:
- no poll timeout also when large number of evicts is pending
Signed-off-by: Olaf Hering <olaf@aepfle.de>
diff -r 4b2dbd2cb997 -r 9c678c4e4658 tools/xenpaging/policy_default.c
--- a/tools/xenpaging/policy_default.c
+++ b/tools/xenpaging/policy_default.c
@@ -90,6 +90,7 @@ unsigned long policy_choose_victim(struc
/* Could not nominate any gfn */
if ( wrap == current_gfn )
{
+ paging->use_poll_timeout = 1;
/* Count wrap arounds */
unconsumed_cleared++;
/* Force retry every few seconds (depends on poll() timeout) */
diff -r 4b2dbd2cb997 -r 9c678c4e4658 tools/xenpaging/xenpaging.c
--- a/tools/xenpaging/xenpaging.c
+++ b/tools/xenpaging/xenpaging.c
@@ -84,6 +84,7 @@ static int xenpaging_wait_for_event_or_t
struct pollfd fd[2];
int port;
int rc;
+ int timeout;
/* Wait for event channel and xenstore */
fd[0].fd = xc_evtchn_fd(xce);
@@ -91,7 +92,9 @@ static int xenpaging_wait_for_event_or_t
fd[1].fd = xs_fileno(paging->xs_handle);
fd[1].events = POLLIN | POLLERR;
- rc = poll(fd, 2, 100);
+ /* No timeout while page-out is still in progress */
+ timeout = paging->use_poll_timeout ? 100 : 0;
+ rc = poll(fd, 2, timeout);
if ( rc < 0 )
{
if (errno == EINTR)
@@ -133,6 +136,8 @@ static int xenpaging_wait_for_event_or_t
if ( target_tot_pages < 0 || target_tot_pages > paging->max_pages )
target_tot_pages = paging->max_pages;
paging->target_tot_pages = target_tot_pages;
+ /* Disable poll() delay while new target is not yet reached */
+ paging->use_poll_timeout = 0;
DPRINTF("new target_tot_pages %d\n", target_tot_pages);
}
free(val);
@@ -970,7 +975,10 @@ int main(int argc, char *argv[])
}
/* Limit the number of evicts to be able to process page-in requests */
if ( num > 42 )
+ {
+ paging->use_poll_timeout = 0;
num = 42;
+ }
evict_pages(paging, fd, num);
}
/* Resume some pages if target not reached */
@@ -984,6 +992,11 @@ int main(int argc, char *argv[])
}
resume_pages(paging, num);
}
+ /* Now target was reached, enable poll() timeout */
+ else
+ {
+ paging->use_poll_timeout = 1;
+ }
}
DPRINTF("xenpaging got signal %d\n", interrupted);
diff -r 4b2dbd2cb997 -r 9c678c4e4658 tools/xenpaging/xenpaging.h
--- a/tools/xenpaging/xenpaging.h
+++ b/tools/xenpaging/xenpaging.h
@@ -55,6 +55,7 @@ struct xenpaging {
int num_paged_out;
int target_tot_pages;
int policy_mru_size;
+ int use_poll_timeout;
int debug;
unsigned long pagein_queue[XENPAGING_PAGEIN_QUEUE_SIZE];
};
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 3 of 9] xenpaging: reduce number of qemu cache flushes
2012-02-20 20:48 [PATCH 0 of 9] tools/xenpaging: cleanups and performance improvements Olaf Hering
2012-02-20 20:48 ` [PATCH 1 of 9] xenpaging: use flat index for pagefile and page-in requests Olaf Hering
2012-02-20 20:48 ` [PATCH 2 of 9] xenpaging: no poll timeout while page-out is in progress Olaf Hering
@ 2012-02-20 20:48 ` Olaf Hering
2012-02-20 20:48 ` [PATCH 4 of 9] xenpaging: move nominate+evict into single function Olaf Hering
` (6 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Olaf Hering @ 2012-02-20 20:48 UTC (permalink / raw)
To: xen-devel
# HG changeset patch
# User Olaf Hering <olaf@aepfle.de>
# Date 1329769124 -3600
# Node ID 41d398992bc05ec5c3d9c7e10f5d5156d8794725
# Parent 9c678c4e4658f17325e4549cb152d610f85efad4
xenpaging: reduce number of qemu cache flushes
Currently the command to flush the qemu cache is called alot if there
are no more pages to evict. This causes churn in the logfiles, and qemu
can not release more pages anyway since the last command.
Fix this by remembering the current number of paged-out gfns, if this
number did not change since the last flush command then sending another
new flush command will not free any more gfns.
Remove return code from xenpaging_mem_paging_flush_ioemu_cache() since
errors do not matter, and will be handled elsewhere. Also failure to
send the flush command is not fatal.
Signed-off-by: Olaf Hering <olaf@aepfle.de>
diff -r 9c678c4e4658 -r 41d398992bc0 tools/xenpaging/xenpaging.c
--- a/tools/xenpaging/xenpaging.c
+++ b/tools/xenpaging/xenpaging.c
@@ -61,18 +61,15 @@ static void close_handler(int sig)
unlink_pagefile();
}
-static int xenpaging_mem_paging_flush_ioemu_cache(struct xenpaging *paging)
+static void xenpaging_mem_paging_flush_ioemu_cache(struct xenpaging *paging)
{
struct xs_handle *xsh = paging->xs_handle;
domid_t domain_id = paging->mem_event.domain_id;
char path[80];
- bool rc;
sprintf(path, "/local/domain/0/device-model/%u/command", domain_id);
- rc = xs_write(xsh, XBT_NULL, path, "flush-cache", strlen("flush-cache"));
-
- return rc == true ? 0 : -1;
+ xs_write(xsh, XBT_NULL, path, "flush-cache", strlen("flush-cache"));
}
static int xenpaging_wait_for_event_or_timeout(struct xenpaging *paging)
@@ -728,7 +725,7 @@ static int evict_victim(struct xenpaging
{
xc_interface *xch = paging->xc_handle;
unsigned long gfn;
- int j = 0;
+ static int num_paged_out;
int ret;
do
@@ -736,6 +733,17 @@ static int evict_victim(struct xenpaging
gfn = policy_choose_victim(paging);
if ( gfn == INVALID_MFN )
{
+ /* If the number did not change after last flush command then
+ * the command did not reach qemu yet, or qemu still processes
+ * the command, or qemu has nothing to release.
+ * Right now there is no need to issue the command again.
+ */
+ 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;
}
@@ -748,12 +756,6 @@ static int evict_victim(struct xenpaging
ret = xc_mem_paging_nominate(xch, paging->mem_event.domain_id, gfn);
if ( ret == 0 )
ret = xenpaging_evict_page(paging, gfn, fd, slot);
- else
- {
- if ( j++ % 1000 == 0 )
- if ( xenpaging_mem_paging_flush_ioemu_cache(paging) )
- PERROR("Error flushing ioemu cache");
- }
}
while ( ret );
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 4 of 9] xenpaging: move nominate+evict into single function
2012-02-20 20:48 [PATCH 0 of 9] tools/xenpaging: cleanups and performance improvements Olaf Hering
` (2 preceding siblings ...)
2012-02-20 20:48 ` [PATCH 3 of 9] xenpaging: reduce number of qemu cache flushes Olaf Hering
@ 2012-02-20 20:48 ` Olaf Hering
2012-02-20 20:48 ` [PATCH 5 of 9] xenpaging: improve performance in policy_choose_victim Olaf Hering
` (5 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Olaf Hering @ 2012-02-20 20:48 UTC (permalink / raw)
To: xen-devel
# HG changeset patch
# User Olaf Hering <olaf@aepfle.de>
# Date 1329769124 -3600
# Node ID 1679965628f5fb2f4127edcb0fc1d449f50f32d6
# Parent 41d398992bc05ec5c3d9c7e10f5d5156d8794725
xenpaging: move nominate+evict into single function
Move all code to evict a single gfn into one function. This simplifies
error handling in caller. The function returns -1 on fatal error, 0 on
success and 1 if the gfn cant be paged.
Signed-off-by: Olaf Hering <olaf@aepfle.de>
diff -r 41d398992bc0 -r 1679965628f5 tools/xenpaging/xenpaging.c
--- a/tools/xenpaging/xenpaging.c
+++ b/tools/xenpaging/xenpaging.c
@@ -571,6 +571,11 @@ static void put_response(struct mem_even
RING_PUSH_RESPONSES(back_ring);
}
+/* Evict a given gfn
+ * Returns < 0 on fatal error
+ * Returns 0 on successful evict
+ * Returns > 0 if gfn can not be evicted
+ */
static int xenpaging_evict_page(struct xenpaging *paging, unsigned long gfn, int fd, int slot)
{
xc_interface *xch = paging->xc_handle;
@@ -580,31 +585,51 @@ static int xenpaging_evict_page(struct x
DECLARE_DOMCTL;
+ /* Nominate page */
+ ret = xc_mem_paging_nominate(xch, paging->mem_event.domain_id, gfn);
+ if ( ret < 0 )
+ {
+ /* unpageable gfn is indicated by EBUSY */
+ if ( errno == EBUSY )
+ ret = 1;
+ else
+ PERROR("Error nominating page %lx", gfn);
+ goto out;
+ }
+
/* Map page */
- ret = -EFAULT;
page = xc_map_foreign_pages(xch, paging->mem_event.domain_id, PROT_READ, &victim, 1);
if ( page == NULL )
{
PERROR("Error mapping page %lx", gfn);
+ ret = -1;
goto out;
}
/* Copy page */
ret = write_page(fd, page, slot);
- if ( ret != 0 )
+ if ( ret < 0 )
{
PERROR("Error copying page %lx", gfn);
munmap(page, PAGE_SIZE);
+ ret = -1;
goto out;
}
+ /* Release page */
munmap(page, PAGE_SIZE);
/* Tell Xen to evict page */
ret = xc_mem_paging_evict(xch, paging->mem_event.domain_id, gfn);
- if ( ret != 0 )
+ if ( ret < 0 )
{
- PERROR("Error evicting page %lx", gfn);
+ /* A gfn in use is indicated by EBUSY */
+ if ( errno == EBUSY )
+ {
+ ret = 1;
+ DPRINTF("Nominated page %lx busy", gfn);
+ } else
+ PERROR("Error evicting page %lx", gfn);
goto out;
}
@@ -619,6 +644,8 @@ static int xenpaging_evict_page(struct x
/* Record number of evicted pages */
paging->num_paged_out++;
+ ret = 0;
+
out:
return ret;
}
@@ -753,9 +780,10 @@ static int evict_victim(struct xenpaging
ret = -EINTR;
goto out;
}
- ret = xc_mem_paging_nominate(xch, paging->mem_event.domain_id, gfn);
- if ( ret == 0 )
- ret = xenpaging_evict_page(paging, gfn, fd, slot);
+
+ ret = xenpaging_evict_page(paging, gfn, fd, slot);
+ if ( ret < 0 )
+ goto out;
}
while ( ret );
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 5 of 9] xenpaging: improve performance in policy_choose_victim
2012-02-20 20:48 [PATCH 0 of 9] tools/xenpaging: cleanups and performance improvements Olaf Hering
` (3 preceding siblings ...)
2012-02-20 20:48 ` [PATCH 4 of 9] xenpaging: move nominate+evict into single function Olaf Hering
@ 2012-02-20 20:48 ` Olaf Hering
2012-02-20 20:48 ` [PATCH 6 of 9] xenpaging: unify error handling Olaf Hering
` (4 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Olaf Hering @ 2012-02-20 20:48 UTC (permalink / raw)
To: xen-devel
# HG changeset patch
# User Olaf Hering <olaf@aepfle.de>
# Date 1329769124 -3600
# Node ID 58b9625f746a29db55429c337574f0852e21e06c
# Parent 1679965628f5fb2f4127edcb0fc1d449f50f32d6
xenpaging: improve performance in policy_choose_victim
policy_choose_victim() is one of the bottlenecks in xenpaging. It is called
alot to find free bits in the fragmented bitmaps.
Reduce turnaround time by skipping longs with all bits set.
Adjust wrap detection in loop.
v2:
- fix copy&paste error, bitmap was tested twice
Signed-off-by: Olaf Hering <olaf@aepfle.de>
diff -r 1679965628f5 -r 58b9625f746a tools/xenpaging/policy_default.c
--- a/tools/xenpaging/policy_default.c
+++ b/tools/xenpaging/policy_default.c
@@ -80,33 +80,58 @@ int policy_init(struct xenpaging *paging
unsigned long policy_choose_victim(struct xenpaging *paging)
{
xc_interface *xch = paging->xc_handle;
- unsigned long wrap = current_gfn;
+ unsigned long i;
- do
+ /* One iteration over all possible gfns */
+ for ( i = 0; i < max_pages; i++ )
{
+ /* Try next gfn */
current_gfn++;
+
+ /* Restart on wrap */
if ( current_gfn >= max_pages )
current_gfn = 0;
- /* Could not nominate any gfn */
- if ( wrap == current_gfn )
+
+ if ( (current_gfn & (BITS_PER_LONG - 1)) == 0 )
{
- paging->use_poll_timeout = 1;
- /* Count wrap arounds */
- unconsumed_cleared++;
- /* Force retry every few seconds (depends on poll() timeout) */
- if ( unconsumed_cleared > 123)
+ /* All gfns busy */
+ if ( ~bitmap[current_gfn >> ORDER_LONG] == 0 || ~unconsumed[current_gfn >> ORDER_LONG] == 0 )
{
- /* Force retry of unconsumed gfns */
- bitmap_clear(unconsumed, max_pages);
- unconsumed_cleared = 0;
- DPRINTF("clearing unconsumed, wrap %lx", wrap);
- /* One more round before returning ENOSPC */
+ current_gfn += BITS_PER_LONG;
+ i += BITS_PER_LONG;
continue;
}
- return INVALID_MFN;
}
+
+ /* gfn busy */
+ if ( test_bit(current_gfn, bitmap) )
+ continue;
+
+ /* gfn already tested */
+ if ( test_bit(current_gfn, unconsumed) )
+ continue;
+
+ /* gfn found */
+ break;
}
- while ( test_bit(current_gfn, bitmap) || test_bit(current_gfn, unconsumed) );
+
+ /* Could not nominate any gfn */
+ if ( i >= max_pages )
+ {
+ /* No more pages, wait in poll */
+ paging->use_poll_timeout = 1;
+ /* Count wrap arounds */
+ unconsumed_cleared++;
+ /* Force retry every few seconds (depends on poll() timeout) */
+ if ( unconsumed_cleared > 123)
+ {
+ /* Force retry of unconsumed gfns on next call */
+ bitmap_clear(unconsumed, max_pages);
+ unconsumed_cleared = 0;
+ DPRINTF("clearing unconsumed, current_gfn %lx", current_gfn);
+ }
+ return INVALID_MFN;
+ }
set_bit(current_gfn, unconsumed);
return current_gfn;
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 6 of 9] xenpaging: unify error handling
2012-02-20 20:48 [PATCH 0 of 9] tools/xenpaging: cleanups and performance improvements Olaf Hering
` (4 preceding siblings ...)
2012-02-20 20:48 ` [PATCH 5 of 9] xenpaging: improve performance in policy_choose_victim Olaf Hering
@ 2012-02-20 20:48 ` Olaf Hering
2012-02-20 20:48 ` [PATCH 7 of 9] xenpaging: move pagefile filedescriptor into struct xenpaging Olaf Hering
` (3 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Olaf Hering @ 2012-02-20 20:48 UTC (permalink / raw)
To: xen-devel
# HG changeset patch
# User Olaf Hering <olaf@aepfle.de>
# Date 1329769124 -3600
# Node ID e4b7da7e355998a404252777c274e8e149ce7a63
# Parent 58b9625f746a29db55429c337574f0852e21e06c
xenpaging: unify error handling
Update functions to return -1 on error, 0 on success.
Simplify init_page() and make sure errno is assigned.
Adjust PERROR/ERROR usage, use PERROR early because it overwrites errno.
Adjust xenpaging_populate_page() to handle gfn as unsigned long.
Update xenpaging exit code handling. xenpaging_teardown cant possible
fail. Adjust mainloop to indicate possible errors to final exit.
Signed-off-by: Olaf Hering <olaf@aepfle.de>
diff -r 58b9625f746a -r e4b7da7e3559 tools/xenpaging/xenpaging.c
--- a/tools/xenpaging/xenpaging.c
+++ b/tools/xenpaging/xenpaging.c
@@ -98,7 +98,7 @@ static int xenpaging_wait_for_event_or_t
return 0;
PERROR("Poll exited with an error");
- return -errno;
+ return -1;
}
/* First check for guest shutdown */
@@ -116,6 +116,7 @@ static int xenpaging_wait_for_event_or_t
{
xs_unwatch(paging->xs_handle, "@releaseDomain", watch_token);
interrupted = SIGQUIT;
+ /* No further poll result processing */
rc = 0;
}
}
@@ -183,26 +184,20 @@ static int xenpaging_get_tot_pages(struc
static void *init_page(void)
{
void *buffer;
- int ret;
/* Allocated page memory */
- ret = posix_memalign(&buffer, PAGE_SIZE, PAGE_SIZE);
- if ( ret != 0 )
- goto out_alloc;
+ errno = posix_memalign(&buffer, PAGE_SIZE, PAGE_SIZE);
+ if ( errno != 0 )
+ return NULL;
/* Lock buffer in memory so it can't be paged out */
- ret = mlock(buffer, PAGE_SIZE);
- if ( ret != 0 )
- goto out_lock;
+ if ( mlock(buffer, PAGE_SIZE) < 0 )
+ {
+ free(buffer);
+ buffer = NULL;
+ }
return buffer;
-
- out_init:
- munlock(buffer, PAGE_SIZE);
- out_lock:
- free(buffer);
- out_alloc:
- return NULL;
}
static void usage(void)
@@ -449,7 +444,7 @@ static struct xenpaging *xenpaging_init(
paging_buffer = init_page();
if ( !paging_buffer )
{
- ERROR("Creating page aligned load buffer");
+ PERROR("Creating page aligned load buffer");
goto err;
}
@@ -485,18 +480,14 @@ static struct xenpaging *xenpaging_init(
return NULL;
}
-static int xenpaging_teardown(struct xenpaging *paging)
+static void xenpaging_teardown(struct xenpaging *paging)
{
int rc;
- xc_interface *xch;
-
- if ( paging == NULL )
- return 0;
+ xc_interface *xch = paging->xc_handle;
xs_unwatch(paging->xs_handle, watch_target_tot_pages, "");
xs_unwatch(paging->xs_handle, "@releaseDomain", watch_token);
- xch = paging->xc_handle;
paging->xc_handle = NULL;
/* Tear down domain paging in Xen */
rc = xc_mem_paging_disable(xch, paging->mem_event.domain_id);
@@ -528,13 +519,8 @@ static int xenpaging_teardown(struct xen
rc = xc_interface_close(xch);
if ( rc != 0 )
{
- PERROR("Error closing connection to xen");
+ ERROR("Error closing connection to xen");
}
-
- return 0;
-
- err:
- return -1;
}
static void get_request(struct mem_event *mem_event, mem_event_request_t *req)
@@ -684,21 +670,19 @@ static int xenpaging_resume_page(struct
return ret;
}
-static int xenpaging_populate_page(struct xenpaging *paging,
- xen_pfn_t gfn, int fd, int i)
+static int xenpaging_populate_page(struct xenpaging *paging, unsigned long gfn, int fd, int i)
{
xc_interface *xch = paging->xc_handle;
- void *page;
int ret;
unsigned char oom = 0;
- DPRINTF("populate_page < gfn %"PRI_xen_pfn" pageslot %d\n", gfn, i);
+ DPRINTF("populate_page < gfn %lx pageslot %d\n", gfn, i);
/* Read page */
ret = read_page(fd, paging_buffer, i);
if ( ret != 0 )
{
- ERROR("Error reading page");
+ PERROR("Error reading page");
goto out;
}
@@ -707,17 +691,18 @@ static int xenpaging_populate_page(struc
/* Tell Xen to allocate a page for the domain */
ret = xc_mem_paging_load(xch, paging->mem_event.domain_id, gfn,
paging_buffer);
- if ( ret != 0 )
+ if ( ret < 0 )
{
if ( errno == ENOMEM )
{
if ( oom++ == 0 )
- DPRINTF("ENOMEM while preparing gfn %"PRI_xen_pfn"\n", gfn);
+ DPRINTF("ENOMEM while preparing gfn %lx\n", gfn);
sleep(1);
continue;
}
- PERROR("Error loading %"PRI_xen_pfn" during page-in", gfn);
- goto out;
+ PERROR("Error loading %lx during page-in", gfn);
+ ret = -1;
+ break;
}
}
while ( ret && !interrupted );
@@ -748,6 +733,11 @@ static void resume_pages(struct xenpagin
page_in_trigger();
}
+/* Evict one gfn and write it to the given slot
+ * Returns < 0 on fatal error
+ * Returns 0 on successful evict
+ * Returns > 0 if no gfn can be evicted
+ */
static int evict_victim(struct xenpaging *paging, int fd, int slot)
{
xc_interface *xch = paging->xc_handle;
@@ -771,13 +761,13 @@ static int evict_victim(struct xenpaging
xenpaging_mem_paging_flush_ioemu_cache(paging);
num_paged_out = paging->num_paged_out;
}
- ret = -ENOSPC;
+ ret = ENOSPC;
goto out;
}
if ( interrupted )
{
- ret = -EINTR;
+ ret = EINTR;
goto out;
}
@@ -788,7 +778,7 @@ static int evict_victim(struct xenpaging
while ( ret );
if ( test_and_set_bit(gfn, paging->bitmap) )
- ERROR("Page has been evicted before");
+ ERROR("Page %lx has been evicted before", gfn);
ret = 0;
@@ -796,7 +786,11 @@ static int evict_victim(struct xenpaging
return ret;
}
-/* Evict a batch of pages and write them to a free slot in the paging file */
+/* Evict a batch of pages and write them to a free slot in the paging file
+ * Returns < 0 on fatal error
+ * Returns 0 if no gfn can be evicted
+ * Returns > 0 on successful evict
+ */
static int evict_pages(struct xenpaging *paging, int fd, int num_pages)
{
xc_interface *xch = paging->xc_handle;
@@ -809,12 +803,12 @@ static int evict_pages(struct xenpaging
continue;
rc = evict_victim(paging, fd, slot);
- if ( rc == -ENOSPC )
+ if ( rc )
+ {
+ num = rc < 0 ? -1 : num;
break;
- if ( rc == -EINTR )
- break;
- if ( num && num % 100 == 0 )
- DPRINTF("%d pages evicted\n", num);
+ }
+
num++;
}
return num;
@@ -829,8 +823,7 @@ int main(int argc, char *argv[])
int num, prev_num = 0;
int slot;
int tot_pages;
- int rc = -1;
- int rc1;
+ int rc;
xc_interface *xch;
int open_flags = O_CREAT | O_TRUNC | O_RDWR;
@@ -875,7 +868,7 @@ int main(int argc, char *argv[])
rc = xenpaging_wait_for_event_or_timeout(paging);
if ( rc < 0 )
{
- PERROR("Error getting event");
+ ERROR("Error getting event");
goto out;
}
else if ( rc != 0 )
@@ -885,6 +878,9 @@ int main(int argc, char *argv[])
while ( RING_HAS_UNCONSUMED_REQUESTS(&paging->mem_event.back_ring) )
{
+ /* Indicate possible error */
+ rc = 1;
+
get_request(&paging->mem_event, &req);
if ( req.gfn > paging->max_pages )
@@ -915,10 +911,9 @@ int main(int argc, char *argv[])
else
{
/* Populate the page */
- rc = xenpaging_populate_page(paging, req.gfn, fd, slot);
- if ( rc != 0 )
+ if ( xenpaging_populate_page(paging, req.gfn, fd, slot) < 0 )
{
- PERROR("Error populating page %"PRIx64"", req.gfn);
+ ERROR("Error populating page %"PRIx64"", req.gfn);
goto out;
}
}
@@ -928,8 +923,7 @@ int main(int argc, char *argv[])
rsp.vcpu_id = req.vcpu_id;
rsp.flags = req.flags;
- rc = xenpaging_resume_page(paging, &rsp, 1);
- if ( rc != 0 )
+ if ( xenpaging_resume_page(paging, &rsp, 1) < 0 )
{
PERROR("Error resuming page %"PRIx64"", req.gfn);
goto out;
@@ -955,8 +949,7 @@ int main(int argc, char *argv[])
rsp.vcpu_id = req.vcpu_id;
rsp.flags = req.flags;
- rc = xenpaging_resume_page(paging, &rsp, 0);
- if ( rc != 0 )
+ if ( xenpaging_resume_page(paging, &rsp, 0) < 0 )
{
PERROR("Error resuming page %"PRIx64"", req.gfn);
goto out;
@@ -983,6 +976,9 @@ int main(int argc, char *argv[])
if ( interrupted )
break;
+ /* Indicate possible error */
+ rc = 1;
+
/* Check if the target has been reached already */
tot_pages = xenpaging_get_tot_pages(paging);
if ( tot_pages < 0 )
@@ -1009,7 +1005,8 @@ int main(int argc, char *argv[])
paging->use_poll_timeout = 0;
num = 42;
}
- evict_pages(paging, fd, num);
+ if ( evict_pages(paging, fd, num) < 0 )
+ goto out;
}
/* Resume some pages if target not reached */
else if ( tot_pages < paging->target_tot_pages && paging->num_paged_out )
@@ -1029,6 +1026,10 @@ int main(int argc, char *argv[])
}
}
+
+ /* No error */
+ rc = 0;
+
DPRINTF("xenpaging got signal %d\n", interrupted);
out:
@@ -1036,13 +1037,9 @@ int main(int argc, char *argv[])
unlink_pagefile();
/* Tear down domain paging */
- rc1 = xenpaging_teardown(paging);
- if ( rc1 != 0 )
- fprintf(stderr, "Error tearing down paging");
+ xenpaging_teardown(paging);
- if ( rc == 0 )
- rc = rc1;
- return rc;
+ return rc ? 2 : 0;
}
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 7 of 9] xenpaging: move pagefile filedescriptor into struct xenpaging
2012-02-20 20:48 [PATCH 0 of 9] tools/xenpaging: cleanups and performance improvements Olaf Hering
` (5 preceding siblings ...)
2012-02-20 20:48 ` [PATCH 6 of 9] xenpaging: unify error handling Olaf Hering
@ 2012-02-20 20:48 ` Olaf Hering
2012-02-20 20:48 ` [PATCH 8 of 9] xenpaging: move page_buffer " Olaf Hering
` (2 subsequent siblings)
9 siblings, 0 replies; 11+ messages in thread
From: Olaf Hering @ 2012-02-20 20:48 UTC (permalink / raw)
To: xen-devel
# HG changeset patch
# User Olaf Hering <olaf@aepfle.de>
# Date 1329769124 -3600
# Node ID c137d7bd207b7b21d69bd6470be285023a4c2baf
# Parent e4b7da7e355998a404252777c274e8e149ce7a63
xenpaging: move pagefile filedescriptor into struct xenpaging
Signed-off-by: Olaf Hering <olaf@aepfle.de>
diff -r e4b7da7e3559 -r c137d7bd207b tools/xenpaging/xenpaging.c
--- a/tools/xenpaging/xenpaging.c
+++ b/tools/xenpaging/xenpaging.c
@@ -448,6 +448,14 @@ static struct xenpaging *xenpaging_init(
goto err;
}
+ /* Open file */
+ paging->fd = open(filename, O_CREAT | O_TRUNC | O_RDWR, S_IRUSR | S_IWUSR);
+ if ( paging->fd < 0 )
+ {
+ PERROR("failed to open file");
+ goto err;
+ }
+
return paging;
err:
@@ -562,7 +570,7 @@ static void put_response(struct mem_even
* Returns 0 on successful evict
* Returns > 0 if gfn can not be evicted
*/
-static int xenpaging_evict_page(struct xenpaging *paging, unsigned long gfn, int fd, int slot)
+static int xenpaging_evict_page(struct xenpaging *paging, unsigned long gfn, int slot)
{
xc_interface *xch = paging->xc_handle;
void *page;
@@ -593,7 +601,7 @@ static int xenpaging_evict_page(struct x
}
/* Copy page */
- ret = write_page(fd, page, slot);
+ ret = write_page(paging->fd, page, slot);
if ( ret < 0 )
{
PERROR("Error copying page %lx", gfn);
@@ -670,7 +678,7 @@ static int xenpaging_resume_page(struct
return ret;
}
-static int xenpaging_populate_page(struct xenpaging *paging, unsigned long gfn, int fd, int i)
+static int xenpaging_populate_page(struct xenpaging *paging, unsigned long gfn, int i)
{
xc_interface *xch = paging->xc_handle;
int ret;
@@ -679,7 +687,7 @@ static int xenpaging_populate_page(struc
DPRINTF("populate_page < gfn %lx pageslot %d\n", gfn, i);
/* Read page */
- ret = read_page(fd, paging_buffer, i);
+ ret = read_page(paging->fd, paging_buffer, i);
if ( ret != 0 )
{
PERROR("Error reading page");
@@ -738,7 +746,7 @@ static void resume_pages(struct xenpagin
* Returns 0 on successful evict
* Returns > 0 if no gfn can be evicted
*/
-static int evict_victim(struct xenpaging *paging, int fd, int slot)
+static int evict_victim(struct xenpaging *paging, int slot)
{
xc_interface *xch = paging->xc_handle;
unsigned long gfn;
@@ -771,7 +779,7 @@ static int evict_victim(struct xenpaging
goto out;
}
- ret = xenpaging_evict_page(paging, gfn, fd, slot);
+ ret = xenpaging_evict_page(paging, gfn, slot);
if ( ret < 0 )
goto out;
}
@@ -791,7 +799,7 @@ static int evict_victim(struct xenpaging
* Returns 0 if no gfn can be evicted
* Returns > 0 on successful evict
*/
-static int evict_pages(struct xenpaging *paging, int fd, int num_pages)
+static int evict_pages(struct xenpaging *paging, int num_pages)
{
xc_interface *xch = paging->xc_handle;
int rc, slot, num = 0;
@@ -802,7 +810,7 @@ static int evict_pages(struct xenpaging
if ( paging->slot_to_gfn[slot] )
continue;
- rc = evict_victim(paging, fd, slot);
+ rc = evict_victim(paging, slot);
if ( rc )
{
num = rc < 0 ? -1 : num;
@@ -826,10 +834,6 @@ int main(int argc, char *argv[])
int rc;
xc_interface *xch;
- int open_flags = O_CREAT | O_TRUNC | O_RDWR;
- mode_t open_mode = S_IRUSR | S_IWUSR;
- int fd;
-
/* Initialise domain paging */
paging = xenpaging_init(argc, argv);
if ( paging == NULL )
@@ -841,14 +845,6 @@ int main(int argc, char *argv[])
DPRINTF("starting %s for domain_id %u with pagefile %s\n", argv[0], paging->mem_event.domain_id, filename);
- /* Open file */
- fd = open(filename, open_flags, open_mode);
- if ( fd < 0 )
- {
- perror("failed to open file");
- return 2;
- }
-
/* ensure that if we get a signal, we'll do cleanup, then exit */
act.sa_handler = close_handler;
act.sa_flags = 0;
@@ -911,7 +907,7 @@ int main(int argc, char *argv[])
else
{
/* Populate the page */
- if ( xenpaging_populate_page(paging, req.gfn, fd, slot) < 0 )
+ if ( xenpaging_populate_page(paging, req.gfn, slot) < 0 )
{
ERROR("Error populating page %"PRIx64"", req.gfn);
goto out;
@@ -1005,7 +1001,7 @@ int main(int argc, char *argv[])
paging->use_poll_timeout = 0;
num = 42;
}
- if ( evict_pages(paging, fd, num) < 0 )
+ if ( evict_pages(paging, num) < 0 )
goto out;
}
/* Resume some pages if target not reached */
@@ -1033,7 +1029,7 @@ int main(int argc, char *argv[])
DPRINTF("xenpaging got signal %d\n", interrupted);
out:
- close(fd);
+ close(paging->fd);
unlink_pagefile();
/* Tear down domain paging */
diff -r e4b7da7e3559 -r c137d7bd207b tools/xenpaging/xenpaging.h
--- a/tools/xenpaging/xenpaging.h
+++ b/tools/xenpaging/xenpaging.h
@@ -50,6 +50,7 @@ struct xenpaging {
int *gfn_to_slot;
struct mem_event mem_event;
+ int fd;
/* number of pages for which data structures were allocated */
int max_pages;
int num_paged_out;
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 8 of 9] xenpaging: move page_buffer into struct xenpaging
2012-02-20 20:48 [PATCH 0 of 9] tools/xenpaging: cleanups and performance improvements Olaf Hering
` (6 preceding siblings ...)
2012-02-20 20:48 ` [PATCH 7 of 9] xenpaging: move pagefile filedescriptor into struct xenpaging Olaf Hering
@ 2012-02-20 20:48 ` Olaf Hering
2012-02-20 20:48 ` [PATCH 9 of 9] xenpaging: implement stack of free slots in pagefile Olaf Hering
2012-02-21 17:38 ` [PATCH 0 of 9] tools/xenpaging: cleanups and performance improvements Ian Jackson
9 siblings, 0 replies; 11+ messages in thread
From: Olaf Hering @ 2012-02-20 20:48 UTC (permalink / raw)
To: xen-devel
# HG changeset patch
# User Olaf Hering <olaf@aepfle.de>
# Date 1329769124 -3600
# Node ID bb3de3bbdff3ea9da31f421053cae65999d15c89
# Parent c137d7bd207b7b21d69bd6470be285023a4c2baf
xenpaging: move page_buffer into struct xenpaging
Signed-off-by: Olaf Hering <olaf@aepfle.de>
diff -r c137d7bd207b -r bb3de3bbdff3 tools/xenpaging/xenpaging.c
--- a/tools/xenpaging/xenpaging.c
+++ b/tools/xenpaging/xenpaging.c
@@ -44,7 +44,6 @@ static char *dom_path;
static char watch_token[16];
static char *filename;
static int interrupted;
-static void *paging_buffer = NULL;
static void unlink_pagefile(void)
{
@@ -441,8 +440,8 @@ static struct xenpaging *xenpaging_init(
goto err;
}
- paging_buffer = init_page();
- if ( !paging_buffer )
+ paging->paging_buffer = init_page();
+ if ( !paging->paging_buffer )
{
PERROR("Creating page aligned load buffer");
goto err;
@@ -465,6 +464,11 @@ static struct xenpaging *xenpaging_init(
xs_close(paging->xs_handle);
if ( xch )
xc_interface_close(xch);
+ if ( paging->paging_buffer )
+ {
+ munlock(paging->paging_buffer, PAGE_SIZE);
+ free(paging->paging_buffer);
+ }
if ( paging->mem_event.shared_page )
{
munlock(paging->mem_event.shared_page, PAGE_SIZE);
@@ -687,7 +691,7 @@ static int xenpaging_populate_page(struc
DPRINTF("populate_page < gfn %lx pageslot %d\n", gfn, i);
/* Read page */
- ret = read_page(paging->fd, paging_buffer, i);
+ ret = read_page(paging->fd, paging->paging_buffer, i);
if ( ret != 0 )
{
PERROR("Error reading page");
@@ -697,8 +701,7 @@ static int xenpaging_populate_page(struc
do
{
/* Tell Xen to allocate a page for the domain */
- ret = xc_mem_paging_load(xch, paging->mem_event.domain_id, gfn,
- paging_buffer);
+ ret = xc_mem_paging_load(xch, paging->mem_event.domain_id, gfn, paging->paging_buffer);
if ( ret < 0 )
{
if ( errno == ENOMEM )
diff -r c137d7bd207b -r bb3de3bbdff3 tools/xenpaging/xenpaging.h
--- a/tools/xenpaging/xenpaging.h
+++ b/tools/xenpaging/xenpaging.h
@@ -49,6 +49,8 @@ struct xenpaging {
unsigned long *slot_to_gfn;
int *gfn_to_slot;
+ void *paging_buffer;
+
struct mem_event mem_event;
int fd;
/* number of pages for which data structures were allocated */
^ permalink raw reply [flat|nested] 11+ messages in thread
* [PATCH 9 of 9] xenpaging: implement stack of free slots in pagefile
2012-02-20 20:48 [PATCH 0 of 9] tools/xenpaging: cleanups and performance improvements Olaf Hering
` (7 preceding siblings ...)
2012-02-20 20:48 ` [PATCH 8 of 9] xenpaging: move page_buffer " Olaf Hering
@ 2012-02-20 20:48 ` Olaf Hering
2012-02-21 17:38 ` [PATCH 0 of 9] tools/xenpaging: cleanups and performance improvements Ian Jackson
9 siblings, 0 replies; 11+ messages in thread
From: Olaf Hering @ 2012-02-20 20:48 UTC (permalink / raw)
To: xen-devel
# HG changeset patch
# User Olaf Hering <olaf@aepfle.de>
# Date 1329769124 -3600
# Node ID f6886348f3f6c36d080b1fd667c0327d591e7cb2
# Parent bb3de3bbdff3ea9da31f421053cae65999d15c89
xenpaging: implement stack of free slots in pagefile
Scanning the slot_to_gfn[] array for a free slot is expensive because
evict_pages() always needs to scan the whole array. Remember the last
slots freed during page-in requests and reuse them in evict_pages().
Signed-off-by: Olaf Hering <olaf@aepfle.de>
diff -r bb3de3bbdff3 -r f6886348f3f6 tools/xenpaging/xenpaging.c
--- a/tools/xenpaging/xenpaging.c
+++ b/tools/xenpaging/xenpaging.c
@@ -432,6 +432,11 @@ static struct xenpaging *xenpaging_init(
if ( !paging->slot_to_gfn || !paging->gfn_to_slot )
goto err;
+ /* Allocate stack for known free slots in pagefile */
+ paging->free_slot_stack = calloc(paging->max_pages, sizeof(*paging->free_slot_stack));
+ if ( !paging->free_slot_stack )
+ goto err;
+
/* Initialise policy */
rc = policy_init(paging);
if ( rc != 0 )
@@ -483,6 +488,7 @@ static struct xenpaging *xenpaging_init(
free(dom_path);
free(watch_target_tot_pages);
+ free(paging->free_slot_stack);
free(paging->slot_to_gfn);
free(paging->gfn_to_slot);
free(paging->bitmap);
@@ -807,6 +813,20 @@ static int evict_pages(struct xenpaging
xc_interface *xch = paging->xc_handle;
int rc, slot, num = 0;
+ /* Reuse known free slots */
+ while ( paging->stack_count > 0 && num < num_pages )
+ {
+ slot = paging->free_slot_stack[--paging->stack_count];
+ rc = evict_victim(paging, slot);
+ if ( rc )
+ {
+ num = rc < 0 ? -1 : num;
+ return num;
+ }
+ num++;
+ }
+
+ /* Scan all slots slots for remainders */
for ( slot = 0; slot < paging->max_pages && num < num_pages; slot++ )
{
/* Slot is allocated */
@@ -930,6 +950,9 @@ int main(int argc, char *argv[])
/* Clear this pagefile slot */
paging->slot_to_gfn[slot] = 0;
+
+ /* Record this free slot */
+ paging->free_slot_stack[paging->stack_count++] = slot;
}
else
{
diff -r bb3de3bbdff3 -r f6886348f3f6 tools/xenpaging/xenpaging.h
--- a/tools/xenpaging/xenpaging.h
+++ b/tools/xenpaging/xenpaging.h
@@ -60,6 +60,8 @@ struct xenpaging {
int policy_mru_size;
int use_poll_timeout;
int debug;
+ int stack_count;
+ int *free_slot_stack;
unsigned long pagein_queue[XENPAGING_PAGEIN_QUEUE_SIZE];
};
^ permalink raw reply [flat|nested] 11+ messages in thread
* Re: [PATCH 0 of 9] tools/xenpaging: cleanups and performance improvements
2012-02-20 20:48 [PATCH 0 of 9] tools/xenpaging: cleanups and performance improvements Olaf Hering
` (8 preceding siblings ...)
2012-02-20 20:48 ` [PATCH 9 of 9] xenpaging: implement stack of free slots in pagefile Olaf Hering
@ 2012-02-21 17:38 ` Ian Jackson
9 siblings, 0 replies; 11+ messages in thread
From: Ian Jackson @ 2012-02-21 17:38 UTC (permalink / raw)
To: Olaf Hering; +Cc: xen-devel
Olaf Hering writes ("[Xen-devel] [PATCH 0 of 9] tools/xenpaging: cleanups and performance improvements"):
> Series sent on 2012-01-31, now rebased to 24847:0900b1c905f1
>
> This series adjusts the error reporting in the various code paths, with
> the intention that fatal errors can be detected by callers and handled
> properly. During my performance analysis with callgrind I found and
> fixed a few bottlenecks in the page-in code paths.
Thanks, applied all nine.
Ian.
^ permalink raw reply [flat|nested] 11+ messages in thread
end of thread, other threads:[~2012-02-21 17:38 UTC | newest]
Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2012-02-20 20:48 [PATCH 0 of 9] tools/xenpaging: cleanups and performance improvements Olaf Hering
2012-02-20 20:48 ` [PATCH 1 of 9] xenpaging: use flat index for pagefile and page-in requests Olaf Hering
2012-02-20 20:48 ` [PATCH 2 of 9] xenpaging: no poll timeout while page-out is in progress Olaf Hering
2012-02-20 20:48 ` [PATCH 3 of 9] xenpaging: reduce number of qemu cache flushes Olaf Hering
2012-02-20 20:48 ` [PATCH 4 of 9] xenpaging: move nominate+evict into single function Olaf Hering
2012-02-20 20:48 ` [PATCH 5 of 9] xenpaging: improve performance in policy_choose_victim Olaf Hering
2012-02-20 20:48 ` [PATCH 6 of 9] xenpaging: unify error handling Olaf Hering
2012-02-20 20:48 ` [PATCH 7 of 9] xenpaging: move pagefile filedescriptor into struct xenpaging Olaf Hering
2012-02-20 20:48 ` [PATCH 8 of 9] xenpaging: move page_buffer " Olaf Hering
2012-02-20 20:48 ` [PATCH 9 of 9] xenpaging: implement stack of free slots in pagefile Olaf Hering
2012-02-21 17:38 ` [PATCH 0 of 9] tools/xenpaging: cleanups and performance improvements Ian Jackson
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).