From 931818cacb428305d95a131ba40bfa92df4b1c39 Mon Sep 17 00:00:00 2001 From: "kfraser@localhost.localdomain" Date: Fri, 19 Jan 2007 16:06:09 +0000 Subject: [PATCH] Make xen_suspend handle resume. Don't destroy xenstore watches on suspend, and only recreate them when resuming in a new domain. Likewise, only invoke frontend device resume code when in a new domain (the resume functions all tear down the existing function and wait for the backend to negotiate a new one, which does not happen in the source domain). Signed-off-by: Brendan Cully Signed-off-by: Keir Fraser --- .../drivers/xen/core/machine_reboot.c | 33 ++++++++++++------- .../drivers/xen/xenbus/xenbus_probe.c | 5 +++ .../drivers/xen/xenbus/xenbus_xs.c | 16 ++++----- linux-2.6-xen-sparse/include/xen/xenbus.h | 4 ++- 4 files changed, 36 insertions(+), 22 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c b/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c index 02ee7f4728..b69efd61f9 100644 --- a/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c +++ b/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c @@ -85,13 +85,20 @@ static void pre_suspend(void) mfn_to_pfn(xen_start_info->console.domU.mfn); } -static void post_suspend(void) +static void post_suspend(int suspend_cancelled) { int i, j, k, fpp; extern unsigned long max_pfn; extern unsigned long *pfn_to_mfn_frame_list_list; extern unsigned long *pfn_to_mfn_frame_list[]; + if (suspend_cancelled) { + xen_start_info->store_mfn = + pfn_to_mfn(xen_start_info->store_mfn); + xen_start_info->console.domU.mfn = + pfn_to_mfn(xen_start_info->console.domU.mfn); + } + set_fixmap(FIX_SHARED_INFO, xen_start_info->shared_info); HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO); @@ -120,13 +127,13 @@ static void post_suspend(void) #define switch_idle_mm() ((void)0) #define mm_pin_all() ((void)0) #define pre_suspend() ((void)0) -#define post_suspend() ((void)0) +#define post_suspend(x) ((void)0) #endif int __xen_suspend(void) { - int err; + int err, suspend_cancelled; extern void time_resume(void); @@ -158,16 +165,17 @@ int __xen_suspend(void) pre_suspend(); /* - * We'll stop somewhere inside this hypercall. When it returns, - * we'll start resuming after the restore. + * This hypercall returns 1 if suspend was cancelled or the domain was + * merely checkpointed, and 0 if it is resuming in a new domain. */ - HYPERVISOR_suspend(virt_to_mfn(xen_start_info)); + suspend_cancelled = HYPERVISOR_suspend(virt_to_mfn(xen_start_info)); - post_suspend(); + post_suspend(suspend_cancelled); gnttab_resume(); - irq_resume(); + if (!suspend_cancelled) + irq_resume(); time_resume(); @@ -175,9 +183,12 @@ int __xen_suspend(void) local_irq_enable(); - xencons_resume(); - - xenbus_resume(); + if (!suspend_cancelled) { + xencons_resume(); + xenbus_resume(); + } else { + xenbus_suspend_cancel(); + } smp_resume(); diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c index eee22afbb8..e099114abc 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c @@ -736,6 +736,11 @@ void xenbus_resume(void) } EXPORT_SYMBOL_GPL(xenbus_resume); +void xenbus_suspend_cancel(void) +{ + xs_suspend_cancel(); +} +EXPORT_SYMBOL_GPL(xenbus_suspend_cancel); /* A flag to determine if xenstored is 'ready' (i.e. has started) */ int xenstored_ready = 0; diff --git a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c index 4c5052d13a..23b99b86f5 100644 --- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c +++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c @@ -668,17 +668,7 @@ EXPORT_SYMBOL_GPL(unregister_xenbus_watch); void xs_suspend(void) { - struct xenbus_watch *watch; - char token[sizeof(watch) * 2 + 1]; - down_write(&xs_state.suspend_mutex); - - /* No need for watches_lock: the suspend_mutex is sufficient. */ - list_for_each_entry(watch, &watches, list) { - sprintf(token, "%lX", (long)watch); - xs_unwatch(watch->node, token); - } - mutex_lock(&xs_state.request_mutex); } @@ -698,6 +688,12 @@ void xs_resume(void) up_write(&xs_state.suspend_mutex); } +void xs_suspend_cancel(void) +{ + mutex_unlock(&xs_state.request_mutex); + up_write(&xs_state.suspend_mutex); +} + static int xenwatch_handle_callback(void *data) { struct xs_stored_msg *msg = data; diff --git a/linux-2.6-xen-sparse/include/xen/xenbus.h b/linux-2.6-xen-sparse/include/xen/xenbus.h index 3f525fa2dd..72eb9224ac 100644 --- a/linux-2.6-xen-sparse/include/xen/xenbus.h +++ b/linux-2.6-xen-sparse/include/xen/xenbus.h @@ -160,13 +160,15 @@ int register_xenbus_watch(struct xenbus_watch *watch); void unregister_xenbus_watch(struct xenbus_watch *watch); void xs_suspend(void); void xs_resume(void); +void xs_suspend_cancel(void); /* Used by xenbus_dev to borrow kernel's store connection. */ void *xenbus_dev_request_and_reply(struct xsd_sockmsg *msg); -/* Called from xen core code. */ +/* Prepare for domain suspend: then resume or cancel the suspend. */ void xenbus_suspend(void); void xenbus_resume(void); +void xenbus_suspend_cancel(void); #define XENBUS_IS_ERR_READ(str) ({ \ if (!IS_ERR(str) && strlen(str) == 0) { \ -- 2.30.2