# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1237376966 0
# Node ID a5f497f02e344d92a28c9a170749a83689d94808
# Parent f00e5d83b9ecb5ba9be48ec53bd7536fe85118bf
Move the suspend event channel function to libxc, it will use the
/var/lib/xen/suspend_evtchn_lock.d to protect the access.
Signed-off-by: Jiang Yunhong <yunhong.jiang@xxxxxxxxx>
---
tools/libxc/xc_domain_save.c | 109 ++++++++++++++++++++++++++++++++++++++++
tools/libxc/xenguest.h | 6 ++
tools/xcutils/xc_save.c | 116 +++++++++----------------------------------
tools/xenstore/xs.c | 25 +++++++++
tools/xenstore/xs.h | 1
5 files changed, 166 insertions(+), 91 deletions(-)
diff -r f00e5d83b9ec -r a5f497f02e34 tools/libxc/xc_domain_save.c
--- a/tools/libxc/xc_domain_save.c Wed Mar 18 11:48:48 2009 +0000
+++ b/tools/libxc/xc_domain_save.c Wed Mar 18 11:49:26 2009 +0000
@@ -744,7 +744,114 @@ static xen_pfn_t *map_and_save_p2m_table
return success ? p2m : NULL;
}
-
+#define SUSPEND_LOCK_FILE "/var/lib/xen/suspend_evtchn_lock.d"
+static int lock_suspend_event(void)
+{
+ int fd;
+ mode_t mask;
+ char buf[128];
+
+ mask = umask(022);
+ fd = open(SUSPEND_LOCK_FILE, O_CREAT | O_EXCL | O_RDWR, 0666);
+ if (fd < 0)
+ {
+ ERROR("Can't create lock file for suspend event channel\n");
+ return -EINVAL;
+ }
+ umask(mask);
+ snprintf(buf, sizeof(buf), "%10ld", (long)getpid());
+
+ write(fd, buf, strlen(buf));
+ close(fd);
+
+ return 0;
+}
+
+static int unlock_suspend_event(void)
+{
+ int fd, pid, n;
+ char buf[128];
+
+ fd = open(SUSPEND_LOCK_FILE, O_RDWR);
+
+ if (fd < 0)
+ return -EINVAL;
+
+ n = read(fd, buf, 127);
+
+ close(fd);
+
+ if (n > 0)
+ {
+ sscanf(buf, "%d", &pid);
+ /* We are the owner, so we can simply delete the file */
+ if (pid == getpid())
+ {
+ unlink(SUSPEND_LOCK_FILE);
+ return 0;
+ }
+ }
+
+ return -EPERM;
+}
+
+int xc_await_suspend(int xce, int suspend_evtchn)
+{
+ int rc;
+
+ do {
+ rc = xc_evtchn_pending(xce);
+ if (rc < 0) {
+ ERROR("error polling suspend notification channel: %d", rc);
+ return -1;
+ }
+ } while (rc != suspend_evtchn);
+
+ /* harmless for one-off suspend */
+ if (xc_evtchn_unmask(xce, suspend_evtchn) < 0)
+ ERROR("failed to unmask suspend notification channel: %d", rc);
+
+ return 0;
+}
+
+int xc_suspend_evtchn_release(int xce, int suspend_evtchn)
+{
+ if (suspend_evtchn >= 0)
+ xc_evtchn_unbind(xce, suspend_evtchn);
+
+ return unlock_suspend_event();
+}
+
+int xc_suspend_evtchn_init(int xc, int xce, int domid, int port)
+{
+ int rc, suspend_evtchn = -1;
+
+ if (lock_suspend_event())
+ return -EINVAL;
+
+ suspend_evtchn = xc_evtchn_bind_interdomain(xce, domid, port);
+ if (suspend_evtchn < 0) {
+ ERROR("failed to bind suspend event channel: %d", suspend_evtchn);
+ goto cleanup;
+ }
+
+ rc = xc_domain_subscribe_for_suspend(xc, domid, port);
+ if (rc < 0) {
+ ERROR("failed to subscribe to domain: %d", rc);
+ goto cleanup;
+ }
+
+ /* event channel is pending immediately after binding */
+ xc_await_suspend(xce, suspend_evtchn);
+
+ return suspend_evtchn;
+
+cleanup:
+ if (suspend_evtchn > 0)
+ xc_suspend_evtchn_release(xce, suspend_evtchn);
+
+ return -1;
+}
int xc_domain_save(int xc_handle, int io_fd, uint32_t dom, uint32_t max_iters,
uint32_t max_factor, uint32_t flags, int (*suspend)(void),
diff -r f00e5d83b9ec -r a5f497f02e34 tools/libxc/xenguest.h
--- a/tools/libxc/xenguest.h Wed Mar 18 11:48:48 2009 +0000
+++ b/tools/libxc/xenguest.h Wed Mar 18 11:49:26 2009 +0000
@@ -142,4 +142,10 @@ int xc_hvm_build_mem(int xc_handle,
const char *image_buffer,
unsigned long image_size);
+int xc_suspend_evtchn_release(int xce, int suspend_evtchn);
+
+int xc_suspend_evtchn_init(int xc, int xce, int domid, int port);
+
+int xc_await_suspend(int xce, int suspend_evtchn);
+
#endif /* XENGUEST_H */
diff -r f00e5d83b9ec -r a5f497f02e34 tools/xcutils/xc_save.c
--- a/tools/xcutils/xc_save.c Wed Mar 18 11:48:48 2009 +0000
+++ b/tools/xcutils/xc_save.c Wed Mar 18 11:49:26 2009 +0000
@@ -46,83 +46,6 @@ static int compat_suspend(void)
!strncmp(ans, "done\n", 5));
}
-static int suspend_evtchn_release(int xce, int suspend_evtchn)
-{
- if (suspend_evtchn >= 0)
- xc_evtchn_unbind(xce, suspend_evtchn);
-
- return 0;
-}
-
-static int await_suspend(int xce, int suspend_evtchn)
-{
- int rc;
-
- do {
- rc = xc_evtchn_pending(xce);
- if (rc < 0) {
- warnx("error polling suspend notification channel: %d", rc);
- return -1;
- }
- } while (rc != suspend_evtchn);
-
- /* harmless for one-off suspend */
- if (xc_evtchn_unmask(xce, suspend_evtchn) < 0)
- warnx("failed to unmask suspend notification channel: %d", rc);
-
- return 0;
-}
-
-static int suspend_evtchn_init(int xc, int xce, int domid)
-{
- struct xs_handle *xs;
- char path[128];
- char *portstr;
- unsigned int plen;
- int port;
- int rc, suspend_evtchn = -1;
-
- xs = xs_daemon_open();
- if (!xs) {
- warnx("failed to get xenstore handle");
- return -1;
- }
- sprintf(path, "/local/domain/%d/device/suspend/event-channel", domid);
- portstr = xs_read(xs, XBT_NULL, path, &plen);
- xs_daemon_close(xs);
-
- if (!portstr || !plen) {
- warnx("could not read suspend event channel");
- return -1;
- }
-
- port = atoi(portstr);
- free(portstr);
-
- suspend_evtchn = xc_evtchn_bind_interdomain(xce, domid, port);
- if (suspend_evtchn < 0) {
- warnx("failed to bind suspend event channel: %d", si.suspend_evtchn);
- goto cleanup;
- }
-
- rc = xc_domain_subscribe_for_suspend(xc, domid, port);
- if (rc < 0) {
- warnx("failed to subscribe to domain: %d", rc);
- goto cleanup;
- }
-
- /* event channel is pending immediately after binding */
- await_suspend(xce, suspend_evtchn);
-
- return suspend_evtchn;
-
-cleanup:
- if (suspend_evtchn > 0)
- suspend_evtchn_release(xce, suspend_evtchn);
-
- return -1;
-}
-
/**
* Issue a suspend request to a dedicated event channel in the guest, and
* receive the acknowledgement from the subscribe event channel. */
@@ -136,7 +59,7 @@ static int evtchn_suspend(void)
return 0;
}
- if (await_suspend(si.xce, si.suspend_evtchn) < 0) {
+ if (xc_await_suspend(si.xce, si.suspend_evtchn) < 0) {
warnx("suspend failed");
return 0;
}
@@ -289,12 +212,11 @@ static void *init_qemu_maps(int domid, u
return seg;
}
-
int
main(int argc, char **argv)
{
unsigned int maxit, max_f;
- int io_fd, ret;
+ int io_fd, ret, port;
if (argc != 6)
errx(1, "usage: %s iofd domid maxit maxf flags", argv[0]);
@@ -309,23 +231,37 @@ main(int argc, char **argv)
max_f = atoi(argv[4]);
si.flags = atoi(argv[5]);
+ si.suspend_evtchn = si.xce = -1;
si.xce = xc_evtchn_open();
if (si.xce < 0)
- errx(1, "failed to open event channel handle");
-
- si.suspend_evtchn = suspend_evtchn_init(si.xc_fd, si.xce, si.domid);
-
- if (si.suspend_evtchn < 0)
- warnx("suspend event channel initialization failed, using slow path");
-
+ warnx("failed to open event channel handle");
+
+ if (si.xce > 0)
+ {
+ port = xs_suspend_evtchn_port(si.domid);
+
+ if (port < 0)
+ warnx("faield to get the suspend evtchn port\n");
+ else
+ {
+ si.suspend_evtchn =
+ xc_suspend_evtchn_init(si.xc_fd, si.xce, si.domid, port);
+
+ if (si.suspend_evtchn < 0)
+ warnx("suspend event channel initialization failed"
+ "using slow path");
+ }
+ }
ret = xc_domain_save(si.xc_fd, io_fd, si.domid, maxit, max_f, si.flags,
&suspend, !!(si.flags & XCFLAGS_HVM),
&init_qemu_maps, &qemu_flip_buffer);
- suspend_evtchn_release(si.xce, si.suspend_evtchn);
-
- xc_evtchn_close(si.xce);
+ if (si.suspend_evtchn > 0)
+ xc_suspend_evtchn_release(si.xce, si.suspend_evtchn);
+
+ if (si.xce > 0)
+ xc_evtchn_close(si.xce);
xc_interface_close(si.xc_fd);
diff -r f00e5d83b9ec -r a5f497f02e34 tools/xenstore/xs.c
--- a/tools/xenstore/xs.c Wed Mar 18 11:48:48 2009 +0000
+++ b/tools/xenstore/xs.c Wed Mar 18 11:49:26 2009 +0000
@@ -802,6 +802,31 @@ bool xs_is_domain_introduced(struct xs_h
return rc;
}
+int xs_suspend_evtchn_port(int domid)
+{
+ char path[128];
+ char *portstr;
+ int port;
+ unsigned int plen;
+ struct xs_handle *xs;
+
+ xs = xs_daemon_open();
+ if (!xs)
+ return -1;
+
+ sprintf(path, "/local/domain/%d/device/suspend/event-channel", domid);
+ portstr = xs_read(xs, XBT_NULL, path, &plen);
+ xs_daemon_close(xs);
+
+ if (!portstr || !plen)
+ return -1;
+
+ port = atoi(portstr);
+ free(portstr);
+
+ return port;
+}
+
/* Only useful for DEBUG versions */
char *xs_debug_command(struct xs_handle *h, const char *cmd,
void *data, unsigned int len)
diff -r f00e5d83b9ec -r a5f497f02e34 tools/xenstore/xs.h
--- a/tools/xenstore/xs.h Wed Mar 18 11:48:48 2009 +0000
+++ b/tools/xenstore/xs.h Wed Mar 18 11:49:26 2009 +0000
@@ -163,6 +163,7 @@ char *xs_debug_command(struct xs_handle
char *xs_debug_command(struct xs_handle *h, const char *cmd,
void *data, unsigned int len);
+int xs_suspend_evtchn_port(int domid);
#endif /* _XS_H */
/*
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|