~ubuntu-branches/ubuntu/utopic/xen/utopic

« back to all changes in this revision

Viewing changes to tools/libxc/xc_suspend.c

  • Committer: Bazaar Package Importer
  • Author(s): Bastian Blank
  • Date: 2010-05-06 15:47:38 UTC
  • mto: (1.3.1) (15.1.1 sid) (4.1.1 experimental)
  • mto: This revision was merged to the branch mainline in revision 3.
  • Revision ID: james.westby@ubuntu.com-20100506154738-agoz0rlafrh1fnq7
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This file is subject to the terms and conditions of the GNU General
 
3
 * Public License.  See the file "COPYING" in the main directory of
 
4
 * this archive for more details.
 
5
 */
 
6
 
 
7
#include "xc_private.h"
 
8
#include "xenguest.h"
 
9
 
 
10
#define SUSPEND_LOCK_FILE "/var/lib/xen/suspend_evtchn_lock.d"
 
11
static int lock_suspend_event(void)
 
12
{
 
13
    int fd, rc;
 
14
    mode_t mask;
 
15
    char buf[128];
 
16
 
 
17
    mask = umask(022);
 
18
    fd = open(SUSPEND_LOCK_FILE, O_CREAT | O_EXCL | O_RDWR, 0666);
 
19
    if (fd < 0)
 
20
    {
 
21
        ERROR("Can't create lock file for suspend event channel\n");
 
22
        return -EINVAL;
 
23
    }
 
24
    umask(mask);
 
25
    snprintf(buf, sizeof(buf), "%10ld", (long)getpid());
 
26
 
 
27
    rc = write_exact(fd, buf, strlen(buf));
 
28
    close(fd);
 
29
 
 
30
    return rc;
 
31
}
 
32
 
 
33
static int unlock_suspend_event(void)
 
34
{
 
35
    int fd, pid, n;
 
36
    char buf[128];
 
37
 
 
38
    fd = open(SUSPEND_LOCK_FILE, O_RDWR);
 
39
 
 
40
    if (fd < 0)
 
41
        return -EINVAL;
 
42
 
 
43
    n = read(fd, buf, 127);
 
44
 
 
45
    close(fd);
 
46
 
 
47
    if (n > 0)
 
48
    {
 
49
        sscanf(buf, "%d", &pid);
 
50
        /* We are the owner, so we can simply delete the file */
 
51
        if (pid == getpid())
 
52
        {
 
53
            unlink(SUSPEND_LOCK_FILE);
 
54
            return 0;
 
55
        }
 
56
    }
 
57
 
 
58
    return -EPERM;
 
59
}
 
60
 
 
61
int xc_await_suspend(int xce, int suspend_evtchn)
 
62
{
 
63
    int rc;
 
64
 
 
65
    do {
 
66
        rc = xc_evtchn_pending(xce);
 
67
        if (rc < 0) {
 
68
            ERROR("error polling suspend notification channel: %d", rc);
 
69
            return -1;
 
70
        }
 
71
    } while (rc != suspend_evtchn);
 
72
 
 
73
    /* harmless for one-off suspend */
 
74
    if (xc_evtchn_unmask(xce, suspend_evtchn) < 0)
 
75
        ERROR("failed to unmask suspend notification channel: %d", rc);
 
76
 
 
77
    return 0;
 
78
}
 
79
 
 
80
int xc_suspend_evtchn_release(int xce, int suspend_evtchn)
 
81
{
 
82
    if (suspend_evtchn >= 0)
 
83
        xc_evtchn_unbind(xce, suspend_evtchn);
 
84
 
 
85
    return unlock_suspend_event();
 
86
}
 
87
 
 
88
int xc_suspend_evtchn_init(int xc, int xce, int domid, int port)
 
89
{
 
90
    int rc, suspend_evtchn = -1;
 
91
 
 
92
    if (lock_suspend_event())
 
93
        return -EINVAL;
 
94
 
 
95
    suspend_evtchn = xc_evtchn_bind_interdomain(xce, domid, port);
 
96
    if (suspend_evtchn < 0) {
 
97
        ERROR("failed to bind suspend event channel: %d", suspend_evtchn);
 
98
        goto cleanup;
 
99
    }
 
100
 
 
101
    rc = xc_domain_subscribe_for_suspend(xc, domid, port);
 
102
    if (rc < 0) {
 
103
        ERROR("failed to subscribe to domain: %d", rc);
 
104
        goto cleanup;
 
105
    }
 
106
 
 
107
    /* event channel is pending immediately after binding */
 
108
    xc_await_suspend(xce, suspend_evtchn);
 
109
 
 
110
    return suspend_evtchn;
 
111
 
 
112
cleanup:
 
113
    if (suspend_evtchn != -1)
 
114
        xc_suspend_evtchn_release(xce, suspend_evtchn);
 
115
 
 
116
    return -1;
 
117
}