From: "Zhai, Edwin" <edwin.zhai@intel.com>
To: Stefano Stabellini <stefano.stabellini@eu.citrix.com>,
Ian Jackson <Ian.Jackson@eu.citrix.com>,
Keir Fraser <keir.fraser@eu.citrix.com>
Cc: xen-devel@lists.xensource.com, "Zhai, Edwin" <edwin.zhai@intel.com>
Subject: [PATCH] [HVM] fix HVM log dirty issue
Date: Fri, 04 Sep 2009 17:01:07 +0800 [thread overview]
Message-ID: <4AA0D753.8070005@intel.com> (raw)
[-- Attachment #1: Type: text/plain, Size: 328 bytes --]
These patches fix some issues for HVM log dirty in qemu:
* 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@intel.com>
[-- Attachment #2: hvm_log_dirty_fix_qemu.patch --]
[-- Type: application/octet-stream, Size: 10061 bytes --]
Index: hv/tools/ioemu-remote/cpu-all.h
===================================================================
--- hv.orig/tools/ioemu-remote/cpu-all.h
+++ hv/tools/ioemu-remote/cpu-all.h
@@ -972,10 +972,14 @@ static inline int cpu_physical_memory_ge
return phys_ram_dirty[addr >> TARGET_PAGE_BITS] & dirty_flags;
}
+#ifdef CONFIG_DM
+void cpu_physical_memory_set_dirty(ram_addr_t addr);
+#else
static inline void cpu_physical_memory_set_dirty(ram_addr_t addr)
{
phys_ram_dirty[addr >> TARGET_PAGE_BITS] = 0xff;
}
+#endif
void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t end,
int dirty_flags);
Index: hv/tools/ioemu-remote/i386-dm/exec-dm.c
===================================================================
--- hv.orig/tools/ioemu-remote/i386-dm/exec-dm.c
+++ hv/tools/ioemu-remote/i386-dm/exec-dm.c
@@ -359,6 +359,14 @@ void cpu_unregister_io_memory(int io_tab
io_mem_opaque[io_index] = NULL;
}
+void cpu_physical_memory_set_dirty(ram_addr_t addr)
+{
+ phys_ram_dirty[addr >> TARGET_PAGE_BITS] = 0xff;
+
+ if (xen_logdirty_enable)
+ xc_hvm_modified_memory(xc_handle, domid, addr >> TARGET_PAGE_BITS, 1);
+}
+
CPUWriteMemoryFunc **cpu_get_io_memory_write(int io_index)
{
return io_mem_write[io_index >> IO_MEM_SHIFT];
@@ -453,8 +461,7 @@ void unregister_iomem(target_phys_addr_t
}
-unsigned long *logdirty_bitmap;
-unsigned long logdirty_bitmap_size;
+unsigned int xen_logdirty_enable = 0;
/*
* Replace the standard byte memcpy with a word memcpy for appropriately sized
@@ -557,19 +564,13 @@ void cpu_physical_memory_rw(target_phys_
} else if ((ptr = phys_ram_addr(addr)) != NULL) {
/* Writing to RAM */
memcpy_words(ptr, buf, l);
-#ifndef CONFIG_STUBDOM
- if (logdirty_bitmap != NULL) {
- /* Record that we have dirtied this frame */
- unsigned long pfn = addr >> TARGET_PAGE_BITS;
- if (pfn / 8 >= logdirty_bitmap_size) {
- fprintf(logfile, "dirtying pfn %lx >= bitmap "
- "size %lx\n", pfn, logdirty_bitmap_size * 8);
- } else {
- logdirty_bitmap[pfn / HOST_LONG_BITS]
- |= 1UL << pfn % HOST_LONG_BITS;
- }
- }
-#endif
+
+ if (xen_logdirty_enable)
+ xc_hvm_modified_memory(xc_handle,
+ domid,
+ addr >> TARGET_PAGE_BITS,
+ ((addr + l + TARGET_PAGE_SIZE - 1) >> TARGET_PAGE_BITS)
+ - (addr >> TARGET_PAGE_BITS));
#ifdef __ia64__
sync_icache(ptr, l);
#endif
@@ -605,13 +606,6 @@ void cpu_physical_memory_rw(target_phys_
addr += l;
}
-#ifdef CONFIG_STUBDOM
- if (logdirty_bitmap != NULL)
- xc_hvm_modified_memory(xc_handle, domid, _addr >> TARGET_PAGE_BITS,
- ((_addr + _len + TARGET_PAGE_SIZE - 1) >> TARGET_PAGE_BITS)
- - (_addr >> TARGET_PAGE_BITS));
-#endif
-
mapcache_unlock();
}
#endif
@@ -806,6 +800,11 @@ void *cpu_physical_memory_map(target_phy
if ((*plen) > l)
*plen = l;
#endif
+ if (xen_logdirty_enable)
+ xc_hvm_modified_memory(xc_handle, domid, addr >> TARGET_PAGE_BITS,
+ ((addr + l + TARGET_PAGE_SIZE - 1) >> TARGET_PAGE_BITS)
+ - (addr >> TARGET_PAGE_BITS));
+
return qemu_map_cache(addr, 1);
}
Index: hv/tools/ioemu-remote/xen-config-host.h
===================================================================
--- hv.orig/tools/ioemu-remote/xen-config-host.h
+++ hv/tools/ioemu-remote/xen-config-host.h
@@ -39,8 +39,7 @@ struct CharDriverState;
void xenstore_store_serial_port_info(int i, struct CharDriverState *chr,
const char *devname);
-extern unsigned long *logdirty_bitmap;
-extern unsigned long logdirty_bitmap_size;
+extern unsigned int xen_logdirty_enable;
#ifdef CONFIG_STUBDOM
#undef HAVE_IOVEC
Index: hv/tools/ioemu-remote/xenstore.c
===================================================================
--- hv.orig/tools/ioemu-remote/xenstore.c
+++ hv/tools/ioemu-remote/xenstore.c
@@ -13,13 +13,6 @@
#include "block_int.h"
#include <unistd.h>
-#ifndef CONFIG_STUBDOM
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#endif
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
#include <assert.h>
#include "exec-all.h"
@@ -586,8 +579,8 @@ void xenstore_parse_domain_config(int hv
#endif
- /* Set a watch for log-dirty requests from the migration tools */
- if (pasprintf(&buf, "/local/domain/0/device-model/%u/logdirty/next-active",
+ /* Set a watch for log-dirty commands from the migration tools */
+ if (pasprintf(&buf, "/local/domain/0/device-model/%u/logdirty/cmd",
domid) != -1) {
xs_watch(xsh, buf, "logdirty");
fprintf(logfile, "Watching %s\n", buf);
@@ -678,111 +671,44 @@ int xenstore_fd(void)
static void xenstore_process_logdirty_event(void)
{
char *act;
- static char *active_path = NULL;
- static char *next_active_path = NULL;
- static char *seg = NULL;
+ char *ret_path = NULL;
+ char *cmd_path = NULL;
unsigned int len;
- int i;
-
- if (!seg) {
- char *path = NULL, *key_ascii, key_terminated[17] = {0,};
- key_t key;
- int shmid;
-
- /* Find and map the shared memory segment for log-dirty bitmaps */
- if (pasprintf(&path,
- "/local/domain/0/device-model/%u/logdirty/key",
- domid) == -1) {
- fprintf(logfile, "Log-dirty: out of memory\n");
- exit(1);
- }
-
- key_ascii = xs_read(xsh, XBT_NULL, path, &len);
- free(path);
-
- if (!key_ascii)
- /* No key yet: wait for the next watch */
- return;
-#ifdef CONFIG_STUBDOM
- /* We pass the writes to hypervisor */
- seg = (void*)1;
-#else
- strncpy(key_terminated, key_ascii, 16);
- free(key_ascii);
- key = (key_t) strtoull(key_terminated, NULL, 16);
-
- /* Figure out how bit the log-dirty bitmaps are */
- logdirty_bitmap_size = xc_memory_op(xc_handle,
- XENMEM_maximum_gpfn, &domid) + 1;
- logdirty_bitmap_size = ((logdirty_bitmap_size + HOST_LONG_BITS - 1)
- / HOST_LONG_BITS); /* longs */
- logdirty_bitmap_size *= sizeof (unsigned long); /* bytes */
-
- /* Map the shared-memory segment */
- fprintf(logfile, "%s: key=%16.16llx size=%lu\n", __FUNCTION__,
- (unsigned long long)key, logdirty_bitmap_size);
- shmid = shmget(key, 2 * logdirty_bitmap_size, S_IRUSR|S_IWUSR);
- if (shmid == -1) {
- fprintf(logfile, "Log-dirty: shmget failed: segment %16.16llx "
- "(%s)\n", (unsigned long long)key, strerror(errno));
- exit(1);
- }
-
- seg = shmat(shmid, NULL, 0);
- if (seg == (void *)-1) {
- fprintf(logfile, "Log-dirty: shmat failed: segment %16.16llx "
- "(%s)\n", (unsigned long long)key, strerror(errno));
- exit(1);
- }
-
- fprintf(logfile, "Log-dirty: mapped segment at %p\n", seg);
-
- /* Double-check that the bitmaps are the size we expect */
- if (logdirty_bitmap_size != *(uint32_t *)seg) {
- fprintf(logfile, "Log-dirty: got %u, calc %lu\n",
- *(uint32_t *)seg, logdirty_bitmap_size);
- /* Stale key: wait for next watch */
- shmdt(seg);
- seg = NULL;
- return;
- }
-#endif
-
- /* Remember the paths for the next-active and active entries */
- if (pasprintf(&active_path,
- "/local/domain/0/device-model/%u/logdirty/active",
- domid) == -1) {
- fprintf(logfile, "Log-dirty: out of memory\n");
- exit(1);
- }
- if (pasprintf(&next_active_path,
- "/local/domain/0/device-model/%u/logdirty/next-active",
- domid) == -1) {
- fprintf(logfile, "Log-dirty: out of memory\n");
- exit(1);
- }
+ /* Remember the paths for the command and response entries */
+ if (pasprintf(&ret_path,
+ "/local/domain/0/device-model/%u/logdirty/ret",
+ domid) == -1) {
+ fprintf(logfile, "Log-dirty: out of memory\n");
+ exit(1);
+ }
+ if (pasprintf(&cmd_path,
+ "/local/domain/0/device-model/%u/logdirty/cmd",
+ domid) == -1) {
+ fprintf(logfile, "Log-dirty: out of memory\n");
+ exit(1);
}
- fprintf(logfile, "Triggered log-dirty buffer switch\n");
/* Read the required active buffer from the store */
- act = xs_read(xsh, XBT_NULL, next_active_path, &len);
+ act = xs_read(xsh, XBT_NULL, cmd_path, &len);
if (!act) {
- fprintf(logfile, "Log-dirty: can't read next-active\n");
- exit(1);
+ fprintf(logfile, "Log-dirty: no command yet.\n");
+ return;
}
+ fprintf(logfile, "Log-dirty command %s\n", act);
- /* Switch buffers */
- i = act[0] - '0';
- if (i != 0 && i != 1) {
- fprintf(logfile, "Log-dirty: bad next-active entry: %s\n", act);
+ if (!strcmp(act, "enable")) {
+ xen_logdirty_enable = 1;
+ } else if (!strcmp(act, "disable")) {
+ xen_logdirty_enable = 0;
+ } else {
+ fprintf(logfile, "Log-dirty: bad log-dirty command: %s\n", act);
exit(1);
}
- logdirty_bitmap = (unsigned long *)(seg + i * logdirty_bitmap_size);
- /* Ack that we've switched */
- xs_write(xsh, XBT_NULL, active_path, act, len);
+ /* Ack that we've service the command */
+ xs_write(xsh, XBT_NULL, ret_path, act, len);
free(act);
}
[-- Attachment #3: hvm_log_dirty_fix_tools.patch --]
[-- Type: application/octet-stream, Size: 12382 bytes --]
Index: hv/tools/libxc/ia64/xc_ia64_linux_save.c
===================================================================
--- hv.orig/tools/libxc/ia64/xc_ia64_linux_save.c
+++ hv/tools/libxc/ia64/xc_ia64_linux_save.c
@@ -382,8 +382,7 @@ out:
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;
@@ -424,11 +423,6 @@ xc_domain_save(int xc_handle, int io_fd,
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;
/* Unsigned int was used before. To keep file format compatibility. */
@@ -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);
Index: hv/tools/libxc/xc_domain_save.c
===================================================================
--- hv.orig/tools/libxc/xc_domain_save.c
+++ hv/tools/libxc/xc_domain_save.c
@@ -39,11 +39,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. */
Index: hv/tools/libxc/xenguest.h
===================================================================
--- hv.orig/tools/libxc/xenguest.h
+++ hv/tools/libxc/xenguest.h
@@ -26,8 +26,7 @@
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 */
/**
Index: hv/tools/xcutils/xc_save.c
===================================================================
--- hv.orig/tools/xcutils/xc_save.c
+++ hv/tools/xcutils/xc_save.c
@@ -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)
+static void switch_qemu_logdirty(int domid, unsigned int enable)
{
- char digit = '0' + next_active;
+ 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");
+ 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);
- qemu_flip_buffer(domid, 0);
+ 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);
[-- Attachment #4: Type: text/plain, Size: 138 bytes --]
_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel
reply other threads:[~2009-09-04 9:01 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=4AA0D753.8070005@intel.com \
--to=edwin.zhai@intel.com \
--cc=Ian.Jackson@eu.citrix.com \
--cc=keir.fraser@eu.citrix.com \
--cc=stefano.stabellini@eu.citrix.com \
--cc=xen-devel@lists.xensource.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.