[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] save/restore race
On Tue, Jan 23, 2007 at 11:38:29PM -0000, Ian Pratt wrote: > We should make xc_linux_save cope more gracefully with > arch.pfn_to_mfn_frame_list_list being NULL, have xc_linux_save zero the > field in shared_info before writing it out (its an MFN and not valid > anyhow), and then move the field's re-initialisation a little later in > the post_suspend function to close the race. I've done some testing with the below, and it seems to do the trick. regards john # HG changeset patch # User john.levon@xxxxxxx # Date 1169600022 28800 # Node ID 3121e0cb7be68fa46c59f61422f05adc03ec5a5e # Parent a75413c0072fa5b892bd8b6a05c1f1d3435bb093 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. Signed-off-by: John Levon <john.levon@xxxxxxx> diff --git a/tools/libxc/xc_linux_save.c b/tools/libxc/xc_linux_save.c --- a/tools/libxc/xc_linux_save.c +++ b/tools/libxc/xc_linux_save.c @@ -403,6 +403,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 = 3000; + 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 @@ -663,14 +690,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, @@ -1169,8 +1193,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-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |