[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [RFC][PATCH 06/13] Kemari: Kemari receiver
This is an updated version of the following patch. Followed the changes in live migration code. http://lists.xensource.com/archives/html/xen-devel/2009-03/msg00375.html Signed-off-by: Yoshisato Yanagisawa <yanagisawa.yoshisato@xxxxxxxxxxxxx> Signed-off-by: Yoshi Tamura <tamura.yoshiaki@xxxxxxxxxxxxx> --- tools/libxc/xc_dom_kemari_restore.c | 727 ++++++++++++++++++++++++++++++++++++ tools/xcutils/xc_kemari_restore.c | 88 ++++ 2 files changed, 815 insertions(+) diff -r b249f3e979a5 -r cf6a910e3663 tools/xcutils/xc_kemari_restore.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/xcutils/xc_kemari_restore.c Wed Mar 11 18:03:47 2009 +0900 @@ -0,0 +1,88 @@ +/* + * xc_kemari_restore.c + * + * Restore the state of a running Linux session. + * + * Copyright (c) 2008 Nippon Telegraph and Telephone Corporation. + * + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file "COPYING" in the main directory of + * this archive for more details. + * + * This source code is based on xc_restore.c. + * + * Copyright (C) 2005 by Christian Limpach + * + */ +#include <sys/socket.h> +#include <netinet/in.h> +#include <netinet/tcp.h> + +#include <err.h> +#include <stdlib.h> +#include <stdint.h> +#include <stdio.h> +#include <signal.h> +#include <unistd.h> + +#include <xenctrl.h> +#include <xenguest.h> +#include <xc_private.h> + +static int io_fd; + +static void close_handler(int sig_type) +{ + /* let xc_kemari_restore move build process */ + close(io_fd); +} + +int +main(int argc, char **argv) +{ + unsigned int domid, store_evtchn, console_evtchn; + unsigned int hvm, pae, apic; + int xc_fd, ret, one = 1; + unsigned long store_mfn, console_mfn; + struct sigaction act; + + if ( argc != 8 ) + errx(1, "usage: %s iofd domid store_evtchn " + "console_evtchn hvm pae apic", argv[0]); + + xc_fd = xc_interface_open(); + if ( xc_fd < 0 ) + errx(1, "failed to open control interface"); + + io_fd = atoi(argv[1]); + domid = atoi(argv[2]); + store_evtchn = atoi(argv[3]); + console_evtchn = atoi(argv[4]); + hvm = atoi(argv[5]); + pae = atoi(argv[6]); + apic = atoi(argv[7]); + + act.sa_handler = close_handler; + sigemptyset(&act.sa_mask); + act.sa_flags = 0; + sigaction(SIGHUP, &act, 0); + sigaction(SIGINT, &act, 0); + + if ( setsockopt(io_fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)) < 0 ) + DPRINTF("failed to set TCP_NODELAY"); + + ret = xc_kemari_restore(xc_fd, io_fd, domid, store_evtchn, &store_mfn, + console_evtchn, &console_mfn, hvm, pae); + + if ( ret == 0 ) + { + printf("store-mfn %li\n", store_mfn); + if ( !hvm ) + printf("console-mfn %li\n", console_mfn); + fflush(stdout); + } + + xc_interface_close(xc_fd); + + return ret; +} diff -r b249f3e979a5 -r cf6a910e3663 tools/libxc/xc_dom_kemari_restore.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tools/libxc/xc_dom_kemari_restore.c Wed Mar 11 18:03:47 2009 +0900 @@ -0,0 +1,727 @@ +/****************************************************************************** + * xc_dom_kemari_restore.c + * + * Restore the state of a guest session for kemari. + * + * Copyright (c) 2008 Nippon Telegraph and Telephone Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., 59 Temple + * Place - Suite 330, Boston, MA 02111-1307 USA. + * + * This source code is based on xc_domain_restore.c. + * + * Copyright (c) 2003, K A Fraser. + * Copyright (c) 2006, Intel Corporation + * Copyright (c) 2007, XenSource Inc. + */ + +#include <stdlib.h> +#include <unistd.h> + +#include "xg_private.h" +#include "xg_save_restore.h" +#include "xc_dom.h" + +#include <xen/hvm/ioreq.h> +#include <xen/hvm/params.h> + +/* number of pfns this guest has (i.e. number of entries in the P2M) */ +static unsigned long p2m_size; + +/* number of 'in use' pfns in the guest (i.e. #P2M entries with a valid mfn) */ +static unsigned long nr_pfns; + +/* A table mapping each PFN to its new MFN. */ +static xen_pfn_t *p2m = NULL; + +/* A table of P2M mappings in the current region */ +static xen_pfn_t *p2m_batch = NULL; + +int xc_kemari_restore(int xc_handle, int io_fd, uint32_t dom, + unsigned int store_evtchn, unsigned long *store_mfn, + unsigned int console_evtchn, unsigned long *console_mfn, + unsigned int hvm, unsigned int pae) +{ + int rc = 1, frc, i, n, m; + unsigned long mfn, pfn; + unsigned int prev_pc, this_pc; + + /* The new domain's shared-info frame number. */ + unsigned long shared_info_frame; + + /* A table containing the type of each PFN (/not/ MFN!). */ + unsigned long *pfn_type = NULL; + + /* A table of MFNs to map in the current region */ + xen_pfn_t *region_mfn = NULL; + + /* Types of the pfns in the current region */ + unsigned long region_pfn_type[MAX_BATCH_SIZE]; + + /* Our mapping of the current region (batch) */ + char *region_base; + + /* Magic frames in HVM guests: ioreqs and xenstore comms. */ + uint64_t magic_pfns[3]; /* ioreq_pfn, bufioreq_pfn, store_pfn */ + + /* Temporary buffered memory space until all pages are read. */ + char *tmp_region = NULL; + + /* if true, go into transaction mode */ + int kemari_transaction_mode = 0; + + /* index for grant table */ + int grant_idx = 0; + + /* Callback IRQ */ + uint64_t callback_irq = 0; + + /* active and non-active id of flip buffer */ + int info_active = 0, info_non_active = 1; + + /* Buffer for holding HVM context */ + uint8_t *hvm_buf[2] = {NULL,NULL}; + uint32_t hvm_buf_size = 0; + + /* Buffer for qemu image */ + uint8_t *qemu_image[2] = {NULL,NULL}; + uint32_t qemu_image_size[2] = {0,0}; + uint32_t qemu_buff_size = 0; + + /* Buffer for the EPT identity PT location. */ + uint64_t ident_pt[2] = {0,0}; + /* Buffer for the VM86 TSS. */ + uint64_t vm86_tss[2] = {0,0}; + + if ( !hvm ) { + ERROR("Kemari only works on HVM domain."); + goto out; + } + + /* For info only */ + nr_pfns = 0; + + if ( read_exact(io_fd, &p2m_size, sizeof(unsigned long)) ) + { + ERROR("read: p2m_size"); + goto out; + } + DPRINTF("xc_kemari_restore start: p2m_size = %lx\n", p2m_size); + + /* We want zeroed memory so use calloc rather than malloc. */ + p2m = calloc(p2m_size, sizeof(xen_pfn_t)); + pfn_type = calloc(p2m_size, sizeof(unsigned long)); + + region_mfn = xg_memalign(PAGE_SIZE, ROUNDUP( + MAX_BATCH_SIZE * sizeof(xen_pfn_t), PAGE_SHIFT)); + p2m_batch = xg_memalign(PAGE_SIZE, ROUNDUP( + MAX_BATCH_SIZE * sizeof(xen_pfn_t), PAGE_SHIFT)); + + /* use aligned page for speed up memmove(3) */ + tmp_region = xg_memalign(PAGE_SIZE, PAGE_SIZE * MAX_BATCH_SIZE); + + if ( (p2m == NULL) || (pfn_type == NULL) || + (region_mfn == NULL) || (p2m_batch == NULL) || + (tmp_region == NULL) ) + { + ERROR("memory alloc failed"); + errno = ENOMEM; + goto out; + } + + memset(region_mfn, 0, + ROUNDUP(MAX_BATCH_SIZE * sizeof(xen_pfn_t), PAGE_SHIFT)); + memset(p2m_batch, 0, + ROUNDUP(MAX_BATCH_SIZE * sizeof(xen_pfn_t), PAGE_SHIFT)); + memset(tmp_region, 0, PAGE_SIZE * MAX_BATCH_SIZE); + + if ( lock_pages(region_mfn, sizeof(xen_pfn_t) * MAX_BATCH_SIZE) ) + { + ERROR("Could not lock region_mfn"); + goto out; + } + + if ( lock_pages(p2m_batch, sizeof(xen_pfn_t) * MAX_BATCH_SIZE) ) + { + ERROR("Could not lock p2m_batch"); + goto out; + } + + if ( lock_pages(tmp_region, sizeof(xen_pfn_t) * MAX_BATCH_SIZE) ) + { + ERROR("Could not lock region_mfn"); + goto out; + } + + /* Get the domain's shared-info frame. */ + if ( read_exact(io_fd, &shared_info_frame, sizeof(unsigned long))) + { + ERROR("Error when reading shared_info_frame"); + goto out; + } + DPRINTF("xc_kemari_restore: shared_info_frame: %lx\n", shared_info_frame); + + /* read HVM-specific parameters */ + if ( read_exact(io_fd, magic_pfns, sizeof(magic_pfns)) ) + { + ERROR("error reading magic page addresses"); + goto out; + } + + if (read_exact(io_fd, &callback_irq, sizeof(callback_irq))) + { + ERROR("error reading magic page addresses"); + goto out; + } + + /* Mark all PFNs as invalid; we allocate on demand */ + for ( pfn = 0; pfn < p2m_size; pfn++ ) + p2m[pfn] = INVALID_P2M_ENTRY; + + /* + * Now simply read each saved frame into its new machine frame. + * We uncanonicalise page tables as we go. + */ + prev_pc = 0; + + n = m = 0; + for ( ; ; ) + { + int num_pages; + int nr_mfns; + + num_pages = 0; + for ( ; ; ) { + int j; + + this_pc = (n * 100) / p2m_size; + if ( (this_pc - prev_pc) >= 5 ) + { + PPRINTF("\b\b\b\b%3d%%", this_pc); + prev_pc = this_pc; + } + + if ( read_exact(io_fd, &j, sizeof(int)) ) + { + ERROR("Error when reading batch size"); + goto build; + } + + PPRINTF("batch %d\n",j); + + if (j == -1) + { + uint32_t rec_size; + if ( read_exact(io_fd, &rec_size, sizeof(uint32_t)) ) + { + ERROR("error read the qemu file size"); + goto build; + } + + if (qemu_buff_size < rec_size) + { + qemu_buff_size = rec_size; + qemu_image[0] = realloc(qemu_image[0], qemu_buff_size); + qemu_image[1] = realloc(qemu_image[1], qemu_buff_size); + if ((qemu_image[0] == NULL) || (qemu_image[1] == NULL)) + { + ERROR("error allocate memory"); + goto out; + } + } + + qemu_image_size[info_non_active] = rec_size; + if ( read_exact(io_fd, qemu_image[info_non_active], + qemu_image_size[info_non_active]) ) + { + ERROR("error read the qemu image file"); + goto build; + } + + continue; + } + + if ( j == -3 ) + { + /* Skip padding 4 bytes then read the EPT identity PT location. */ + if ( read_exact(io_fd, &ident_pt[info_non_active], + sizeof(uint32_t)) || + read_exact(io_fd, &ident_pt[info_non_active], + sizeof(uint64_t)) ) + { + ERROR("error read the address of the EPT identity map"); + goto build; + } + + continue; + } + + if ( j == -4 ) + { + /* Skip padding 4 bytes then read the vm86 TSS location. */ + if ( read_exact(io_fd, &vm86_tss[info_non_active], + sizeof(uint32_t)) || + read_exact(io_fd, &vm86_tss[info_non_active], + sizeof(uint64_t)) ) + { + ERROR("error read the address of the vm86 TSS"); + goto out; + } + + continue; + } + + if ( j == 0 ) + break; /* our work here is done */ + + /* j > 0: Read pages here */ + if ( (j > MAX_BATCH_SIZE) || (j < 0) ) + { + ERROR("Max batch size exceeded. Giving up. %d", j); + goto out; + } + + if ( read_exact(io_fd, region_pfn_type, j*sizeof(unsigned long)) ) + { + ERROR("Error when reading region pfn types"); + goto build; + } + + if (kemari_transaction_mode) { + if (num_pages != 0) + { + ERROR("Sorry! You cannot execute page-send-phase " + "twice. We will fix this bug in the future."); + DPRINTF("Sorry\n"); + goto out; + } + num_pages = j; + + /* Since there are not invalid pages, we don't need to skip */ + if ( read_exact(io_fd, tmp_region, PAGE_SIZE * num_pages) ) + { + ERROR("Error when reading page at kemari transaction mode"); + goto build; + } + + continue; + } + + /* Normal mode */ + /* First pass for this batch: work out how much memory to alloc */ + nr_mfns = 0; + for ( i = 0; i < j; i++ ) + { + unsigned long pfn, pagetype; + pfn = region_pfn_type[i] & ~XEN_DOMCTL_PFINFO_LTAB_MASK; + pagetype = region_pfn_type[i] & XEN_DOMCTL_PFINFO_LTAB_MASK; + + if ( (pagetype != XEN_DOMCTL_PFINFO_XTAB) && + (p2m[pfn] == INVALID_P2M_ENTRY) ) + { + /* Have a live PFN which hasn't had an MFN allocated */ + p2m_batch[nr_mfns++] = pfn; + p2m[pfn]--; + } + } + + /* Now allocate a bunch of mfns for this batch */ + if ( nr_mfns && + (xc_domain_memory_populate_physmap(xc_handle, dom, nr_mfns, 0, + 0, p2m_batch) != 0) ) + { + ERROR("Failed to allocate memory for batch.! %d\n", nr_mfns); + for (i = 0; i < nr_mfns; i++) + DPRINTF("p2m_batch[%d] = %lx\n", i, p2m_batch[i]); + errno = ENOMEM; + goto out; + } + + /* set special pages */ + { + struct xen_add_to_physmap xatp; + for (i = 0; i < nr_mfns; i++) + if (p2m_batch[i] == shared_info_frame) { + xatp.domid = dom; + xatp.space = XENMAPSPACE_shared_info; + xatp.idx = 0; + xatp.gpfn = shared_info_frame; + DPRINTF("setting up shared_info_frame: %lu\n", + shared_info_frame); + if (xc_memory_op(xc_handle, XENMEM_add_to_physmap, &xatp) + != 0) + { + ERROR("Error setting shared_info_frame"); + goto out; + } + } else if ((p2m_batch[i] > shared_info_frame) + && (p2m_batch[i] <= shared_info_frame + 32)) { + xatp.domid = dom; + xatp.space = XENMAPSPACE_grant_table; + xatp.idx = grant_idx; + xatp.gpfn = p2m_batch[i]; + DPRINTF("grant[%d]: %lu\n", grant_idx, xatp.gpfn); + if (xc_memory_op(xc_handle, XENMEM_add_to_physmap, + &xatp) != 0) + { + PERROR("Cannot map grant table pfn: %lu", xatp.gpfn); + goto out; + } + grant_idx++; + } + } + + /* Second pass for this batch: update p2m[] and region_mfn[] */ + nr_mfns = 0; + for ( i = 0; i < j; i++ ) + { + unsigned long pfn, pagetype; + pfn = region_pfn_type[i] & ~XEN_DOMCTL_PFINFO_LTAB_MASK; + pagetype = region_pfn_type[i] & XEN_DOMCTL_PFINFO_LTAB_MASK; + + if ( pagetype == XEN_DOMCTL_PFINFO_XTAB ) + region_mfn[i] = ~0UL; /* map will fail but we don't care */ + else + { + if ( p2m[pfn] == (INVALID_P2M_ENTRY-1) ) + { + /* We just allocated a new mfn above; update p2m */ + p2m[pfn] = p2m_batch[nr_mfns++]; + nr_pfns++; + } + + /* setup region_mfn[] for batch map. + * For HVM guests, this interface takes PFNs, not MFNs */ + region_mfn[i] = pfn; + } + } + + /* Map relevant mfns */ + region_base = xc_map_foreign_batch( + xc_handle, dom, PROT_WRITE, region_mfn, j); + + if ( region_base == NULL ) + { + ERROR("map batch failed"); + goto out; + } + + for ( i = 0; i < j; i++ ) + { + void *page; + unsigned long pagetype; + pfn = region_pfn_type[i] & ~XEN_DOMCTL_PFINFO_LTAB_MASK; + pagetype = region_pfn_type[i] & XEN_DOMCTL_PFINFO_LTAB_MASK; + + if ( pagetype == XEN_DOMCTL_PFINFO_XTAB ) + /* a bogus/unmapped page: skip it */ + continue; + + if ( pfn > p2m_size ) + { + ERROR("pfn out of range"); + goto out; + } + + pfn_type[pfn] = pagetype; + + mfn = p2m[pfn]; + + page = region_base + i*PAGE_SIZE; + + if ( read_exact(io_fd, page, PAGE_SIZE) ) + { + ERROR("Error when reading page (type was %lx)", pagetype); + goto out; + } + + pagetype &= XEN_DOMCTL_PFINFO_LTABTYPE_MASK; + + if ( (pagetype >= XEN_DOMCTL_PFINFO_L1TAB) && + (pagetype <= XEN_DOMCTL_PFINFO_L4TAB) ) + { + DPRINTF("uncanonicalize_pagetable pagetype = %lx pfn = %lu\n", pagetype, pfn); + } + else if ( pagetype != XEN_DOMCTL_PFINFO_NOTAB ) + { + ERROR("Bogus page type %lx page table is out of range: " + "i=%d p2m_size=%lu", pagetype, i, p2m_size); + goto out; + + } + } /* end of 'batch' for loop */ + + munmap(region_base, j*PAGE_SIZE); + n+= j; /* crude stats */ + } + + /* HVM specific */ + { + uint32_t rec_len; + + /* Read HVM context */ + if ( read_exact(io_fd, &rec_len, sizeof(uint32_t)) ) + { + ERROR("error read hvm context size!\n"); + goto build; + } + + if (rec_len != hvm_buf_size) + { + if (hvm_buf[info_non_active] == NULL) + { /* hvm_buf will be reused. */ + hvm_buf_size = rec_len; + hvm_buf[0] = malloc(hvm_buf_size); + hvm_buf[1] = malloc(hvm_buf_size); + if ( hvm_buf[0] == NULL || hvm_buf[1] == NULL) + { + ERROR("memory alloc for hvm context buffer failed"); + errno = ENOMEM; + goto out; + } + } else { + ERROR("Sorry, we did not thought about HVM image size " + "change."); + goto out; + } + } + + if ( read_exact(io_fd, hvm_buf[info_non_active], hvm_buf_size) ) + { + ERROR("error loading the HVM context"); + goto build; + } + } + + /* + * Commit! + */ + { + int zero = 0; + + if ( write_exact(io_fd, &zero, sizeof(int))) { + ERROR("Error when replying to sender (errno %d)", errno); + goto out; + } + } + + /* commit pages */ + if (kemari_transaction_mode && num_pages > 0) + { + int nr_mfns; + /* First pass for this batch: work out how much memory to alloc */ + nr_mfns = 0; + for ( i = 0; i < num_pages; i++ ) + { + unsigned long pfn, pagetype; + pfn = region_pfn_type[i] & ~XEN_DOMCTL_PFINFO_LTAB_MASK; + pagetype = region_pfn_type[i] & XEN_DOMCTL_PFINFO_LTAB_MASK; + + if ( (pagetype != XEN_DOMCTL_PFINFO_XTAB) && + (p2m[pfn] == INVALID_P2M_ENTRY) ) + { + /* Have a live PFN which hasn't had an MFN allocated */ + p2m_batch[nr_mfns++] = pfn; + p2m[pfn]--; + DPRINTF("Cannot be occur!!! no map for pfn: %lu\n", pfn); + } + } + + /* Now allocate a bunch of mfns for this batch */ + if ( nr_mfns && + (xc_domain_memory_populate_physmap(xc_handle, dom, nr_mfns, 0, + 0, p2m_batch) != 0) ) + { + ERROR("Failed to allocate memory for batch.!\n"); + errno = ENOMEM; + goto out; + } + + /* Second pass for this batch: update p2m[] and region_mfn[] */ + nr_mfns = 0; + for ( i = 0; i < num_pages; i++ ) + { + unsigned long pfn, pagetype; + pfn = region_pfn_type[i] & ~XEN_DOMCTL_PFINFO_LTAB_MASK; + pagetype = region_pfn_type[i] & XEN_DOMCTL_PFINFO_LTAB_MASK; + + if ( pagetype == XEN_DOMCTL_PFINFO_XTAB ) { + DPRINTF("pfn %lu = XEN_DOMCTL_PFINFO_XTAB\n", pfn); + region_mfn[i] = ~0UL; /* map will fail but we don't care */ + } + else + { + if ( p2m[pfn] == (INVALID_P2M_ENTRY-1) ) + { + /* We just allocated a new mfn above; update p2m */ + p2m[pfn] = p2m_batch[nr_mfns++]; + nr_pfns++; + } + + /* setup region_mfn[] for batch map. + * For HVM guests, this interface takes PFNs, not MFNs */ + region_mfn[i] = pfn; + } + } + + /* Map relevant mfns */ + region_base = xc_map_foreign_batch( + xc_handle, dom, PROT_WRITE, region_mfn, num_pages); + + if ( region_base == NULL ) + { + ERROR("map batch failed"); + goto out; + } + + for ( i = 0; i < num_pages; i++ ) + { + void *page, *spage; + unsigned long pagetype; + + pfn = region_pfn_type[i] & ~XEN_DOMCTL_PFINFO_LTAB_MASK; + pagetype = region_pfn_type[i] & XEN_DOMCTL_PFINFO_LTAB_MASK; + + if ( pfn > p2m_size ) + { + ERROR("pfn out of range"); + goto out; + } + + pfn_type[pfn] = pagetype; + + mfn = p2m[pfn]; + + page = region_base + i*PAGE_SIZE; + spage = tmp_region + i*PAGE_SIZE; + + if ( !memmove(page, spage, PAGE_SIZE) ) + { + ERROR("Error when reading page (type was %lx)", pagetype); + goto out; + } + + } /* end of 'batch' for loop */ + + munmap(region_base, num_pages*PAGE_SIZE); + num_pages = 0; /* clear num_pages for refill */ + } + + /* commit HVM specific status */ + info_active = info_non_active; + info_non_active = info_active ? 0 : 1; + + /* HVM success! */ + rc = 0; + kemari_transaction_mode = 1; + } + + build: /* building HVM context */ + DPRINTF("building status %d\n", rc); + if (rc == 0) + { + FILE *qemu_fp; + char path[128]; + + /* set the EPT identity PT location */ + xc_set_hvm_param(xc_handle, dom, HVM_PARAM_IDENT_PT, + ident_pt[info_active]); + xc_set_hvm_param(xc_handle, dom, HVM_PARAM_VM86_TSS, + vm86_tss[info_active]); + + if ( (frc = xc_set_hvm_param(xc_handle, dom, + HVM_PARAM_IOREQ_PFN, magic_pfns[0])) + || (frc = xc_set_hvm_param(xc_handle, dom, + HVM_PARAM_BUFIOREQ_PFN, magic_pfns[1])) + || (frc = xc_set_hvm_param(xc_handle, dom, + HVM_PARAM_STORE_PFN, magic_pfns[2])) + || (frc = xc_set_hvm_param(xc_handle, dom, + HVM_PARAM_PAE_ENABLED, pae)) + || (frc = xc_set_hvm_param(xc_handle, dom, + HVM_PARAM_STORE_EVTCHN, + store_evtchn)) + || (frc = xc_set_hvm_param(xc_handle, dom, + HVM_PARAM_CALLBACK_IRQ, + callback_irq)) ) + { + ERROR("error setting HVM params: %i", frc); + rc = 3; + goto out; + } + *store_mfn = magic_pfns[2]; + DPRINTF("kemari_restore: magic_pfns 0: %lld, 1: %lld, 2: %lld\n", + magic_pfns[0], magic_pfns[1], magic_pfns[2]); + + frc = xc_domain_hvm_setcontext(xc_handle, dom, hvm_buf[info_active], + hvm_buf_size); + if ( frc ) + { + ERROR("error setting the HVM context"); + rc = 4; + goto out; + } + + if (qemu_image_size[info_active] == 0) + { + ERROR("Did not received QEMU image"); + rc = 5; + goto out; + } + snprintf(path, sizeof(path), "/var/lib/xen/qemu-save.%d", dom); + if ((qemu_fp = fopen(path, "w")) == NULL) + { + ERROR("error opening QEMU image"); + rc = 5; + goto out; + } + if (fwrite(qemu_image[info_active], qemu_image_size[info_active], + 1, qemu_fp) != 1) + { + ERROR("error writing QEMU image"); + rc = 5; + goto out; + } + fclose(qemu_fp); + } + + out: + if ( (rc != 0) && (dom != 0) ) + xc_domain_destroy(xc_handle, dom); + free(p2m); + free(pfn_type); + free(region_mfn); + free(p2m_batch); + free(tmp_region); + free(hvm_buf[0]); + free(hvm_buf[1]); + free(qemu_image[0]); + free(qemu_image[1]); + + /* discard cache for save file */ + discard_file_cache(io_fd, 1 /*flush*/); + + DPRINTF("Restore exit with rc=%d\n", rc); + + return rc; +} + +/* + * Local variables: + * mode: C + * c-set-style: "BSD" + * c-basic-offset: 4 + * tab-width: 4 + * indent-tabs-mode: nil + * End: + */ + _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |