[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] Close save-after-restore race.
# HG changeset patch # User john.levon@xxxxxxx # Date 1169607991 28800 # Node ID 73b88d158ec946beb01b9bca534dcc7aa89e8c3d # Parent bea505a697223f59eceb789ccbff7fd09bc14a7b Close save-after-restore race. Make xc_linux_save() wait for the frame_list_list MFN to be updated by the domain before trying to use it. Make Linux set the top-level MFN /after/ updating the other MFN lists. Signed-off-by: John Levon <john.levon@xxxxxxx> --- linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c | 4 - linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c | 4 - linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c | 5 - tools/libxc/xc_linux_save.c | 48 +++++++++++++---- 4 files changed, 45 insertions(+), 16 deletions(-) diff -r bea505a69722 -r 73b88d158ec9 linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c --- a/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c Tue Jan 23 15:58:05 2007 +0000 +++ b/linux-2.6-xen-sparse/arch/i386/kernel/setup-xen.c Tue Jan 23 19:06:31 2007 -0800 @@ -1736,8 +1736,6 @@ void __init setup_arch(char **cmdline_p) * frames that make up the p2m table. Used by save/restore */ pfn_to_mfn_frame_list_list = alloc_bootmem_low_pages(PAGE_SIZE); - HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list = - virt_to_mfn(pfn_to_mfn_frame_list_list); fpp = PAGE_SIZE/sizeof(unsigned long); for (i=0, j=0, k=-1; i< max_pfn; i+=fpp, j++) { @@ -1754,6 +1752,8 @@ void __init setup_arch(char **cmdline_p) virt_to_mfn(&phys_to_machine_mapping[i]); } HYPERVISOR_shared_info->arch.max_pfn = max_pfn; + HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list = + virt_to_mfn(pfn_to_mfn_frame_list_list); } /* diff -r bea505a69722 -r 73b88d158ec9 linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c --- a/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c Tue Jan 23 15:58:05 2007 +0000 +++ b/linux-2.6-xen-sparse/arch/x86_64/kernel/setup-xen.c Tue Jan 23 19:06:31 2007 -0800 @@ -817,8 +817,6 @@ void __init setup_arch(char **cmdline_p) * save/restore. */ pfn_to_mfn_frame_list_list = alloc_bootmem_pages(PAGE_SIZE); - HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list = - virt_to_mfn(pfn_to_mfn_frame_list_list); fpp = PAGE_SIZE/sizeof(unsigned long); for (i=0, j=0, k=-1; i< end_pfn; i+=fpp, j++) { @@ -835,6 +833,8 @@ void __init setup_arch(char **cmdline_p) virt_to_mfn(&phys_to_machine_mapping[i]); } HYPERVISOR_shared_info->arch.max_pfn = end_pfn; + HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list = + virt_to_mfn(pfn_to_mfn_frame_list_list); } } diff -r bea505a69722 -r 73b88d158ec9 linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c --- a/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c Tue Jan 23 15:58:05 2007 +0000 +++ b/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c Tue Jan 23 19:06:31 2007 -0800 @@ -105,9 +105,6 @@ static void post_suspend(int suspend_can memset(empty_zero_page, 0, PAGE_SIZE); - HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list = - virt_to_mfn(pfn_to_mfn_frame_list_list); - fpp = PAGE_SIZE/sizeof(unsigned long); for (i = 0, j = 0, k = -1; i < max_pfn; i += fpp, j++) { if ((j % fpp) == 0) { @@ -120,6 +117,8 @@ static void post_suspend(int suspend_can virt_to_mfn(&phys_to_machine_mapping[i]); } HYPERVISOR_shared_info->arch.max_pfn = max_pfn; + HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list_list = + virt_to_mfn(pfn_to_mfn_frame_list_list); } #else /* !(defined(__i386__) || defined(__x86_64__)) */ diff -r bea505a69722 -r 73b88d158ec9 tools/libxc/xc_linux_save.c --- a/tools/libxc/xc_linux_save.c Tue Jan 23 15:58:05 2007 +0000 +++ b/tools/libxc/xc_linux_save.c Tue Jan 23 19:06:31 2007 -0800 @@ -404,6 +404,33 @@ static int suspend_and_state(int (*suspe return -1; } +/* +** Map the top-level page of MFNs from the guest. The guest might not have +** finished resuming from a previous restore operation, so we wait a while for +** it to update the MFN to a reasonable value. +*/ +static void *map_frame_list_list(int xc_handle, uint32_t dom, + shared_info_t *shinfo) +{ + int count = 100; + void *p; + + while (count-- && shinfo->arch.pfn_to_mfn_frame_list_list == 0) + usleep(10000); + + if (shinfo->arch.pfn_to_mfn_frame_list_list == 0) { + ERROR("Timed out waiting for frame list updated."); + return NULL; + } + + p = xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ, + shinfo->arch.pfn_to_mfn_frame_list_list); + + if (p == NULL) + ERROR("Couldn't map p2m_frame_list_list (errno %d)", errno); + + return p; +} /* ** During transfer (or in the state file), all page-table pages must be @@ -669,14 +696,11 @@ int xc_linux_save(int xc_handle, int io_ max_pfn = live_shinfo->arch.max_pfn; - live_p2m_frame_list_list = - xc_map_foreign_range(xc_handle, dom, PAGE_SIZE, PROT_READ, - live_shinfo->arch.pfn_to_mfn_frame_list_list); - - if (!live_p2m_frame_list_list) { - ERROR("Couldn't map p2m_frame_list_list (errno %d)", errno); - goto out; - } + live_p2m_frame_list_list = map_frame_list_list(xc_handle, dom, + live_shinfo); + + if (!live_p2m_frame_list_list) + goto out; live_p2m_frame_list = xc_map_foreign_batch(xc_handle, dom, PROT_READ, @@ -1175,8 +1199,14 @@ int xc_linux_save(int xc_handle, int io_ ctxt.ctrlreg[3] = xen_pfn_to_cr3(mfn_to_pfn(xen_cr3_to_pfn(ctxt.ctrlreg[3]))); + /* + * Reset the MFN to be a known-invalid value. See map_frame_list_list(). + */ + memcpy(page, live_shinfo, PAGE_SIZE); + ((shared_info_t *)page)->arch.pfn_to_mfn_frame_list_list = 0; + if (!write_exact(io_fd, &ctxt, sizeof(ctxt)) || - !write_exact(io_fd, live_shinfo, PAGE_SIZE)) { + !write_exact(io_fd, page, PAGE_SIZE)) { ERROR("Error when writing to state file (1) (errno %d)", errno); goto out; } _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |