# HG changeset patch
# User Brendan Cully <brendan@xxxxxxxxx>
# Date 1166166342 28800
# Node ID d39e577379a3375d7340ef265d472f957694d8a0
# Parent dc4d3d58b1d24199101c782a2890b03bfb82fe28
Add new shutdown mode for checkpoint.
When control/shutdown = checkpoint, invoke an alternate suspend path
that doesn't disconnect from back ends, and only reconnects when the
image has been restored into a new domain.
Signed-off-by: Brendan Cully <brendan@xxxxxxxxx>
diff -r dc4d3d58b1d2 -r d39e577379a3
linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c
--- a/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c Thu Dec 14
23:05:42 2006 -0800
+++ b/linux-2.6-xen-sparse/drivers/xen/core/machine_reboot.c Thu Dec 14
23:05:42 2006 -0800
@@ -85,6 +85,20 @@ static void pre_suspend(void)
mfn_to_pfn(xen_start_info->console.domU.mfn);
}
+static void pre_checkpoint(void)
+{
+ xen_start_info->store_mfn = mfn_to_pfn(xen_start_info->store_mfn);
+ xen_start_info->console.domU.mfn =
+ mfn_to_pfn(xen_start_info->console.domU.mfn);
+}
+
+static void post_checkpoint(void)
+{
+ 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);
+}
+
static void post_suspend(void)
{
int i, j, k, fpp;
@@ -183,3 +197,70 @@ int __xen_suspend(void)
return err;
}
+
+int __xen_checkpoint(void)
+{
+ int err;
+
+ extern void time_resume(void);
+
+ BUG_ON(smp_processor_id() != 0);
+ BUG_ON(in_interrupt());
+
+#if defined(__i386__) || defined(__x86_64__)
+ if (xen_feature(XENFEAT_auto_translated_physmap)) {
+ printk(KERN_WARNING "Cannot suspend in "
+ "auto_translated_physmap mode.\n");
+ return -EOPNOTSUPP;
+ }
+#endif
+
+ err = smp_suspend();
+ if (err)
+ return err;
+
+ xenbus_lock();
+
+ preempt_disable();
+
+ mm_pin_all();
+ local_irq_disable();
+ preempt_enable();
+
+ pre_checkpoint();
+
+ /*
+ * We'll stop somewhere inside this hypercall. When it returns,
+ * we'll start resuming after the restore.
+ */
+ err = HYPERVISOR_suspend(virt_to_mfn(xen_start_info));
+
+ if (err) {
+ /* We are resuming in a new domain -- reconnect */
+ post_suspend();
+
+ gnttab_resume();
+
+ irq_resume();
+
+ time_resume();
+
+ switch_idle_mm();
+
+ local_irq_enable();
+
+ xencons_resume();
+
+ xenbus_resume();
+ } else {
+ post_checkpoint();
+
+ local_irq_enable();
+
+ xenbus_unlock();
+ }
+
+ smp_resume();
+
+ return err;
+}
diff -r dc4d3d58b1d2 -r d39e577379a3
linux-2.6-xen-sparse/drivers/xen/core/reboot.c
--- a/linux-2.6-xen-sparse/drivers/xen/core/reboot.c Thu Dec 14 23:05:42
2006 -0800
+++ b/linux-2.6-xen-sparse/drivers/xen/core/reboot.c Thu Dec 14 23:05:42
2006 -0800
@@ -11,15 +11,16 @@
MODULE_LICENSE("Dual BSD/GPL");
-#define SHUTDOWN_INVALID -1
-#define SHUTDOWN_POWEROFF 0
-#define SHUTDOWN_SUSPEND 2
+#define SHUTDOWN_INVALID -1
+#define SHUTDOWN_POWEROFF 0
+#define SHUTDOWN_SUSPEND 2
/* Code 3 is SHUTDOWN_CRASH, which we don't use because the domain can only
* report a crash, not be instructed to crash!
* HALT is the same as POWEROFF, as far as we're concerned. The tools use
* the distinction when we return the reason code to them.
*/
-#define SHUTDOWN_HALT 4
+#define SHUTDOWN_HALT 4
+#define SHUTDOWN_CHECKPOINT 5
/* Ignore multiple shutdown requests. */
static int shutting_down = SHUTDOWN_INVALID;
@@ -29,8 +30,10 @@ static DECLARE_WORK(shutdown_work, __shu
#ifdef CONFIG_XEN
int __xen_suspend(void);
+int __xen_checkpoint(void);
#else
#define __xen_suspend() (void)0
+#define __xen_checkpoint() (void)0
#endif
static int shutdown_process(void *__unused)
@@ -61,7 +64,10 @@ static int shutdown_process(void *__unus
static int xen_suspend(void *__unused)
{
- __xen_suspend();
+ if (shutting_down == SHUTDOWN_CHECKPOINT)
+ __xen_checkpoint();
+ else
+ __xen_suspend();
shutting_down = SHUTDOWN_INVALID;
return 0;
}
@@ -84,7 +90,8 @@ static void __shutdown_handler(void *unu
{
int err;
- if (shutting_down != SHUTDOWN_SUSPEND)
+ if (shutting_down != SHUTDOWN_SUSPEND
+ && shutting_down != SHUTDOWN_CHECKPOINT)
err = kernel_thread(shutdown_process, NULL,
CLONE_FS | CLONE_FILES);
else
@@ -132,6 +139,8 @@ static void shutdown_handler(struct xenb
kill_proc(1, SIGINT, 1); /* interrupt init */
else if (strcmp(str, "suspend") == 0)
shutting_down = SHUTDOWN_SUSPEND;
+ else if (strcmp(str, "checkpoint") == 0)
+ shutting_down = SHUTDOWN_CHECKPOINT;
else if (strcmp(str, "halt") == 0)
shutting_down = SHUTDOWN_HALT;
else {
diff -r dc4d3d58b1d2 -r d39e577379a3
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Thu Dec 14
23:05:42 2006 -0800
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_probe.c Thu Dec 14
23:05:42 2006 -0800
@@ -727,6 +727,18 @@ void xenbus_suspend(void)
}
EXPORT_SYMBOL_GPL(xenbus_suspend);
+void xenbus_lock(void)
+{
+ xs_lock();
+}
+EXPORT_SYMBOL_GPL(xenbus_lock);
+
+void xenbus_unlock(void)
+{
+ xs_unlock();
+}
+EXPORT_SYMBOL_GPL(xenbus_unlock);
+
void xenbus_resume(void)
{
xb_init_comms();
diff -r dc4d3d58b1d2 -r d39e577379a3
linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c
--- a/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c Thu Dec 14
23:05:42 2006 -0800
+++ b/linux-2.6-xen-sparse/drivers/xen/xenbus/xenbus_xs.c Thu Dec 14
23:05:42 2006 -0800
@@ -666,6 +666,18 @@ void unregister_xenbus_watch(struct xenb
}
EXPORT_SYMBOL_GPL(unregister_xenbus_watch);
+void xs_lock(void)
+{
+ down_write(&xs_state.suspend_mutex);
+ mutex_lock(&xs_state.request_mutex);
+}
+
+void xs_unlock(void)
+{
+ mutex_unlock(&xs_state.request_mutex);
+ up_write(&xs_state.suspend_mutex);
+}
+
void xs_suspend(void)
{
struct xenbus_watch *watch;
diff -r dc4d3d58b1d2 -r d39e577379a3 linux-2.6-xen-sparse/include/xen/xenbus.h
--- a/linux-2.6-xen-sparse/include/xen/xenbus.h Thu Dec 14 23:05:42 2006 -0800
+++ b/linux-2.6-xen-sparse/include/xen/xenbus.h Thu Dec 14 23:05:42 2006 -0800
@@ -158,6 +158,8 @@ void unregister_xenstore_notifier(struct
int register_xenbus_watch(struct xenbus_watch *watch);
void unregister_xenbus_watch(struct xenbus_watch *watch);
+void xs_lock(void);
+void xs_unlock(void);
void xs_suspend(void);
void xs_resume(void);
@@ -167,6 +169,8 @@ void *xenbus_dev_request_and_reply(struc
/* Called from xen core code. */
void xenbus_suspend(void);
void xenbus_resume(void);
+void xenbus_lock(void);
+void xenbus_unlock(void);
#define XENBUS_IS_ERR_READ(str) ({ \
if (!IS_ERR(str) && strlen(str) == 0) { \
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel
|