diff options
Diffstat (limited to 'tools/xc/lib/xc_linux_save.c')
-rw-r--r-- | tools/xc/lib/xc_linux_save.c | 69 |
1 files changed, 52 insertions, 17 deletions
diff --git a/tools/xc/lib/xc_linux_save.c b/tools/xc/lib/xc_linux_save.c index 64625c53f6..8bcd207d7f 100644 --- a/tools/xc/lib/xc_linux_save.c +++ b/tools/xc/lib/xc_linux_save.c @@ -95,7 +95,7 @@ int xc_linux_save(int xc_handle, int verbose = flags & XCFLAGS_VERBOSE; int live = flags & XCFLAGS_LIVE; int debug = flags & XCFLAGS_DEBUG; - int sent_last_iter, sent_this_iter, max_iters; + int sent_last_iter, sent_this_iter, skip_this_iter, max_iters; /* Remember if we stopped the guest, so we can restart it on exit. */ int we_stopped_it = 0; @@ -137,8 +137,11 @@ int xc_linux_save(int xc_handle, /* number of pages we're dealing with */ unsigned long nr_pfns; - /* bitmap of pages left to send */ - unsigned long *to_send, *to_fix; + /* bitmap of pages: + - that should be sent this iteration (unless later marked as skip); + - to skip this iteration because already dirty; + - to fixup by sending at the end if not already resent; */ + unsigned long *to_send, *to_skip, *to_fix; int needed_to_fix = 0; int total_sent = 0; @@ -289,7 +292,7 @@ int xc_linux_save(int xc_handle, last_iter = 0; sent_last_iter = 1<<20; // 4GB's worth of pages - max_iters = 9; // limit us to 10 time round loop + max_iters = 19; // limit us to 20 times round loop } else last_iter = 1; @@ -301,12 +304,14 @@ int xc_linux_save(int xc_handle, to_send = malloc( sz ); to_fix = calloc( 1, sz ); + to_skip = malloc( sz ); - if (!to_send || !to_fix) + if (!to_send || !to_fix || !to_skip) { ERROR("Couldn't allocate to_send array"); goto out; } + memset( to_send, 0xff, sz ); if ( mlock( to_send, sz ) ) @@ -314,6 +319,15 @@ int xc_linux_save(int xc_handle, PERROR("Unable to mlock to_send"); return 1; } + + /* (to fix is local only) */ + + if ( mlock( to_skip, sz ) ) + { + PERROR("Unable to mlock to_skip"); + return 1; + } + } @@ -379,6 +393,7 @@ int xc_linux_save(int xc_handle, iter++; sent_this_iter = 0; + skip_this_iter = 0; prev_pc = 0; verbose_printf("Saving memory pages: iter %d 0%%", iter); @@ -392,6 +407,18 @@ int xc_linux_save(int xc_handle, prev_pc = this_pc; } + /* slightly wasteful to peek the whole array evey time, + but this is fast enough for the moment. */ + + if ( !last_iter && + xc_shadow_control( xc_handle, domid, + DOM0_SHADOW_CONTROL_OP_PEEK, + to_skip, nr_pfns ) != nr_pfns ) + { + ERROR("Error peeking shadow bitmap"); + goto out; + } + /* load pfn_type[] with the mfn of all the pages we're doing in this batch. */ @@ -405,15 +432,29 @@ int xc_linux_save(int xc_handle, test_bit(n,to_send), live_mfn_to_pfn_table[live_pfn_to_mfn_table[n]&0xFFFFF]); + if (!last_iter && test_bit(n, to_send) && test_bit(n, to_skip)) + skip_this_iter++; // stats keeping + + if (! ( (test_bit(n, to_send) && !test_bit(n, to_skip)) || + (test_bit(n, to_send) && last_iter) || + (test_bit(n, to_fix) && last_iter) ) ) + continue; - if ( !test_bit(n, to_send ) && - !( last_iter && test_bit(n, to_fix ) ) ) continue; + /* we get here if: + 1. page is marked to_send & hasn't already been re-dirtied + 2. (ignore to_skip in last iteration) + 3. add in pages that still need fixup (net bufs) + */ pfn_batch[batch] = n; pfn_type[batch] = live_pfn_to_mfn_table[n]; if( pfn_type[batch] == 0x80000004 ) { + /* not currently in pusedo-physical map -- set bit + in to_fix that we must send this page in last_iter + unless its sent sooner anyhow */ + set_bit( n, to_fix ); if( iter>1 ) DDPRINTF("Urk! netbuf race: iter %d, pfn %lx. mfn %lx\n", @@ -572,7 +613,8 @@ int xc_linux_save(int xc_handle, total_sent += sent_this_iter; - verbose_printf("\b\b\b\b100%% (%d pages)\n", sent_this_iter ); + verbose_printf("\b\b\b\b100%% (pages sent= %d, skipped= %d )\n", + sent_this_iter, skip_this_iter ); if ( last_iter ) { @@ -604,7 +646,8 @@ int xc_linux_save(int xc_handle, if ( live ) { if ( ( sent_this_iter > (sent_last_iter * 0.95) ) || - (iter >= max_iters) || (sent_this_iter < 10) ) + (iter >= max_iters) || (sent_this_iter < 10) || + (total_sent > nr_pfns*2) ) { DPRINTF("Start last iteration\n"); last_iter = 1; @@ -685,14 +728,6 @@ int xc_linux_save(int xc_handle, munmap(live_shinfo, PAGE_SIZE); out: - /* Restart the domain if we had to stop it to save its state. */ - if ( we_stopped_it ) - { - printf("Restart domain\n"); - op.cmd = DOM0_STARTDOMAIN; - op.u.startdomain.domain = (domid_t)domid; - (void)do_dom0_op(xc_handle, &op); - } if ( pfn_type != NULL ) free(pfn_type); |