WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-devel

[Xen-devel] [PATCH 7 of 9] Buffer checkpoint data locally until domain h

To: xen-devel@xxxxxxxxxxxxxxxxxxx
Subject: [Xen-devel] [PATCH 7 of 9] Buffer checkpoint data locally until domain has resumed execution
From: Brendan Cully <brendan@xxxxxxxxx>
Date: Wed, 13 May 2009 17:19:35 -0700
Cc: andy@xxxxxxxxx
Delivery-date: Wed, 13 May 2009 17:25:40 -0700
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
In-reply-to: <patchbomb.1242260368@xxxxxxxxxxxxxxxxxxxxxxxxxxx>
List-help: <mailto:xen-devel-request@lists.xensource.com?subject=help>
List-id: Xen developer discussion <xen-devel.lists.xensource.com>
List-post: <mailto:xen-devel@lists.xensource.com>
List-subscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=subscribe>
List-unsubscribe: <http://lists.xensource.com/mailman/listinfo/xen-devel>, <mailto:xen-devel-request@lists.xensource.com?subject=unsubscribe>
References: <patchbomb.1242260368@xxxxxxxxxxxxxxxxxxxxxxxxxxx>
Sender: xen-devel-bounces@xxxxxxxxxxxxxxxxxxx
User-agent: Mercurial-patchbomb/1f0f01bc86a5
# 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