[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-changelog] [xen-unstable] Move the suspend event channel function to libxc, it will use the



# 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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.