[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] [HVM] Control qemu's state-save via xenstore, instead of SIGUSR1
# HG changeset patch # User Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx> # Date 1185285136 -3600 # Node ID c585f993385c9dd6f61e27a9c6622adc8a8e50b1 # Parent 531b8ccda9732e521ea96b4d0a6b6d58b8981149 [HVM] Control qemu's state-save via xenstore, instead of SIGUSR1 This lets us verify that qemu has indeed stopped processing before we start saving guest memory. Also allow qemu to continue processing after the save has happened, instead of exiting immediately. Signed-off-by: Tim Deegan <Tim.Deegan@xxxxxxxxxxxxx> --- tools/ioemu/hw/cirrus_vga.c | 2 - tools/ioemu/target-i386-dm/helper2.c | 42 ++++++++++++++++------- tools/ioemu/vl.c | 33 +++--------------- tools/ioemu/vl.h | 1 tools/ioemu/xenstore.c | 57 ++++++++++++++++++++++++++++++++ tools/python/xen/xend/XendCheckpoint.py | 6 --- tools/python/xen/xend/XendDomainInfo.py | 5 ++ tools/python/xen/xend/image.py | 42 ++++++++++++++++++++--- 8 files changed, 135 insertions(+), 53 deletions(-) diff -r 531b8ccda973 -r c585f993385c tools/ioemu/hw/cirrus_vga.c --- a/tools/ioemu/hw/cirrus_vga.c Tue Jul 24 11:10:08 2007 +0100 +++ b/tools/ioemu/hw/cirrus_vga.c Tue Jul 24 14:52:16 2007 +0100 @@ -3096,8 +3096,6 @@ static void cirrus_vga_save(QEMUFile *f, qemu_put_be64s(f, (uint64_t*)&s->cirrus_lfb_addr); qemu_put_be64s(f, (uint64_t*)&s->cirrus_lfb_end); qemu_put_buffer(f, s->vram_ptr, VGA_RAM_SIZE); - if (vga_acc) - cirrus_stop_acc(s); } static int cirrus_vga_load(QEMUFile *f, void *opaque, int version_id) diff -r 531b8ccda973 -r c585f993385c tools/ioemu/target-i386-dm/helper2.c --- a/tools/ioemu/target-i386-dm/helper2.c Tue Jul 24 11:10:08 2007 +0100 +++ b/tools/ioemu/target-i386-dm/helper2.c Tue Jul 24 14:52:16 2007 +0100 @@ -618,6 +618,7 @@ int main_loop(void) CPUState *env = cpu_single_env; int evtchn_fd = xc_evtchn_fd(xce_handle); char qemu_file[PATH_MAX]; + fd_set fds; buffered_io_timer = qemu_new_timer(rt_clock, handle_buffered_io, cpu_single_env); @@ -625,19 +626,34 @@ int main_loop(void) qemu_set_fd_handler(evtchn_fd, cpu_handle_ioreq, NULL, env); - while (!(vm_running && suspend_requested)) - /* Wait up to 10 msec. */ - main_loop_wait(10); - - fprintf(logfile, "device model received suspend signal!\n"); - - /* Pull all outstanding ioreqs through the system */ - handle_buffered_io(env); - main_loop_wait(1); /* For the select() on events */ - - /* Save the device state */ - snprintf(qemu_file, sizeof(qemu_file), "/var/lib/xen/qemu-save.%d", domid); - do_savevm(qemu_file); + xenstore_record_dm_state("running"); + while (1) { + while (!(vm_running && suspend_requested)) + /* Wait up to 10 msec. */ + main_loop_wait(10); + + xenstore_record_dm_state("paused"); + fprintf(logfile, "device model saving state\n"); + + /* Pull all outstanding ioreqs through the system */ + handle_buffered_io(env); + main_loop_wait(1); /* For the select() on events */ + + /* Save the device state */ + snprintf(qemu_file, sizeof(qemu_file), + "/var/lib/xen/qemu-save.%d", domid); + do_savevm(qemu_file); + + /* Wait to be allowed to continue */ + while (suspend_requested) { + FD_ZERO(&fds); + FD_SET(xenstore_fd(), &fds); + if (select(xenstore_fd() + 1, &fds, NULL, NULL, NULL) > 0) + xenstore_process_event(NULL); + } + + xenstore_record_dm_state("running"); + } return 0; } diff -r 531b8ccda973 -r c585f993385c tools/ioemu/vl.c --- a/tools/ioemu/vl.c Tue Jul 24 11:10:08 2007 +0100 +++ b/tools/ioemu/vl.c Tue Jul 24 14:52:16 2007 +0100 @@ -6856,15 +6856,6 @@ int set_mm_mapping(int xc_handle, uint32 return 0; } -void suspend(int sig) -{ - fprintf(logfile, "suspend sig handler called with requested=%d!\n", - suspend_requested); - if (sig != SIGUSR1) - fprintf(logfile, "suspend signal dismatch, get sig=%d!\n", sig); - suspend_requested = 1; -} - #if defined(MAPCACHE) #if defined(__i386__) @@ -7057,6 +7048,7 @@ int main(int argc, char **argv) xen_pfn_t *page_array; extern void *buffered_pio_page; #endif + sigset_t set; char qemu_dm_logfilename[128]; @@ -7982,24 +7974,11 @@ int main(int argc, char **argv) close(fd); } - /* register signal for the suspend request when save */ - { - struct sigaction act; - sigset_t set; - act.sa_handler = suspend; - act.sa_flags = SA_RESTART; - sigemptyset(&act.sa_mask); - - sigaction(SIGUSR1, &act, NULL); - - /* control panel mask some signals when spawn qemu, need unmask here*/ - sigemptyset(&set); - sigaddset(&set, SIGUSR1); - sigaddset(&set, SIGTERM); - if (sigprocmask(SIG_UNBLOCK, &set, NULL) == -1) - fprintf(stderr, "unblock signal fail, possible issue for HVM save!\n"); - - } + /* Unblock SIGTERM, which may have been blocked by the caller */ + sigemptyset(&set); + sigaddset(&set, SIGTERM); + if (sigprocmask(SIG_UNBLOCK, &set, NULL) == -1) + fprintf(stderr, "Failed to unblock SIGTERM\n"); main_loop(); quit_timers(); diff -r 531b8ccda973 -r c585f993385c tools/ioemu/vl.h --- a/tools/ioemu/vl.h Tue Jul 24 11:10:08 2007 +0100 +++ b/tools/ioemu/vl.h Tue Jul 24 14:52:16 2007 +0100 @@ -1456,6 +1456,7 @@ void xenstore_parse_domain_config(int do void xenstore_parse_domain_config(int domid); int xenstore_fd(void); void xenstore_process_event(void *opaque); +void xenstore_record_dm_state(char *state); void xenstore_check_new_media_present(int timeout); void xenstore_write_vncport(int vnc_display); int xenstore_read_vncpasswd(int domid); diff -r 531b8ccda973 -r c585f993385c tools/ioemu/xenstore.c --- a/tools/ioemu/xenstore.c Tue Jul 24 11:10:08 2007 +0100 +++ b/tools/ioemu/xenstore.c Tue Jul 24 14:52:16 2007 +0100 @@ -186,6 +186,12 @@ void xenstore_parse_domain_config(int do fprintf(logfile, "Watching %s\n", buf); } + /* Set a watch for suspend requests from the migration tools */ + if (pasprintf(&buf, + "/local/domain/0/device-model/%u/command", domid) != -1) { + xs_watch(xsh, buf, "dm-command"); + fprintf(logfile, "Watching %s\n", buf); + } out: free(type); @@ -310,6 +316,52 @@ void xenstore_process_logdirty_event(voi } +/* Accept state change commands from the control tools */ +static void xenstore_process_dm_command_event(void) +{ + char *path = NULL, *command = NULL; + unsigned int len; + extern int suspend_requested; + + if (pasprintf(&path, + "/local/domain/0/device-model/%u/command", domid) == -1) { + fprintf(logfile, "out of memory reading dm command\n"); + goto out; + } + command = xs_read(xsh, XBT_NULL, path, &len); + if (!command) + goto out; + + if (!strncmp(command, "save", len)) { + fprintf(logfile, "dm-command: pause and save state\n"); + suspend_requested = 1; + } else if (!strncmp(command, "continue", len)) { + fprintf(logfile, "dm-command: continue after state save\n"); + suspend_requested = 0; + } else { + fprintf(logfile, "dm-command: unknown command\"%*s\"\n", len, command); + } + + out: + free(path); + free(command); +} + +void xenstore_record_dm_state(char *state) +{ + char *path = NULL; + + if (pasprintf(&path, + "/local/domain/0/device-model/%u/state", domid) == -1) { + fprintf(logfile, "out of memory recording dm state\n"); + goto out; + } + if (!xs_write(xsh, XBT_NULL, path, state, strlen(state))) + fprintf(logfile, "error recording dm state\n"); + + out: + free(path); +} void xenstore_process_event(void *opaque) { @@ -322,6 +374,11 @@ void xenstore_process_event(void *opaque if (!strcmp(vec[XS_WATCH_TOKEN], "logdirty")) { xenstore_process_logdirty_event(); + goto out; + } + + if (!strcmp(vec[XS_WATCH_TOKEN], "dm-command")) { + xenstore_process_dm_command_event(); goto out; } diff -r 531b8ccda973 -r c585f993385c tools/python/xen/xend/XendCheckpoint.py --- a/tools/python/xen/xend/XendCheckpoint.py Tue Jul 24 11:10:08 2007 +0100 +++ b/tools/python/xen/xend/XendCheckpoint.py Tue Jul 24 14:52:16 2007 +0100 @@ -98,10 +98,6 @@ def save(fd, dominfo, network, live, dst log.info("Domain %d suspended.", dominfo.getDomid()) dominfo.migrateDevices(network, dst, DEV_MIGRATE_STEP3, domain_name) - #send signal to device model for save - if hvm: - log.info("release_devices for hvm domain") - dominfo._releaseDevices(True) tochild.write("done\n") tochild.flush() log.debug('Written done') @@ -139,7 +135,7 @@ def save(fd, dominfo, network, live, dst except Exception, exn: log.exception("Save failed on domain %s (%s).", domain_name, dominfo.getDomid()) - + dominfo.resumeDomain() log.debug("XendCheckpoint.save: resumeDomain") diff -r 531b8ccda973 -r c585f993385c tools/python/xen/xend/XendDomainInfo.py --- a/tools/python/xen/xend/XendDomainInfo.py Tue Jul 24 11:10:08 2007 +0100 +++ b/tools/python/xen/xend/XendDomainInfo.py Tue Jul 24 14:52:16 2007 +0100 @@ -1122,6 +1122,8 @@ class XendDomainInfo: self._clearRestart() if reason == 'suspend': + if self._stateGet() != DOM_STATE_SUSPENDED: + self.image.saveDeviceModel() self._stateSet(DOM_STATE_SUSPENDED) # Don't destroy the domain. XendCheckpoint will do # this once it has finished. However, stop watching @@ -1764,6 +1766,9 @@ class XendDomainInfo: ResumeDomain(self.domid) except: log.exception("XendDomainInfo.resume: xc.domain_resume failed on domain %s." % (str(self.domid))) + if self.is_hvm(): + self.image.resumeDeviceModel() + # # Channels for xenstore and console diff -r 531b8ccda973 -r c585f993385c tools/python/xen/xend/image.py --- a/tools/python/xen/xend/image.py Tue Jul 24 11:10:08 2007 +0100 +++ b/tools/python/xen/xend/image.py Tue Jul 24 14:52:16 2007 +0100 @@ -20,6 +20,7 @@ import os, string import os, string import re import math +import time import signal import xen.lowlevel.xc @@ -27,6 +28,7 @@ from xen.xend.XendError import VmError, from xen.xend.XendError import VmError, XendError, HVMRequired from xen.xend.XendLogging import log from xen.xend.XendOptions import instance as xenopts +from xen.xend.xenstore.xstransact import xstransact from xen.xend.xenstore.xswatch import xswatch from xen.xend import arch @@ -175,6 +177,14 @@ class ImageHandler: """Create device model for the domain (define in subclass if needed).""" pass + def saveDeviceModel(self): + """Save device model for the domain (define in subclass if needed).""" + pass + + def resumeDeviceModel(self): + """Unpause device model for the domain (define in subclass if needed).""" + pass + def destroy(self): """Extra cleanup on domain destroy (define in subclass if needed).""" pass @@ -443,17 +453,34 @@ class HVMImageHandler(ImageHandler): self.vm.storeDom("image/device-model-pid", self.pid) log.info("device model pid: %d", self.pid) + def saveDeviceModel(self): + # Signal the device model to pause itself and save its state + xstransact.Store("/local/domain/0/device-model/%i" + % self.vm.getDomid(), ('command', 'save')) + # Wait for confirmation. Could do this with a watch but we'd + # still end up spinning here waiting for the watch to fire. + state = '' + count = 0 + while state != 'paused': + state = xstransact.Read("/local/domain/0/device-model/%i/state" + % self.vm.getDomid()) + time.sleep(0.1) + count += 1 + if count > 100: + raise VmError('Timed out waiting for device model to save') + + def resumeDeviceModel(self): + # Signal the device model to resume activity after pausing to save. + xstransact.Store("/local/domain/0/device-model/%i" + % self.vm.getDomid(), ('command', 'continue')) + def recreate(self): self.pid = self.vm.gatherDom(('image/device-model-pid', int)) def destroy(self, suspend = False): - if self.pid: + if self.pid and not suspend: try: - sig = signal.SIGKILL - if suspend: - log.info("use sigusr1 to signal qemu %d", self.pid) - sig = signal.SIGUSR1 - os.kill(self.pid, sig) + os.kill(self.pid, signal.SIGKILL) except OSError, exn: log.exception(exn) try: @@ -464,6 +491,8 @@ class HVMImageHandler(ImageHandler): # but we can't wait for it because it's not our child. pass self.pid = None + state = xstransact.Remove("/local/domain/0/device-model/%i" + % self.vm.getDomid()) class IA64_HVM_ImageHandler(HVMImageHandler): @@ -506,6 +535,7 @@ class X86_HVM_ImageHandler(HVMImageHandl # were given (but the Xen minimum is for safety, not performance). return max(4 * (256 * self.vm.getVCpuCount() + 2 * (maxmem_kb / 1024)), shadow_mem_kb) + class X86_Linux_ImageHandler(LinuxImageHandler): _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |