[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH 7 of 9] Buffer checkpoint data locally until domain has resumed execution
# HG changeset patch # User Brendan Cully <brendan@xxxxxxxxx> # Date 1240355510 25200 # Node ID dd394ec3ad784da4cfe789c380aa47092dfb0f20 # Parent 03fd0c9729f3d87e7803afb170dfc3cdff184998 Buffer checkpoint data locally until domain has resumed execution. Signed-off-by: Brendan Cully <brendan@xxxxxxxxx> diff --git a/tools/libxc/xc_domain_save.c b/tools/libxc/xc_domain_save.c --- a/tools/libxc/xc_domain_save.c +++ b/tools/libxc/xc_domain_save.c @@ -57,6 +57,15 @@ /* Address size of the guest */ unsigned int guest_width; +/* buffer for output */ +struct outbuf { + void* buf; + size_t size; + size_t pos; +}; + +#define OUTBUF_SIZE (16384 * 1024) + /* grep fodder: machine_to_phys */ #define mfn_to_pfn(_mfn) (live_m2p[(_mfn)]) @@ -159,6 +168,93 @@ return rc; } +static int outbuf_init(struct outbuf* ob, size_t size) +{ + memset(ob, 0, sizeof(*ob)); + + if (!(ob->buf = malloc(size))) { + DPRINTF("error allocating output buffer of size %zu\n", size); + return -1; + } + + ob->size = size; + + return 0; +} + +static inline int outbuf_resize(struct outbuf* ob, size_t nsize) +{ + void* nbuf; + + if (nsize <= ob->size) + return 0; + + if (!(nbuf = realloc(ob->buf, nsize))) { + DPRINTF("error reallocating output buffer from %zu to %zu\n", + ob->size, nsize); + return -1; + } + + ob->buf = nbuf; + + return 0; +} + +static inline int outbuf_write(struct outbuf* ob, void* buf, size_t len) +{ + if (len > ob->size - ob->pos) { + DPRINTF("outbuf_write: %zu > %zu@%zu\n", len, ob->size - ob->pos, ob->pos); + return -1; + } + + memcpy(ob->buf + ob->pos, buf, len); + ob->pos += len; + + return 0; +} + +/* prep for nonblocking I/O */ +static int outbuf_flush(struct outbuf* ob, int fd) +{ + int rc; + int cur = 0; + + if (!ob->pos) + return 0; + + rc = write(fd, ob->buf, ob->pos); + while (rc < 0 || cur + rc < ob->pos) { + if (rc < 0 && errno != EAGAIN && errno != EINTR) { + DPRINTF("error flushing output: %d\n", errno); + return -1; + } + if (rc > 0) + cur += rc; + + rc = write(fd, ob->buf + cur, ob->pos - cur); + } + + ob->pos = 0; + + return 0; +} + +/* if there's no room in the buffer, flush it and try again. */ +static inline int outbuf_hardwrite(struct outbuf* ob, int fd, void* buf, + size_t len) +{ + if (!len) + return 0; + + if (!outbuf_write(ob, buf, len)) + return 0; + + if (outbuf_flush(ob, fd) < 0) + return -1; + + return outbuf_write(ob, buf, len); +} + #ifdef ADAPTIVE_SAVE /* @@ -799,6 +895,10 @@ unsigned long mfn; + struct outbuf ob; + + outbuf_init(&ob, OUTBUF_SIZE); + /* If no explicit control parameters given, use defaults */ max_iters = max_iters ? : DEF_MAX_ITERS; max_factor = max_factor ? : DEF_MAX_FACTOR; @@ -1171,13 +1271,21 @@ } } - if ( write_exact(io_fd, &batch, sizeof(unsigned int)) ) + if ( last_iter ) + rc = outbuf_hardwrite(&ob, io_fd, &batch, sizeof(unsigned int)); + else + rc = write_exact(io_fd, &batch, sizeof(unsigned int)); + if ( rc ) { PERROR("Error when writing to state file (2)"); goto out; } - if ( write_exact(io_fd, pfn_type, sizeof(unsigned long)*batch) ) + if ( last_iter ) + rc = outbuf_hardwrite(&ob, io_fd, pfn_type, sizeof(unsigned long)*batch); + else + rc = write_exact(io_fd, pfn_type, sizeof(unsigned long)*batch); + if ( rc ) { PERROR("Error when writing to state file (3)"); goto out; @@ -1199,9 +1307,14 @@ run of pages we may have previously acumulated */ if ( run ) { - if ( ratewrite(io_fd, live, - (char*)region_base+(PAGE_SIZE*(j-run)), - PAGE_SIZE*run) != PAGE_SIZE*run ) + if ( last_iter ) + rc = outbuf_hardwrite(&ob, io_fd,(char*)region_base+(PAGE_SIZE*(j-run)), + PAGE_SIZE*run); + else + rc = ratewrite(io_fd, live, + (char*)region_base+(PAGE_SIZE*(j-run)), + PAGE_SIZE*run) != PAGE_SIZE*run; + if ( rc ) { ERROR("Error when writing to state file (4a)" " (errno %d)", errno); @@ -1231,7 +1344,12 @@ goto out; } - if ( ratewrite(io_fd, live, page, PAGE_SIZE) != PAGE_SIZE ) + if ( last_iter ) + rc = outbuf_hardwrite(&ob, io_fd, page, PAGE_SIZE); + else + rc = ratewrite(io_fd, live, page, PAGE_SIZE) != + PAGE_SIZE; + if ( rc ) { ERROR("Error when writing to state file (4b)" " (errno %d)", errno); @@ -1240,17 +1358,37 @@ } else { +#if 0 /* We have a normal page: accumulate it for writing. */ run++; +#else + /* We have a normal page: just write it directly. */ + if ( last_iter ) + rc = outbuf_hardwrite(&ob, io_fd, spage, PAGE_SIZE); + else + rc = ratewrite(io_fd, live, spage, PAGE_SIZE) != + PAGE_SIZE; + if ( rc ) + { + ERROR("Error when writing to state file (5)" + " (errno %d)", errno); + goto out; + } +#endif } } /* end of the write out for this batch */ if ( run ) { /* write out the last accumulated run of pages */ - if ( ratewrite(io_fd, live, - (char*)region_base+(PAGE_SIZE*(j-run)), - PAGE_SIZE*run) != PAGE_SIZE*run ) + if ( last_iter ) + rc = outbuf_hardwrite(&ob, io_fd, (char*)region_base+(PAGE_SIZE*(j-run)), + PAGE_SIZE*run); + else + rc = ratewrite(io_fd, live, + (char*)region_base+(PAGE_SIZE*(j-run)), + PAGE_SIZE*run) != PAGE_SIZE*run; + if ( rc ) { ERROR("Error when writing to state file (4c)" " (errno %d)", errno); @@ -1275,9 +1413,11 @@ { print_stats( xc_handle, dom, sent_this_iter, &stats, 1); + /* DPRINTF("Total pages sent= %ld (%.2fx)\n", total_sent, ((float)total_sent)/p2m_size ); DPRINTF("(of which %ld were fixups)\n", needed_to_fix ); + */ } if ( last_iter && debug ) @@ -1288,7 +1428,7 @@ DPRINTF("Entering debug resend-all mode\n"); /* send "-1" to put receiver into debug mode */ - if ( write_exact(io_fd, &minusone, sizeof(int)) ) + if ( outbuf_hardwrite(&ob, io_fd, &minusone, sizeof(int)) ) { PERROR("Error when writing to state file (6)"); goto out; @@ -1356,7 +1496,9 @@ } } /* end of infinite for loop */ + /* DPRINTF("All memory is saved\n"); + */ { struct { @@ -1380,7 +1522,7 @@ } chunk.vcpumap = vcpumap; - if ( write_exact(io_fd, &chunk, sizeof(chunk)) ) + if ( outbuf_hardwrite(&ob, io_fd, &chunk, sizeof(chunk)) ) { PERROR("Error when writing to state file"); goto out; @@ -1400,7 +1542,7 @@ (unsigned long *)&chunk.data); if ( (chunk.data != 0) && - write_exact(io_fd, &chunk, sizeof(chunk)) ) + outbuf_hardwrite(&ob, io_fd, &chunk, sizeof(chunk)) ) { PERROR("Error when writing the ident_pt for EPT guest"); goto out; @@ -1411,7 +1553,7 @@ (unsigned long *)&chunk.data); if ( (chunk.data != 0) && - write_exact(io_fd, &chunk, sizeof(chunk)) ) + outbuf_hardwrite(&ob, io_fd, &chunk, sizeof(chunk)) ) { PERROR("Error when writing the vm86 TSS for guest"); goto out; @@ -1420,7 +1562,7 @@ /* Zero terminate */ i = 0; - if ( write_exact(io_fd, &i, sizeof(int)) ) + if ( outbuf_hardwrite(&ob, io_fd, &i, sizeof(int)) ) { PERROR("Error when writing to state file (6')"); goto out; @@ -1438,7 +1580,7 @@ (unsigned long *)&magic_pfns[1]); xc_get_hvm_param(xc_handle, dom, HVM_PARAM_STORE_PFN, (unsigned long *)&magic_pfns[2]); - if ( write_exact(io_fd, magic_pfns, sizeof(magic_pfns)) ) + if ( outbuf_hardwrite(&ob, io_fd, magic_pfns, sizeof(magic_pfns)) ) { PERROR("Error when writing to state file (7)"); goto out; @@ -1452,13 +1594,13 @@ goto out; } - if ( write_exact(io_fd, &rec_size, sizeof(uint32_t)) ) + if ( outbuf_hardwrite(&ob, io_fd, &rec_size, sizeof(uint32_t)) ) { PERROR("error write hvm buffer size"); goto out; } - if ( write_exact(io_fd, hvm_buf, rec_size) ) + if ( outbuf_hardwrite(&ob, io_fd, hvm_buf, rec_size) ) { PERROR("write HVM info failed!\n"); goto out; @@ -1482,7 +1624,7 @@ j++; } - if ( write_exact(io_fd, &j, sizeof(unsigned int)) ) + if ( outbuf_hardwrite(&ob, io_fd, &j, sizeof(unsigned int)) ) { PERROR("Error when writing to state file (6a)"); goto out; @@ -1496,7 +1638,7 @@ i++; if ( (j == 1024) || (i == p2m_size) ) { - if ( write_exact(io_fd, &pfntab, sizeof(unsigned long)*j) ) + if ( outbuf_hardwrite(&ob, io_fd, &pfntab, sizeof(unsigned long)*j) ) { PERROR("Error when writing to state file (6b)"); goto out; @@ -1567,9 +1709,9 @@ FOLD_CR3(mfn_to_pfn(UNFOLD_CR3(ctxt.x64.ctrlreg[1]))); } - if ( write_exact(io_fd, &ctxt, ((guest_width==8) - ? sizeof(ctxt.x64) - : sizeof(ctxt.x32))) ) + if ( outbuf_hardwrite(&ob, io_fd, &ctxt, ((guest_width==8) + ? sizeof(ctxt.x64) + : sizeof(ctxt.x32))) ) { PERROR("Error when writing to state file (1)"); goto out; @@ -1583,7 +1725,7 @@ ERROR("No extended context for VCPU%d", i); goto out; } - if ( write_exact(io_fd, &domctl.u.ext_vcpucontext, 128) ) + if ( outbuf_hardwrite(&ob, io_fd, &domctl.u.ext_vcpucontext, 128) ) { PERROR("Error when writing to state file (2)"); goto out; @@ -1596,7 +1738,7 @@ memcpy(page, live_shinfo, PAGE_SIZE); SET_FIELD(((shared_info_any_t *)page), arch.pfn_to_mfn_frame_list_list, 0); - if ( write_exact(io_fd, page, PAGE_SIZE) ) + if ( outbuf_hardwrite(&ob, io_fd, page, PAGE_SIZE) ) { PERROR("Error when writing to state file (1)"); goto out; @@ -1610,6 +1752,11 @@ callbacks->postcopy(callbacks->data); /* Flush last write and discard cache for file. */ + if (outbuf_flush(&ob, io_fd) < 0) { + ERROR("Error when flushing output buffer\n"); + rc = 1; + } + discard_file_cache(io_fd, 1 /* flush */); /* checkpoint_cb can spend arbitrarily long in between rounds */ @@ -1627,9 +1774,11 @@ ERROR("Domain appears not to have suspended"); goto out; } + /* DPRINTF("SUSPEND shinfo %08lx\n", info.shared_info_frame); + print_stats(xc_handle, dom, 0, &stats, 1); - + */ if ( xc_shadow_control(xc_handle, dom, XEN_DOMCTL_SHADOW_OP_CLEAN, to_send, p2m_size, NULL, 0, &stats) != p2m_size ) _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |