diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2009-03-24 06:55:29 +0000 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2009-03-24 06:55:29 +0000 |
commit | 92f5c346e70b04742d84485579228a6d60c8e543 (patch) | |
tree | d3782f73ed9ae4b7ae1c3ab5f9684eae41e2fa1f /tools/libxc/xc_suspend.c | |
parent | e8c21780e35f5fd0a6860458282e89a81a8d33f1 (diff) | |
download | xen-92f5c346e70b04742d84485579228a6d60c8e543.tar.gz xen-92f5c346e70b04742d84485579228a6d60c8e543.tar.bz2 xen-92f5c346e70b04742d84485579228a6d60c8e543.zip |
libxc: fix link error of xc_save on ia64
The suspend event channel functions are arch independent code
which xc_save uses.
The changeset of 19382:a5f497f02e34 cause link error on ia64.
This patch moves the functions into arch common file from
x86 specific file xc_domain_save.c
Signed-off-by: Isaku Yamahata <yamahata@valinux.co.jp>
Diffstat (limited to 'tools/libxc/xc_suspend.c')
-rw-r--r-- | tools/libxc/xc_suspend.c | 117 |
1 files changed, 117 insertions, 0 deletions
diff --git a/tools/libxc/xc_suspend.c b/tools/libxc/xc_suspend.c new file mode 100644 index 0000000000..c0ab75762d --- /dev/null +++ b/tools/libxc/xc_suspend.c @@ -0,0 +1,117 @@ +/* + * This file is subject to the terms and conditions of the GNU General + * Public License. See the file "COPYING" in the main directory of + * this archive for more details. + */ + +#include "xc_private.h" +#include "xenguest.h" + +#define SUSPEND_LOCK_FILE "/var/lib/xen/suspend_evtchn_lock.d" +static int lock_suspend_event(void) +{ + int fd, rc; + 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()); + + rc = write_exact(fd, buf, strlen(buf)); + close(fd); + + return rc; +} + +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; +} |