[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 3/4] libxc: stop migration in case of p2m list structural changes
On 11/12/15 16:20, Andrew Cooper wrote: > On 11/12/15 11:31, Juergen Gross wrote: >> With support of the virtual mapped linear p2m list for migration it is >> now possible to detect structural changes of the p2m list which before >> would either lead to a crashing or otherwise wrong behaving domU. >> >> A guest supporting the linear p2m list will increment the >> p2m_generation counter located in the shared info page before and after >> each modification of a mapping related to the p2m list. A change of >> that counter can be detected by the tools and reacted upon. >> >> As such a change should occur only very rarely once the domU is up the >> most simple reaction is to cancel migration in such an event. >> >> Signed-off-by: Juergen Gross <jgross@xxxxxxxx> >> --- >> tools/libxc/xc_sr_common.h | 11 ++++++++++ >> tools/libxc/xc_sr_save.c | 4 ++++ >> tools/libxc/xc_sr_save_x86_hvm.c | 7 +++++++ >> tools/libxc/xc_sr_save_x86_pv.c | 44 >> ++++++++++++++++++++++++++++++++++++++++ >> 4 files changed, 66 insertions(+) >> >> diff --git a/tools/libxc/xc_sr_common.h b/tools/libxc/xc_sr_common.h >> index 9aecde2..bfb9602 100644 >> --- a/tools/libxc/xc_sr_common.h >> +++ b/tools/libxc/xc_sr_common.h >> @@ -83,6 +83,14 @@ struct xc_sr_save_ops >> int (*end_of_checkpoint)(struct xc_sr_context *ctx); >> >> /** >> + * Check whether new iteration can be started. This is called before >> each >> + * iteration to check whether all criteria for the migration are still >> + * met. If that's not the case either migration is cancelled via a bad >> rc >> + * or the situation is handled, e.g. by sending appropriate records. >> + */ >> + int (*check_iteration)(struct xc_sr_context *ctx); >> + > > This is slightly ambiguous, especially with the not-so-different > differences between live migration and remus checkpoints. > > I would be tempted to name it check_vm_state() and document simply that > it is called periodically, to allow for fixup (or abort) for guest state > which may have changed while the VM was running. Yes, this is better. > On the remus side, it needs to be called between start_of_checkpoint() > and send_memory_***() in save(), as the guest gets to run between the > checkpoints. Okay. > >> + /** >> * Clean up the local environment. Will be called exactly once, either >> * after a successful save, or upon encountering an error. >> */ >> @@ -280,6 +288,9 @@ struct xc_sr_context >> /* Read-only mapping of guests shared info page */ >> shared_info_any_t *shinfo; >> >> + /* p2m generation count for verifying validity of local p2m. */ >> + uint64_t p2m_generation; >> + >> union >> { >> struct >> diff --git a/tools/libxc/xc_sr_save.c b/tools/libxc/xc_sr_save.c >> index cefcef5..c235706 100644 >> --- a/tools/libxc/xc_sr_save.c >> +++ b/tools/libxc/xc_sr_save.c >> @@ -370,6 +370,10 @@ static int send_dirty_pages(struct xc_sr_context *ctx, >> DECLARE_HYPERCALL_BUFFER_SHADOW(unsigned long, dirty_bitmap, >> &ctx->save.dirty_bitmap_hbuf); >> >> + rc = ctx->save.ops.check_iteration(ctx); >> + if ( rc ) >> + return rc; >> + > > As there is now a call at each start of checkpoint, this call > essentially becomes back-to-back. I would suggest having it after the > batch, rather than ahead. Okay. > >> for ( p = 0, written = 0; p < ctx->save.p2m_size; ++p ) >> { >> if ( !test_bit(p, dirty_bitmap) ) >> diff --git a/tools/libxc/xc_sr_save_x86_hvm.c >> b/tools/libxc/xc_sr_save_x86_hvm.c >> index f3d6cee..aa24f90 100644 >> --- a/tools/libxc/xc_sr_save_x86_hvm.c >> +++ b/tools/libxc/xc_sr_save_x86_hvm.c >> @@ -175,6 +175,12 @@ static int x86_hvm_start_of_checkpoint(struct >> xc_sr_context *ctx) >> return 0; >> } >> >> +static int x86_hvm_check_iteration(struct xc_sr_context *ctx) >> +{ >> + /* no-op */ >> + return 0; >> +} >> + >> static int x86_hvm_end_of_checkpoint(struct xc_sr_context *ctx) >> { >> int rc; >> @@ -221,6 +227,7 @@ struct xc_sr_save_ops save_ops_x86_hvm = >> .start_of_stream = x86_hvm_start_of_stream, >> .start_of_checkpoint = x86_hvm_start_of_checkpoint, >> .end_of_checkpoint = x86_hvm_end_of_checkpoint, >> + .check_iteration = x86_hvm_check_iteration, >> .cleanup = x86_hvm_cleanup, >> }; >> >> diff --git a/tools/libxc/xc_sr_save_x86_pv.c >> b/tools/libxc/xc_sr_save_x86_pv.c >> index 0237378..3a58d0d 100644 >> --- a/tools/libxc/xc_sr_save_x86_pv.c >> +++ b/tools/libxc/xc_sr_save_x86_pv.c >> @@ -268,6 +268,39 @@ err: >> } >> >> /* >> + * Get p2m_generation count. >> + * Returns an error if the generation count has changed since the last call. >> + */ >> +static int get_p2m_generation(struct xc_sr_context *ctx) >> +{ >> + uint64_t p2m_generation; >> + int rc; >> + >> + p2m_generation = GET_FIELD(ctx->x86_pv.shinfo, arch.p2m_generation, >> + ctx->x86_pv.width); >> + >> + rc = (p2m_generation == ctx->x86_pv.p2m_generation) ? 0 : -1; >> + ctx->x86_pv.p2m_generation = p2m_generation; >> + >> + return rc; >> +} >> + >> +static int x86_pv_check_iteration_p2m_list(struct xc_sr_context *ctx) >> +{ >> + xc_interface *xch = ctx->xch; >> + int rc; >> + >> + if ( !ctx->save.live ) >> + return 0; >> + >> + rc = get_p2m_generation(ctx); >> + if ( rc ) >> + ERROR("p2m generation count changed. Migration aborted."); >> + >> + return rc; >> +} >> + >> +/* >> * Map the guest p2m frames specified via a cr3 value, a virtual address, >> and >> * the maximum pfn. >> */ >> @@ -281,6 +314,9 @@ static int map_p2m_list(struct xc_sr_context *ctx, >> uint64_t p2m_cr3) >> unsigned fpp, n_pages, level, shift, idx_start, idx_end, idx, saved_idx; >> int rc = -1; >> >> + /* Before each iteration check for local p2m list still valid. */ >> + ctx->save.ops.check_iteration = x86_pv_check_iteration_p2m_list; >> + > > This is admittedly the first, but definitely not the only eventual thing > needed for check iteration. To avoid clobbering one check with another > in the future, it would be cleaner to have a single > x86_pv_check_iteration() which performs the get_p2m_generation() check > iff linear p2m is in use. Agreed. Juergen _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |