[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


 


Rackspace

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