[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] Fix some issues for HVM log dirty:



# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1252309078 -3600
# Node ID 49b561416efca3b5ebe143ce6349f892f249b5f4
# Parent  ead107bc25cb18143213d271b4122bf87d790228
Fix some issues for HVM log dirty:
* Add necessary logging dirty in qemu to avoid guest error with
intensive disk access when live migration
* Take place of shared memory between qemu and migration tools by new
added hypercall, which is clean and simple

Signed-Off-By: Zhai, Edwin <edwin.zhai@xxxxxxxxx>
---
 tools/libxc/ia64/xc_ia64_linux_save.c |   38 +--------
 tools/libxc/xc_domain_save.c          |   41 +---------
 tools/libxc/xenguest.h                |    3 
 tools/xcutils/xc_save.c               |  133 ++++++++++------------------------
 4 files changed, 53 insertions(+), 162 deletions(-)

diff -r ead107bc25cb -r 49b561416efc tools/libxc/ia64/xc_ia64_linux_save.c
--- a/tools/libxc/ia64/xc_ia64_linux_save.c     Fri Sep 04 08:43:05 2009 +0100
+++ b/tools/libxc/ia64/xc_ia64_linux_save.c     Mon Sep 07 08:37:58 2009 +0100
@@ -382,8 +382,7 @@ int
 int
 xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
                uint32_t max_factor, uint32_t flags, int (*suspend)(void),
-               int hvm, void *(*init_qemu_maps)(int, unsigned),
-               void (*qemu_flip_buffer)(int, int))
+               int hvm, void (*switch_qemu_logdirty)(int, unsigned))
 {
     DECLARE_DOMCTL;
     xc_dominfo_t info;
@@ -423,11 +422,6 @@ xc_domain_save(int xc_handle, int io_fd,
     unsigned long *to_skip = NULL;
 
     char *mem;
-
-    /* HVM: shared-memory bitmaps for getting log-dirty bits from qemu-dm */
-    unsigned long *qemu_bitmaps[2];
-    int qemu_active = 0;
-    int qemu_non_active = 1;
 
     /* for foreign p2m exposure */
     unsigned long memmap_info_num_pages;
@@ -545,14 +539,9 @@ xc_domain_save(int xc_handle, int io_fd,
             goto out;
         }
 
-        if (hvm) {
-            /* Get qemu-dm logging dirty pages too */
-            void *seg = init_qemu_maps(dom, bitmap_size);
-            qemu_bitmaps[0] = seg;
-            qemu_bitmaps[1] = seg + bitmap_size;
-            qemu_active = 0;
-            qemu_non_active = 1;
-        }
+        /* Enable qemu-dm logging dirty pages to xen */
+        if (hvm)
+            switch_qemu_logdirty(dom, 1);
     } else {
 
         /* This is a non-live suspend. Issue the call back to get the
@@ -703,23 +692,6 @@ xc_domain_save(int xc_handle, int io_fd,
                 goto out;
             }
 
-            if (hvm) {
-                unsigned int j;
-                /* Pull in the dirty bits from qemu-dm too */
-                if (!last_iter) {
-                    qemu_active = qemu_non_active;
-                    qemu_non_active = qemu_active ? 0 : 1;
-                    qemu_flip_buffer(dom, qemu_active);
-                    for (j = 0; j < bitmap_size / sizeof(unsigned long); j++) {
-                        to_send[j] |= qemu_bitmaps[qemu_non_active][j];
-                        qemu_bitmaps[qemu_non_active][j] = 0;
-                    }
-                } else {
-                    for (j = 0; j < bitmap_size / sizeof(unsigned long); j++)
-                        to_send[j] |= qemu_bitmaps[qemu_active][j];
-                }
-            }
-
             sent_last_iter = sent_this_iter;
 
             //print_stats(xc_handle, dom, sent_this_iter, &stats, 1);
@@ -762,6 +734,8 @@ xc_domain_save(int xc_handle, int io_fd,
                               NULL, 0, NULL, 0, NULL ) < 0) {
             DPRINTF("Warning - couldn't disable shadow mode");
         }
+        if ( hvm )
+            switch_qemu_logdirty(dom, 0);
     }
 
     unlock_pages(to_send, bitmap_size);
diff -r ead107bc25cb -r 49b561416efc tools/libxc/xc_domain_save.c
--- a/tools/libxc/xc_domain_save.c      Fri Sep 04 08:43:05 2009 +0100
+++ b/tools/libxc/xc_domain_save.c      Mon Sep 07 08:37:58 2009 +0100
@@ -38,11 +38,6 @@ static unsigned long hvirt_start;
 
 /* #levels of page tables used by the current guest */
 static unsigned int pt_levels;
-
-/* HVM: shared-memory bitmaps for getting log-dirty bits from qemu-dm */
-static unsigned long *qemu_bitmaps[2];
-static int qemu_active;
-static int qemu_non_active;
 
 /* number of pfns this guest has (i.e. number of entries in the P2M) */
 static unsigned long p2m_size;
@@ -748,8 +743,7 @@ static xen_pfn_t *map_and_save_p2m_table
 
 int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
                    uint32_t max_factor, uint32_t flags, int (*suspend)(void),
-                   int hvm, void *(*init_qemu_maps)(int, unsigned), 
-                   void (*qemu_flip_buffer)(int, int))
+                   int hvm, void (*switch_qemu_logdirty)(int, unsigned))
 {
     xc_dominfo_t info;
     DECLARE_DOMCTL;
@@ -863,15 +857,9 @@ int xc_domain_save(int xc_handle, int io
             }
         }
 
+        /* Enable qemu-dm logging dirty pages to xen */
         if ( hvm )
-        {
-            /* Get qemu-dm logging dirty pages too */
-            void *seg = init_qemu_maps(dom, BITMAP_SIZE);
-            qemu_bitmaps[0] = seg;
-            qemu_bitmaps[1] = seg + BITMAP_SIZE;
-            qemu_active = 0;
-            qemu_non_active = 1;
-        }
+            switch_qemu_logdirty(dom, 1);
     }
     else
     {
@@ -1341,27 +1329,6 @@ int xc_domain_save(int xc_handle, int io
                 goto out;
             }
 
-            if ( hvm ) 
-            {
-                /* Pull in the dirty bits from qemu-dm too */
-                if ( !last_iter )
-                {
-                    qemu_active = qemu_non_active;
-                    qemu_non_active = qemu_active ? 0 : 1;
-                    qemu_flip_buffer(dom, qemu_active);
-                    for ( j = 0; j < BITMAP_SIZE / sizeof(unsigned long); j++ )
-                    {
-                        to_send[j] |= qemu_bitmaps[qemu_non_active][j];
-                        qemu_bitmaps[qemu_non_active][j] = 0;
-                    }
-                }
-                else
-                {
-                    for ( j = 0; j < BITMAP_SIZE / sizeof(unsigned long); j++ )
-                        to_send[j] |= qemu_bitmaps[qemu_active][j];
-                }
-            }
-
             sent_last_iter = sent_this_iter;
 
             print_stats(xc_handle, dom, sent_this_iter, &stats, 1);
@@ -1629,6 +1596,8 @@ int xc_domain_save(int xc_handle, int io
                                XEN_DOMCTL_SHADOW_OP_OFF,
                                NULL, 0, NULL, 0, NULL) < 0 )
             DPRINTF("Warning - couldn't disable shadow mode");
+        if ( hvm )
+            switch_qemu_logdirty(dom, 0);
     }
 
     /* Flush last write and discard cache for file. */
diff -r ead107bc25cb -r 49b561416efc tools/libxc/xenguest.h
--- a/tools/libxc/xenguest.h    Fri Sep 04 08:43:05 2009 +0100
+++ b/tools/libxc/xenguest.h    Mon Sep 07 08:37:58 2009 +0100
@@ -26,8 +26,7 @@ int xc_domain_save(int xc_handle, int io
 int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
                    uint32_t max_factor, uint32_t flags /* XCFLAGS_xxx */,
                    int (*suspend)(void), int hvm,
-                   void *(*init_qemu_maps)(int, unsigned),  /* HVM only */
-                   void (*qemu_flip_buffer)(int, int));     /* HVM only */
+                   void (*switch_qemu_logdirty)(int, unsigned)); /* HVM only */
 
 
 /**
diff -r ead107bc25cb -r 49b561416efc tools/xcutils/xc_save.c
--- a/tools/xcutils/xc_save.c   Fri Sep 04 08:43:05 2009 +0100
+++ b/tools/xcutils/xc_save.c   Mon Sep 07 08:37:58 2009 +0100
@@ -101,115 +101,64 @@ static int suspend(void)
  * the new active buffer.  xc_save can then process and clear the old
  * active buffer. */
 
-static char *qemu_active_path;
-static char *qemu_next_active_path;
-static int qemu_shmid = -1;
-static struct xs_handle *xs;
-
-
-/* Mark the shared-memory segment for destruction */
-static void qemu_destroy_buffer(void)
-{
-    if (qemu_shmid != -1)
-        shmctl(qemu_shmid, IPC_RMID, NULL);
-    qemu_shmid = -1;
-}
-
-/* Get qemu to change buffers. */
-static void qemu_flip_buffer(int domid, int next_active)
-{
-    char digit = '0' + next_active;
+
+static void switch_qemu_logdirty(int domid, unsigned int enable)
+{
+    struct xs_handle *xs;
+    char *path, *p, *ret_str, *cmd_str, **watch;
     unsigned int len;
-    char *active_str, **watch;
     struct timeval tv;
     fd_set fdset;
 
-    /* Tell qemu that we want it to start writing log-dirty bits to the
-     * other buffer */
-    if (!xs_write(xs, XBT_NULL, qemu_next_active_path, &digit, 1))
-        errx(1, "can't write next-active to store path (%s)\n", 
-             qemu_next_active_path);
-
-    /* Wait a while for qemu to signal that it has switched to the new 
-     * active buffer */
- read_again: 
-    tv.tv_sec = 5;
-    tv.tv_usec = 0;
-    FD_ZERO(&fdset);
-    FD_SET(xs_fileno(xs), &fdset);
-    if ((select(xs_fileno(xs) + 1, &fdset, NULL, NULL, &tv)) != 1)
-        errx(1, "timed out waiting for qemu to switch buffers\n");
-    watch = xs_read_watch(xs, &len);
-    free(watch);
-    
-    active_str = xs_read(xs, XBT_NULL, qemu_active_path, &len);
-    if (active_str == NULL || active_str[0] - '0' != next_active) 
-        /* Watch fired but value is not yet right */
-        goto read_again;
-}
-
-static void *init_qemu_maps(int domid, unsigned int bitmap_size)
-{
-    key_t key;
-    char key_ascii[17] = {0,};
-    void *seg; 
-    char *path, *p;
-
-    /* Make a shared-memory segment */
-    do {
-        key = rand(); /* No security, just a sequence of numbers */
-        qemu_shmid = shmget(key, 2 * bitmap_size, 
-                       IPC_CREAT|IPC_EXCL|S_IRUSR|S_IWUSR);
-        if (qemu_shmid == -1 && errno != EEXIST)
-            errx(1, "can't get shmem to talk to qemu-dm");
-    } while (qemu_shmid == -1);
-
-    /* Remember to tidy up after ourselves */
-    atexit(qemu_destroy_buffer);
-
-    /* Map it into our address space */
-    seg = shmat(qemu_shmid, NULL, 0);
-    if (seg == (void *) -1) 
-        errx(1, "can't map shmem to talk to qemu-dm");
-    memset(seg, 0, 2 * bitmap_size);
-
-    /* Write the size of it into the first 32 bits */
-    *(uint32_t *)seg = bitmap_size;
-
-    /* Tell qemu about it */
     if ((xs = xs_daemon_open()) == NULL)
         errx(1, "Couldn't contact xenstore");
     if (!(path = strdup("/local/domain/0/device-model/")))
         errx(1, "can't get domain path in store");
     if (!(path = realloc(path, strlen(path) 
                          + 10 
-                         + strlen("/logdirty/next-active") + 1))) 
+                         + strlen("/logdirty/cmd") + 1)))
         errx(1, "no memory for constructing xenstore path");
     snprintf(path + strlen(path), 11, "%i", domid);
     strcat(path, "/logdirty/");
     p = path + strlen(path);
 
-    strcpy(p, "key");
-    snprintf(key_ascii, 17, "%16.16llx", (unsigned long long) key);
-    if (!xs_write(xs, XBT_NULL, path, key_ascii, 16))
-        errx(1, "can't write key (%s) to store path (%s)\n", key_ascii, path);
-
-    /* Watch for qemu's indication of the active buffer, and request it 
-     * to start writing to buffer 0 */
-    strcpy(p, "active");
-    if (!xs_watch(xs, path, "qemu-active-buffer"))
+
+    /* Watch for qemu's return value */
+    strcpy(p, "ret");
+    if (!xs_watch(xs, path, "qemu-logdirty-ret"))
         errx(1, "can't set watch in store (%s)\n", path);
-    if (!(qemu_active_path = strdup(path)))
-        errx(1, "no memory for copying xenstore path");
-
-    strcpy(p, "next-active");
-    if (!(qemu_next_active_path = strdup(path)))
-        errx(1, "no memory for copying xenstore path");
-
-    qemu_flip_buffer(domid, 0);
+
+    if (!(cmd_str = strdup( enable == 0 ? "disable" : "enable")))
+        errx(1, "can't get logdirty cmd path in store");
+
+    /* Tell qemu that we want it to start logging dirty page to Xen */
+    strcpy(p, "cmd");
+    if (!xs_write(xs, XBT_NULL, path, cmd_str, strlen(cmd_str)))
+        errx(1, "can't write  to store path (%s)\n",
+             path);
+
+    /* Wait a while for qemu to signal that it has service logdirty command */
+ read_again:
+    tv.tv_sec = 5;
+    tv.tv_usec = 0;
+    FD_ZERO(&fdset);
+    FD_SET(xs_fileno(xs), &fdset);
+
+    if ((select(xs_fileno(xs) + 1, &fdset, NULL, NULL, &tv)) != 1)
+        errx(1, "timed out waiting for qemu logdirty response.\n");
+
+    watch = xs_read_watch(xs, &len);
+    free(watch);
+
+    strcpy(p, "ret");
+    ret_str = xs_read(xs, XBT_NULL, path, &len);
+    if (ret_str == NULL || strcmp(ret_str, cmd_str))
+        /* Watch fired but value is not yet right */
+        goto read_again;
 
     free(path);
-    return seg;
+    free(cmd_str);
+    free(ret_str);
 }
 
 int
@@ -255,7 +204,7 @@ main(int argc, char **argv)
     }
     ret = xc_domain_save(si.xc_fd, io_fd, si.domid, maxit, max_f, si.flags, 
                          &suspend, !!(si.flags & XCFLAGS_HVM),
-                         &init_qemu_maps, &qemu_flip_buffer);
+                         &switch_qemu_logdirty);
 
     if (si.suspend_evtchn > 0)
         xc_suspend_evtchn_release(si.xce, si.suspend_evtchn);

_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog


 


Rackspace

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