[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.